├── LICENSE ├── Quantumult ├── wangyiyun │ ├── README.md │ ├── cookie_wyy.js │ ├── icon.png │ ├── img │ │ ├── ceshi │ │ ├── 复制cookie.png │ │ ├── 新建云函数1.png │ │ ├── 格式化ck.png │ │ ├── 源码下载.png │ │ ├── 目录展示1.png │ │ ├── 目录展示2.png │ │ └── 通知配置.png │ ├── wyy_config.js │ └── wyy_yyr.js └── wozaixiaoyuan │ ├── cookie_wzxy.js │ ├── icon.jpg │ ├── wzxy_health.js │ └── wzxy_leave.js ├── README.md ├── alpay.jpg ├── boxjs └── laoxin.boxjs.json └── sendNotify.js /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 | . 675 | -------------------------------------------------------------------------------- /Quantumult/wangyiyun/README.md: -------------------------------------------------------------------------------- 1 | ## 🎵网易云音乐腾讯云函数教程(弃用) 2 | **新版教程 [云函数教程](https://www.laoxin.top/index.php/2022/04/04/ncmusiciancloud/)** 3 | **[Quantumult教程](https://www.laoxin.top/index.php/2022/04/04/ncmusicianqx/)** 4 | #### 目前仓库发布仅有网易云音乐人任务脚本,后续将会发布更多脚本(如果有什么有趣的脚本需要编写请提交[Issues](https://github.com/laoxinH/MyScript/issues)) 5 | #### 感谢支持和建议,欢迎[打赏](https://github.com/laoxinH/MyScript#赞赏码开发维护不易请赏杯茶水费) 6 | >目前完成的功能,简单说明一下,任务都是周任务,像发布动态回复评论这种任务不会一次性执行完。跑一次脚本执行一次。所以别问为啥没执行完 7 | 8 | - [x] 多账号支持 9 | - [x] 每日登录 10 | - [x] 发布动态 11 | - [x] 回复私信 12 | - [x] 回复评论 13 | - [x] 发主创说 14 | - [x] 访问云圈 15 | ---------- 16 | 17 | ### 1.下载依赖和脚本代码 18 | 19 | 20 | - [点击下载依赖](https://github.com/laoxinH/MyScript/releases/download/node.js/node_modules.zip)(下载后的文件名:node_modules.zip) 21 | - [前往下载脚本](https://github.com/laoxinH/MyScript)*下载方式参考下图*(下载后的文件名:MyScript-main.zip) 22 | ![code.png](https://github.com/laoxinH/MyScript/blob/main/Quantumult/wangyiyun/img/%E6%BA%90%E7%A0%81%E4%B8%8B%E8%BD%BD.png?raw=true) 23 | 24 | ### 2.建立脚本目录 25 | 1. 找一个位置建立script文件夹*(文件夹名字随意)* 26 | 2. 将之前下载的依赖解压到新建的文件夹 27 | 3. 将下载的脚本解压,找到**sendNotify.js** | **wyy_config.js** | **wyy_yyr.js** 28 | 29 | > sendNotify.js---发送通知的脚本(位置:你解压的目录/sendNotify.js)
30 | > wyy_config.js---网易云配置文件(位置:你解压的目录/Quantumult/wangyiyun/wyy_config.js)
31 | > wyy_yyr.js---网易云音乐人任务脚本(位置:你解压的目录/Quantumult/wangyiyun/wyy_yyr.js)
32 | 33 | ![code1.png](https://github.com/laoxinH/MyScript/blob/main/Quantumult/wangyiyun/img/%E7%9B%AE%E5%BD%95%E5%B1%95%E7%A4%BA1.png?raw=true) 34 | ### 3.建立index.js并抓取cookie(账号登录已修复可以通过账号登录跳过抓取cookie) 35 | #### 同时复制浏览器的UA备用 36 | 1. 在上面的script目录新建index.js文件并添加以下代码(使用自带的文本编辑器即可) 37 | 38 | exports.main_handler = async (event, context, callback) => { 39 | // 解决云函数热启动问题 40 | // 以后需要添加其他脚本也在需要此添加以下两行代码才能执行 41 | // delete require.cache[require.resolve('./你需要的脚本.js')]; 42 | // require('./你需要的脚本.js'); 43 | // 注意“./”是必不可少的 44 | delete require.cache[require.resolve('./wyy_yyr.js')]; 45 | require('./wyy_yyr.js'); //这里写你想要的脚本 46 | } 47 | **账号登录(若账号登录存在问题请使用cookie登录)** 48 | > 账号登录已修复
49 | > 在laoxinH_config.js中填写即可(将第5步的粘贴cookie改为填写电话和密码)
50 | > 若使用账号密码登录直接跳过获取cookie(获取cookie对应本部分的2,3,4步)
51 | > 下面为修改好的示例代码
52 | > 多账号参考账号1和脚本注释填写即可 53 | 54 | 55 | module.exports = { 56 | // 网易云相关配置 57 | wangyi: { 58 | // 不填写则使用默认回复 59 | shareMsg: "", // 发送动态的文字内容 60 | commentMsg: "", // 主创说评论内容 61 | reMsg: "", // 私信内容 62 | reCommentMsg: "", // 回复评论内容 63 | users: [ 64 | { 65 | // 账号一 66 | // 说明: 若填写cookie将直接通过cookie登录,电话号码登录将会失效(优先级:cookie > 电话登录) 67 | // 因此cookie 和 电话二选一即可 68 | // 账号密码登录可能有问题,原因异地登陆,若出现问题请使用cookie登录 69 | cookie: "", 70 | // 建议填写最简cookie:MUSIC_U=xxxxx; __csrf=xxxxxx; 71 | // 电话登录配置 72 | phone: "188888888888", // 电话号码 73 | password: "qweerrttt", // 密码 74 | UA:"你的浏览器UA" 75 | }, 76 | { 77 | // 账号二 78 | cookie: "", 79 | phone: "", 80 | password: "", 81 | UA:"你的浏览器UA" 82 | } 83 | /** 84 | * 若需要添加更多账号请自行添加以下内容,注意每一个{}之间有英文逗号“,”分割 85 | { 86 | cookie: "", 87 | phone: "", 88 | password: "", 89 | UA:"你的浏览器UA" 90 | } 91 | */ 92 | ] 93 | } 94 | } 95 | 96 | **在wyy_config.js填写好点账号密码后[击跳过获取cookie](#zuizhong)** 97 | 98 | **以下为通过cookie方式登录(推荐)** 99 | 100 | 2. 前往[网易云音乐(点击直达)](https://music.163.com)获取cookie(推荐使用edge或者chrome浏览器) 101 | 3. 登录后按F12打开复制cookie(以chrome为例) 102 | ![cookie](https://github.com/laoxinH/MyScript/blob/main/Quantumult/wangyiyun/img/%E5%A4%8D%E5%88%B6cookie.png?raw=true) 103 | 4. 切换到控制台(Console)格式化为最简cookie 104 | > 通过执行以下代码格式化cookie 105 | 106 | var CV = '单引号里面放拿到的完整cookie'; 107 | var CookieValue = CV.match(/MUSIC_U=.+?;/) + CV.match(/__csrf=.+?;/); 108 | copy(CookieValue); 109 | 110 | > 建议复制一行执行一行代码(粘贴到控制台后回车执行)
111 | > 详细参考下图
112 | > 格式化后的cookie格式为MUSIC_U=xxxx;__csrf=xxxx;
113 | > 示例:MUSIC_U=2da45fadcea83dbe492669abdc6c26c4a1e1d6db309b58b6853993166e004087dd3d78b6050a17a35e705925a4e6992f61dfe3f0151024f9e31;__csrf=a43e6551fb5b7978040b5b463b20; 114 | 115 | ![格式化ck](https://github.com/laoxinH/MyScript/blob/main/Quantumult/wangyiyun/img/%E6%A0%BC%E5%BC%8F%E5%8C%96ck.png?raw=true) 116 | 5. 将格式化后的cookie粘贴到laoxinH_config.js文件的对应位置 117 | > 粘贴后代码示例如下
118 | > 多账号参考账号1和脚本注释填写即可 119 | 120 | module.exports = { 121 | // 网易云相关配置 122 | wangyi: { 123 | // 不填写则使用默认回复 124 | shareMsg: "", // 发送动态的文字内容 125 | commentMsg: "", // 主创说评论内容 126 | reMsg: "", // 私信内容 127 | reCommentMsg: "", // 回复评论内容 128 | users: [ 129 | { 130 | // 账号一 131 | // 说明: 若填写cookie将直接通过cookie登录,电话号码登录将会失效(优先级:cookie > 电话登录) 132 | // 因此cookie 和 电话二选一即可 133 | // 账号密码登录可能有问题,原因异地登陆,若出现问题请使用cookie登录 134 | cookie: "MUSIC_U=2da45fadcea83dbe492669abdc6c26c4a1e1d6db309b58b688403539931004087dd3d78b6050a17a35e705925a4e6992f61dfe3f0151024f9e31;__csrf=a43e6551fb5b7978040b5b463b20;", 135 | // 请填写最简cookie:MUSIC_U=xxxxx; __csrf=xxxxxx; 136 | // 电话登录配置 137 | phone: "", // 电话号码 138 | password: "", // 密码 139 | UA:"你的浏览器UA" 140 | }, 141 | { 142 | // 账号二 143 | cookie: "", 144 | phone: "", 145 | password: "", 146 | UA:"你的浏览器UA" 147 | } 148 | /** 149 | * 若需要添加更多账号请自行添加以下内容,注意每一个{}之间有英文逗号“,”分割 150 | { 151 | cookie: "", 152 | phone: "", 153 | password: "", 154 | UA:"你的浏览器UA" 155 | } 156 | */ 157 | ] 158 | } 159 | } 160 | 161 | 162 | >最终目录展示 163 | 164 | ![最终目录](https://github.com/laoxinH/MyScript/blob/main/Quantumult/wangyiyun/img/%E7%9B%AE%E5%BD%95%E5%B1%95%E7%A4%BA2.png?raw=true) 165 | 166 | ### 4.登录腾讯云函数上传代码 167 | 1. [点击前往](https://console.cloud.tencent.com/scf)腾讯云函数 168 | 2. 选择 函数服务>>新建 169 | > 参考下图 170 | 171 | ![新建云函数](https://github.com/laoxinH/MyScript/blob/main/Quantumult/wangyiyun/img/%E6%96%B0%E5%BB%BA%E4%BA%91%E5%87%BD%E6%95%B01.png?raw=true) 172 | 173 | 3. 下拉网页找到 **高级配置** 174 | > ### **环境配置**
175 | > 内存64MB
176 | > 初始化超时时间300秒
177 | > 执行超时时间900秒
178 | > ### **执行配置**
179 | > 异步执行勾选启用
180 | 181 | *其他使用默认即可* 182 | 183 | 4. 下拉网页找到 **触发器配置** 184 | > 创建触发器勾选自定义创建
185 | > 触发周期选择自定义触发周期
186 | > Cron表达式填写 10 10 * * *(表示每天10.10分执行,可自行修改,修改方法百度cron表达式)
187 | 188 | *其他使用默认即可* 189 | 190 | 5. 点击**完成** 191 | **至此配置完成** 192 | ### 其他说明 193 | **通知配置** 194 | > 这里以service酱为例
195 | > service的SCKEY(SendKey)[点击登录微信获取](https://sct.ftqq.com/sendkey)
196 | > 其他通知配置方式参考sendNotify.js脚本注释并自行百度相关使用方法
197 | 198 | ![通知配置](https://github.com/laoxinH/MyScript/blob/main/Quantumult/wangyiyun/img/%E9%80%9A%E7%9F%A5%E9%85%8D%E7%BD%AE.png?raw=true) 199 | **添加新脚本(如果以后还会有网易云脚本的话)** 200 | 201 | > 将新脚本上传到云函数目录(具体方法百度,不在赘述)
202 | > 并按照[第三部](#index)分将脚本添加到index.js
203 | 204 | **脚本更新说明** 205 | 206 | > 打开**函数服务**>>**函数代码**
207 | > 将更新后的脚本上传,并删除老脚本(具体百度,不在赘述) 208 | -------------------------------------------------------------------------------- /Quantumult/wangyiyun/cookie_wyy.js: -------------------------------------------------------------------------------- 1 | // 此脚本用于获取网易云cookie 2 | const $ = new Env("网易云cookie"); 3 | 4 | !(async () => { 5 | if (!$.getdata("wyy_cookie") || $.getdata("wyy_cookie") == "") { 6 | if ($request.headers["Cookie"].indexOf("__csrf") != -1 && $request.headers["Cookie"].indexOf("MUSIC_U") != -1) { 7 | const cookieKey = "wyy_cookie"; 8 | const cookieVal = $request.headers["Cookie"]; 9 | const UA = $request.headers["User-Agent"] 10 | if ($.setdata(cookieVal, cookieKey)) { 11 | $.setdata(UA,"wyy_UA"); 12 | $.log($.name,"cookie获取成功",cookieVal); 13 | $.msg($.name,"cookie获取成功!","cookie: " + cookieVal); 14 | } else { 15 | $.log($.name,"cookie获取失败"); 16 | } 17 | } else { 18 | $.log($.name,"当前已存在cookie",$.getdata("Cookie_wyy")); 19 | } 20 | } 21 | $.done(); 22 | return; 23 | })(); 24 | 25 | function Env(t,e){class s{constructor(t){this.env=t}send(t,e="GET"){t="string"==typeof t?{url:t}:t;let s=this.get;return"POST"===e&&(s=this.post),new Promise((e,i)=>{s.call(this,t,(t,s,r)=>{t?i(t):e(s)})})}get(t){return this.send.call(this.env,t)}post(t){return this.send.call(this.env,t,"POST")}}return new class{constructor(t,e){this.name=t,this.http=new s(this),this.data=null,this.dataFile="box.dat",this.logs=[],this.isMute=!1,this.isNeedRewrite=!1,this.logSeparator="\n",this.encoding="utf-8",this.startTime=(new Date).getTime(),Object.assign(this,e),this.log("",`\ud83d\udd14${this.name}, \u5f00\u59cb!`)}isNode(){return"undefined"!=typeof module&&!!module.exports}isQuanX(){return"undefined"!=typeof $task}isSurge(){return"undefined"!=typeof $httpClient&&"undefined"==typeof $loon}isLoon(){return"undefined"!=typeof $loon}isShadowrocket(){return"undefined"!=typeof $rocket}toObj(t,e=null){try{return JSON.parse(t)}catch{return e}}toStr(t,e=null){try{return JSON.stringify(t)}catch{return e}}getjson(t,e){let s=e;const i=this.getdata(t);if(i)try{s=JSON.parse(this.getdata(t))}catch{}return s}setjson(t,e){try{return this.setdata(JSON.stringify(t),e)}catch{return!1}}getScript(t){return new Promise(e=>{this.get({url:t},(t,s,i)=>e(i))})}runScript(t,e){return new Promise(s=>{let i=this.getdata("@chavy_boxjs_userCfgs.httpapi");i=i?i.replace(/\n/g,"").trim():i;let r=this.getdata("@chavy_boxjs_userCfgs.httpapi_timeout");r=r?1*r:20,r=e&&e.timeout?e.timeout:r;const[o,h]=i.split("@"),n={url:`http://${h}/v1/scripting/evaluate`,body:{script_text:t,mock_type:"cron",timeout:r},headers:{"X-Key":o,Accept:"*/*"}};this.post(n,(t,e,i)=>s(i))}).catch(t=>this.logErr(t))}loaddata(){if(!this.isNode())return{};{this.fs=this.fs?this.fs:require("fs"),this.path=this.path?this.path:require("path");const t=this.path.resolve(this.dataFile),e=this.path.resolve(process.cwd(),this.dataFile),s=this.fs.existsSync(t),i=!s&&this.fs.existsSync(e);if(!s&&!i)return{};{const i=s?t:e;try{return JSON.parse(this.fs.readFileSync(i))}catch(t){return{}}}}}writedata(){if(this.isNode()){this.fs=this.fs?this.fs:require("fs"),this.path=this.path?this.path:require("path");const t=this.path.resolve(this.dataFile),e=this.path.resolve(process.cwd(),this.dataFile),s=this.fs.existsSync(t),i=!s&&this.fs.existsSync(e),r=JSON.stringify(this.data);s?this.fs.writeFileSync(t,r):i?this.fs.writeFileSync(e,r):this.fs.writeFileSync(t,r)}}lodash_get(t,e,s){const i=e.replace(/\[(\d+)\]/g,".$1").split(".");let r=t;for(const t of i)if(r=Object(r)[t],void 0===r)return s;return r}lodash_set(t,e,s){return Object(t)!==t?t:(Array.isArray(e)||(e=e.toString().match(/[^.[\]]+/g)||[]),e.slice(0,-1).reduce((t,s,i)=>Object(t[s])===t[s]?t[s]:t[s]=Math.abs(e[i+1])>>0==+e[i+1]?[]:{},t)[e[e.length-1]]=s,t)}getdata(t){let e=this.getval(t);if(/^@/.test(t)){const[,s,i]=/^@(.*?)\.(.*?)$/.exec(t),r=s?this.getval(s):"";if(r)try{const t=JSON.parse(r);e=t?this.lodash_get(t,i,""):e}catch(t){e=""}}return e}setdata(t,e){let s=!1;if(/^@/.test(e)){const[,i,r]=/^@(.*?)\.(.*?)$/.exec(e),o=this.getval(i),h=i?"null"===o?null:o||"{}":"{}";try{const e=JSON.parse(h);this.lodash_set(e,r,t),s=this.setval(JSON.stringify(e),i)}catch(e){const o={};this.lodash_set(o,r,t),s=this.setval(JSON.stringify(o),i)}}else s=this.setval(t,e);return s}getval(t){return this.isSurge()||this.isLoon()?$persistentStore.read(t):this.isQuanX()?$prefs.valueForKey(t):this.isNode()?(this.data=this.loaddata(),this.data[t]):this.data&&this.data[t]||null}setval(t,e){return this.isSurge()||this.isLoon()?$persistentStore.write(t,e):this.isQuanX()?$prefs.setValueForKey(t,e):this.isNode()?(this.data=this.loaddata(),this.data[e]=t,this.writedata(),!0):this.data&&this.data[e]||null}initGotEnv(t){this.got=this.got?this.got:require("got"),this.cktough=this.cktough?this.cktough:require("tough-cookie"),this.ckjar=this.ckjar?this.ckjar:new this.cktough.CookieJar,t&&(t.headers=t.headers?t.headers:{},void 0===t.headers.Cookie&&void 0===t.cookieJar&&(t.cookieJar=this.ckjar))}get(t,e=(()=>{})){if(t.headers&&(delete t.headers["Content-Type"],delete t.headers["Content-Length"]),this.isSurge()||this.isLoon())this.isSurge()&&this.isNeedRewrite&&(t.headers=t.headers||{},Object.assign(t.headers,{"X-Surge-Skip-Scripting":!1})),$httpClient.get(t,(t,s,i)=>{!t&&s&&(s.body=i,s.statusCode=s.status),e(t,s,i)});else if(this.isQuanX())this.isNeedRewrite&&(t.opts=t.opts||{},Object.assign(t.opts,{hints:!1})),$task.fetch(t).then(t=>{const{statusCode:s,statusCode:i,headers:r,body:o}=t;e(null,{status:s,statusCode:i,headers:r,body:o},o)},t=>e(t));else if(this.isNode()){let s=require("iconv-lite");this.initGotEnv(t),this.got(t).on("redirect",(t,e)=>{try{if(t.headers["set-cookie"]){const s=t.headers["set-cookie"].map(this.cktough.Cookie.parse).toString();s&&this.ckjar.setCookieSync(s,null),e.cookieJar=this.ckjar}}catch(t){this.logErr(t)}}).then(t=>{const{statusCode:i,statusCode:r,headers:o,rawBody:h}=t;e(null,{status:i,statusCode:r,headers:o,rawBody:h},s.decode(h,this.encoding))},t=>{const{message:i,response:r}=t;e(i,r,r&&s.decode(r.rawBody,this.encoding))})}}post(t,e=(()=>{})){const s=t.method?t.method.toLocaleLowerCase():"post";if(t.body&&t.headers&&!t.headers["Content-Type"]&&(t.headers["Content-Type"]="application/x-www-form-urlencoded"),t.headers&&delete t.headers["Content-Length"],this.isSurge()||this.isLoon())this.isSurge()&&this.isNeedRewrite&&(t.headers=t.headers||{},Object.assign(t.headers,{"X-Surge-Skip-Scripting":!1})),$httpClient[s](t,(t,s,i)=>{!t&&s&&(s.body=i,s.statusCode=s.status),e(t,s,i)});else if(this.isQuanX())t.method=s,this.isNeedRewrite&&(t.opts=t.opts||{},Object.assign(t.opts,{hints:!1})),$task.fetch(t).then(t=>{const{statusCode:s,statusCode:i,headers:r,body:o}=t;e(null,{status:s,statusCode:i,headers:r,body:o},o)},t=>e(t));else if(this.isNode()){let i=require("iconv-lite");this.initGotEnv(t);const{url:r,...o}=t;this.got[s](r,o).then(t=>{const{statusCode:s,statusCode:r,headers:o,rawBody:h}=t;e(null,{status:s,statusCode:r,headers:o,rawBody:h},i.decode(h,this.encoding))},t=>{const{message:s,response:r}=t;e(s,r,r&&i.decode(r.rawBody,this.encoding))})}}time(t,e=null){const s=e?new Date(e):new Date;let i={"M+":s.getMonth()+1,"d+":s.getDate(),"H+":s.getHours(),"m+":s.getMinutes(),"s+":s.getSeconds(),"q+":Math.floor((s.getMonth()+3)/3),S:s.getMilliseconds()};/(y+)/.test(t)&&(t=t.replace(RegExp.$1,(s.getFullYear()+"").substr(4-RegExp.$1.length)));for(let e in i)new RegExp("("+e+")").test(t)&&(t=t.replace(RegExp.$1,1==RegExp.$1.length?i[e]:("00"+i[e]).substr((""+i[e]).length)));return t}msg(e=t,s="",i="",r){const o=t=>{if(!t)return t;if("string"==typeof t)return this.isLoon()?t:this.isQuanX()?{"open-url":t}:this.isSurge()?{url:t}:void 0;if("object"==typeof t){if(this.isLoon()){let e=t.openUrl||t.url||t["open-url"],s=t.mediaUrl||t["media-url"];return{openUrl:e,mediaUrl:s}}if(this.isQuanX()){let e=t["open-url"]||t.url||t.openUrl,s=t["media-url"]||t.mediaUrl;return{"open-url":e,"media-url":s}}if(this.isSurge()){let e=t.url||t.openUrl||t["open-url"];return{url:e}}}};if(this.isMute||(this.isSurge()||this.isLoon()?$notification.post(e,s,i,o(r)):this.isQuanX()&&$notify(e,s,i,o(r))),!this.isMuteLog){let t=["","==============\ud83d\udce3\u7cfb\u7edf\u901a\u77e5\ud83d\udce3=============="];t.push(e),s&&t.push(s),i&&t.push(i),console.log(t.join("\n")),this.logs=this.logs.concat(t)}}log(...t){t.length>0&&(this.logs=[...this.logs,...t]),console.log(t.join(this.logSeparator))}logErr(t,e){const s=!this.isSurge()&&!this.isQuanX()&&!this.isLoon();s?this.log("",`\u2757\ufe0f${this.name}, \u9519\u8bef!`,t.stack):this.log("",`\u2757\ufe0f${this.name}, \u9519\u8bef!`,t)}wait(t){return new Promise(e=>setTimeout(e,t))}done(t={}){const e=(new Date).getTime(),s=(e-this.startTime)/1e3;this.log("",`\ud83d\udd14${this.name}, \u7ed3\u675f! \ud83d\udd5b ${s} \u79d2`),this.log(),(this.isSurge()||this.isQuanX()||this.isLoon())&&$done(t)}}(t,e)} 26 | 27 | -------------------------------------------------------------------------------- /Quantumult/wangyiyun/icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/laoxinH/MyScript/2580340cb5d866f29d3cbee4c43847a2d436a871/Quantumult/wangyiyun/icon.png -------------------------------------------------------------------------------- /Quantumult/wangyiyun/img/ceshi: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /Quantumult/wangyiyun/img/复制cookie.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/laoxinH/MyScript/2580340cb5d866f29d3cbee4c43847a2d436a871/Quantumult/wangyiyun/img/复制cookie.png -------------------------------------------------------------------------------- /Quantumult/wangyiyun/img/新建云函数1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/laoxinH/MyScript/2580340cb5d866f29d3cbee4c43847a2d436a871/Quantumult/wangyiyun/img/新建云函数1.png -------------------------------------------------------------------------------- /Quantumult/wangyiyun/img/格式化ck.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/laoxinH/MyScript/2580340cb5d866f29d3cbee4c43847a2d436a871/Quantumult/wangyiyun/img/格式化ck.png -------------------------------------------------------------------------------- /Quantumult/wangyiyun/img/源码下载.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/laoxinH/MyScript/2580340cb5d866f29d3cbee4c43847a2d436a871/Quantumult/wangyiyun/img/源码下载.png -------------------------------------------------------------------------------- /Quantumult/wangyiyun/img/目录展示1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/laoxinH/MyScript/2580340cb5d866f29d3cbee4c43847a2d436a871/Quantumult/wangyiyun/img/目录展示1.png -------------------------------------------------------------------------------- /Quantumult/wangyiyun/img/目录展示2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/laoxinH/MyScript/2580340cb5d866f29d3cbee4c43847a2d436a871/Quantumult/wangyiyun/img/目录展示2.png -------------------------------------------------------------------------------- /Quantumult/wangyiyun/img/通知配置.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/laoxinH/MyScript/2580340cb5d866f29d3cbee4c43847a2d436a871/Quantumult/wangyiyun/img/通知配置.png -------------------------------------------------------------------------------- /Quantumult/wangyiyun/wyy_config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | // 网易云相关配置 3 | wangyi: { 4 | // 不填写则使用默认回复 5 | // 6 | doSignInMusician: true, // 是否执行音乐人签到 7 | doShareBlog:true, // 是否执行音乐人发布动态任务 8 | shareMsg: "", // 发送动态的文字内容 9 | doCommentYourself:true, // 是否执行音乐人主创说任务 10 | commentMsg: "", // 主创说评论内容 11 | doRePrivatrMessage:true, // 是否执行音乐人私信任务 12 | reMsg: "", // 私信内容 13 | doReplyMusicComment:true, // 是否执行音乐人回复粉丝评论任务 14 | reCommentMsg: "", // 回复评论内容 15 | doViewMyCircle:true, // 是否执行音乐人访问自己云圈任务 16 | doWatchLesson:true, // 是否执行音乐人观看课程任务 17 | users: [ 18 | { 19 | // 账号一 20 | // 说明: 若填写cookie将直接通过cookie登录,电话账号登录将会失效(优先级:cookie > 账号登录) 21 | // 因此cookie 和 电话二选一即可(推荐cookie登录) 22 | cookie: "MUSIC_U=2da45fadcea83dbe492669abdc6c2690d89fdfb5c377e5a9e548218dd27afef3993166e004087dd3d78b6050a17a35e705925a4e6992f61d07c385928f88e8de;__csrf=6d4b52f2c55af05556fa31d913134659;", 23 | phone: "18382750609", 24 | password: "laoxin0318", 25 | // UA推荐填写自己浏览器UA,防止大量UA相同出现错误 26 | UA:"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/99.0.4844.74 Safari/537.37 Edg/99.0.1150.55", 27 | 28 | }, 29 | { 30 | // 账号二 31 | cookie: "", 32 | phone: "", 33 | password: "", 34 | UA:"" 35 | } 36 | /** 37 | * 若需要添加更多账号请自行添加以下内容,注意每一个{}之间有英文逗号“,”分割 38 | { 39 | cookie: "", 40 | phone: "", 41 | password: "", 42 | UA:"" 43 | } 44 | */ 45 | ] 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /Quantumult/wangyiyun/wyy_yyr.js: -------------------------------------------------------------------------------- 1 | /** 2 | * 网易云音乐人 3 | * @author: github@laoxinH 4 | * @version: 2.4 5 | * 每天10点10分执行任务,如有需要请自行修改cron表达式 6 | ==============cookie获取方式=================== 7 | 打开我在校园微信小程序--"我的",脚本将会自动获取,当看到通知获取成功时即可 8 | ===============配置方式========================= 9 | ===#quanx==== 10 | [rewrite_local] 11 | https:\/\/music\.163\.com\/weapi\/feedback url script-request-header https://raw.githubusercontent.com/laoxinH/MyScript/main/Quantumult/wangyiyun/cookie_wyy.js 12 | ======================================== 13 | [mitm] 14 | hostname = music.163.com 15 | ======================================== 16 | [task_local] 17 | 10 10 * * * https://raw.githubusercontent.com/laoxinH/MyScript/main/Quantumult/wangyiyun/wyy_yyr.js, tag=网易云音乐人, img-url=https://github.com/laoxinH/MyScript/blob/main/Quantumult/wangyiyun/icon.png?raw=true?raw=true, enabled=true 18 | =======boxjs订阅地址======= 19 | https://raw.githubusercontent.com/laoxinH/MyScript/main/boxjs/laoxin.boxjs.json 20 | */ 21 | const $ = new Env("网易云音乐云豆"); 22 | const api = new NCApi(); 23 | 24 | 25 | // CrytoJS加密 26 | var CryptoJS=CryptoJS||function(u,p){var d={},l=d.lib={},s=function(){},t=l.Base={extend:function(a){s.prototype=this;var c=new s;a&&c.mixIn(a);c.hasOwnProperty("init")||(c.init=function(){c.$super.init.apply(this,arguments)});c.init.prototype=c;c.$super=this;return c},create:function(){var a=this.extend();a.init.apply(a,arguments);return a},init:function(){},mixIn:function(a){for(var c in a){a.hasOwnProperty(c)&&(this[c]=a[c])}a.hasOwnProperty("toString")&&(this.toString=a.toString)},clone:function(){return this.init.prototype.extend(this)}},r=l.WordArray=t.extend({init:function(a,c){a=this.words=a||[];this.sigBytes=c!=p?c:4*a.length},toString:function(a){return(a||v).stringify(this)},concat:function(a){var c=this.words,e=a.words,j=this.sigBytes;a=a.sigBytes;this.clamp();if(j%4){for(var k=0;k>>2]|=(e[k>>>2]>>>24-8*(k%4)&255)<<24-8*((j+k)%4)}}else{if(65535>>2]=e[k>>>2]}}else{c.push.apply(c,e)}}this.sigBytes+=a;return this},clamp:function(){var a=this.words,c=this.sigBytes;a[c>>>2]&=4294967295<<32-8*(c%4);a.length=u.ceil(c/4)},clone:function(){var a=t.clone.call(this);a.words=this.words.slice(0);return a},random:function(a){for(var c=[],e=0;e>>2]>>>24-8*(j%4)&255;e.push((k>>>4).toString(16));e.push((k&15).toString(16))}return e.join("")},parse:function(a){for(var c=a.length,e=[],j=0;j>>3]|=parseInt(a.substr(j,2),16)<<24-4*(j%8)}return new r.init(e,c/2)}},b=w.Latin1={stringify:function(a){var c=a.words;a=a.sigBytes;for(var e=[],j=0;j>>2]>>>24-8*(j%4)&255))}return e.join("")},parse:function(a){for(var c=a.length,e=[],j=0;j>>2]|=(a.charCodeAt(j)&255)<<24-8*(j%4)}return new r.init(e,c)}},x=w.Utf8={stringify:function(a){try{return decodeURIComponent(escape(b.stringify(a)))}catch(c){throw Error("Malformed UTF-8 data")}},parse:function(a){return b.parse(unescape(encodeURIComponent(a)))}},q=l.BufferedBlockAlgorithm=t.extend({reset:function(){this.i4m=new r.init;this.sL0x=0},vE1x:function(a){"string"==typeof a&&(a=x.parse(a));this.i4m.concat(a);this.sL0x+=a.sigBytes},kG8y:function(a){var c=this.i4m,e=c.words,j=c.sigBytes,k=this.blockSize,b=j/(4*k),b=a?u.ceil(b):u.max((b|0)-this.JP5U,0);a=b*k;j=u.min(4*a,j);if(a){for(var q=0;q>>2]>>>24-8*(r%4)&255)<<16|(l[r+1>>>2]>>>24-8*((r+1)%4)&255)<<8|l[r+2>>>2]>>>24-8*((r+2)%4)&255,v=0;4>v&&r+0.75*v>>6*(3-v)&63))}}if(l=t.charAt(64)){for(;d.length%4;){d.push(l)}}return d.join("")},parse:function(d){var l=d.length,s=this.bA4E,t=s.charAt(64);t&&(t=d.indexOf(t),-1!=t&&(l=t));for(var t=[],r=0,w=0;w>>6-2*(w%4);t[r>>>2]|=(v|b)<<24-8*(r%4);r++}}return p.create(t,r)},bA4E:"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/="}})();(function(u){function p(b,n,a,c,e,j,k){b=b+(n&a|~n&c)+e+k;return(b<>>32-j)+n}function d(b,n,a,c,e,j,k){b=b+(n&c|a&~c)+e+k;return(b<>>32-j)+n}function l(b,n,a,c,e,j,k){b=b+(n^a^c)+e+k;return(b<>>32-j)+n}function s(b,n,a,c,e,j,k){b=b+(a^(n|~c))+e+k;return(b<>>32-j)+n}for(var t=CryptoJS,r=t.lib,w=r.WordArray,v=r.Hasher,r=t.algo,b=[],x=0;64>x;x++){b[x]=4294967296*u.abs(u.sin(x+1))|0}r=r.MD5=v.extend({ly8q:function(){this.cO5T=new w.init([1732584193,4023233417,2562383102,271733878])},rb0x:function(q,n){for(var a=0;16>a;a++){var c=n+a,e=q[c];q[c]=(e<<8|e>>>24)&16711935|(e<<24|e>>>8)&4278255360}var a=this.cO5T.words,c=q[n+0],e=q[n+1],j=q[n+2],k=q[n+3],z=q[n+4],r=q[n+5],t=q[n+6],w=q[n+7],v=q[n+8],A=q[n+9],B=q[n+10],C=q[n+11],u=q[n+12],D=q[n+13],E=q[n+14],x=q[n+15],f=a[0],m=a[1],g=a[2],h=a[3],f=p(f,m,g,h,c,7,b[0]),h=p(h,f,m,g,e,12,b[1]),g=p(g,h,f,m,j,17,b[2]),m=p(m,g,h,f,k,22,b[3]),f=p(f,m,g,h,z,7,b[4]),h=p(h,f,m,g,r,12,b[5]),g=p(g,h,f,m,t,17,b[6]),m=p(m,g,h,f,w,22,b[7]),f=p(f,m,g,h,v,7,b[8]),h=p(h,f,m,g,A,12,b[9]),g=p(g,h,f,m,B,17,b[10]),m=p(m,g,h,f,C,22,b[11]),f=p(f,m,g,h,u,7,b[12]),h=p(h,f,m,g,D,12,b[13]),g=p(g,h,f,m,E,17,b[14]),m=p(m,g,h,f,x,22,b[15]),f=d(f,m,g,h,e,5,b[16]),h=d(h,f,m,g,t,9,b[17]),g=d(g,h,f,m,C,14,b[18]),m=d(m,g,h,f,c,20,b[19]),f=d(f,m,g,h,r,5,b[20]),h=d(h,f,m,g,B,9,b[21]),g=d(g,h,f,m,x,14,b[22]),m=d(m,g,h,f,z,20,b[23]),f=d(f,m,g,h,A,5,b[24]),h=d(h,f,m,g,E,9,b[25]),g=d(g,h,f,m,k,14,b[26]),m=d(m,g,h,f,v,20,b[27]),f=d(f,m,g,h,D,5,b[28]),h=d(h,f,m,g,j,9,b[29]),g=d(g,h,f,m,w,14,b[30]),m=d(m,g,h,f,u,20,b[31]),f=l(f,m,g,h,r,4,b[32]),h=l(h,f,m,g,v,11,b[33]),g=l(g,h,f,m,C,16,b[34]),m=l(m,g,h,f,E,23,b[35]),f=l(f,m,g,h,e,4,b[36]),h=l(h,f,m,g,z,11,b[37]),g=l(g,h,f,m,w,16,b[38]),m=l(m,g,h,f,B,23,b[39]),f=l(f,m,g,h,D,4,b[40]),h=l(h,f,m,g,c,11,b[41]),g=l(g,h,f,m,k,16,b[42]),m=l(m,g,h,f,t,23,b[43]),f=l(f,m,g,h,A,4,b[44]),h=l(h,f,m,g,u,11,b[45]),g=l(g,h,f,m,x,16,b[46]),m=l(m,g,h,f,j,23,b[47]),f=s(f,m,g,h,c,6,b[48]),h=s(h,f,m,g,w,10,b[49]),g=s(g,h,f,m,E,15,b[50]),m=s(m,g,h,f,r,21,b[51]),f=s(f,m,g,h,u,6,b[52]),h=s(h,f,m,g,k,10,b[53]),g=s(g,h,f,m,B,15,b[54]),m=s(m,g,h,f,e,21,b[55]),f=s(f,m,g,h,v,6,b[56]),h=s(h,f,m,g,x,10,b[57]),g=s(g,h,f,m,t,15,b[58]),m=s(m,g,h,f,D,21,b[59]),f=s(f,m,g,h,z,6,b[60]),h=s(h,f,m,g,C,10,b[61]),g=s(g,h,f,m,j,15,b[62]),m=s(m,g,h,f,A,21,b[63]); 27 | a[0]=a[0]+f|0;a[1]=a[1]+m|0;a[2]=a[2]+g|0;a[3]=a[3]+h|0},mD8v:function(){var b=this.i4m,n=b.words,a=8*this.sL0x,c=8*b.sigBytes;n[c>>>5]|=128<<24-c%32;var e=u.floor(a/4294967296);n[(c+64>>>9<<4)+15]=(e<<8|e>>>24)&16711935|(e<<24|e>>>8)&4278255360;n[(c+64>>>9<<4)+14]=(a<<8|a>>>24)&16711935|(a<<24|a>>>8)&4278255360;b.sigBytes=4*(n.length+1);this.kG8y();b=this.cO5T;n=b.words;for(a=0;4>a;a++){c=n[a],n[a]=(c<<8|c>>>24)&16711935|(c<<24|c>>>8)&4278255360}return b},clone:function(){var b=v.clone.call(this);b.cO5T=this.cO5T.clone();return b}});t.MD5=v.lT8L(r);t.HmacMD5=v.vy1x(r)})(Math);(function(){var u=CryptoJS,p=u.lib,d=p.Base,l=p.WordArray,p=u.algo,s=p.EvpKDF=d.extend({cfg:d.extend({keySize:4,hasher:p.MD5,iterations:1}),init:function(d){this.cfg=this.cfg.extend(d)},compute:function(d,r){for(var p=this.cfg,s=p.hasher.create(),b=l.create(),u=b.words,q=p.keySize,p=p.iterations;u.length>>2]&255}};d.BlockCipher=v.extend({cfg:v.cfg.extend({mode:b,padding:q}),reset:function(){v.reset.call(this);var a=this.cfg,b=a.iv,a=a.mode;if(this.YP9G==this.JN5S){var c=a.createEncryptor}else{c=a.createDecryptor,this.JP5U=1}this.eP6J=c.call(a,this,b&&b.words)},rb0x:function(a,b){this.eP6J.processBlock(a,b)},mD8v:function(){var a=this.cfg.padding;if(this.YP9G==this.JN5S){a.pad(this.i4m,this.blockSize);var b=this.kG8y(!0)}else{b=this.kG8y(!0),a.unpad(b)}return b},blockSize:4});var n=d.CipherParams=l.extend({init:function(a){this.mixIn(a)},toString:function(a){return(a||this.formatter).stringify(this)}}),b=(p.format={}).OpenSSL={stringify:function(a){var b=a.ciphertext;a=a.salt;return(a?s.create([1398893684,1701076831]).concat(a).concat(b):b).toString(r)},parse:function(a){a=r.parse(a);var b=a.words;if(1398893684==b[0]&&1701076831==b[1]){var c=s.create(b.slice(2,4));b.splice(0,4);a.sigBytes-=16}return n.create({ciphertext:a,salt:c})}},a=d.SerializableCipher=l.extend({cfg:l.extend({format:b}),encrypt:function(a,b,c,d){d=this.cfg.extend(d);var l=a.createEncryptor(c,d);b=l.finalize(b);l=l.cfg;return n.create({ciphertext:b,key:c,iv:l.iv,algorithm:a,mode:l.mode,padding:l.padding,blockSize:a.blockSize,formatter:d.format})},decrypt:function(a,b,c,d){d=this.cfg.extend(d);b=this.In5s(b,d.format);return a.createDecryptor(c,d).finalize(b.ciphertext)},In5s:function(a,b){return"string"==typeof a?b.parse(a,this):a}}),p=(p.kdf={}).OpenSSL={execute:function(a,b,c,d){d||(d=s.random(8));a=w.create({keySize:b+c}).compute(a,d);c=s.create(a.words.slice(b),4*c);a.sigBytes=4*b;return n.create({key:a,iv:c,salt:d})}},c=d.PasswordBasedCipher=a.extend({cfg:a.cfg.extend({kdf:p}),encrypt:function(b,c,d,l){l=this.cfg.extend(l);d=l.kdf.execute(d,b.keySize,b.ivSize);l.iv=d.iv;b=a.encrypt.call(this,b,c,d.key,l);b.mixIn(d);return b},decrypt:function(b,c,d,l){l=this.cfg.extend(l);c=this.In5s(c,l.format);d=l.kdf.execute(d,b.keySize,b.ivSize,c.salt);l.iv=d.iv;return a.decrypt.call(this,b,c,d.key,l)}})}();(function(){for(var u=CryptoJS,p=u.lib.BlockCipher,d=u.algo,l=[],s=[],t=[],r=[],w=[],v=[],b=[],x=[],q=[],n=[],a=[],c=0;256>c;c++){a[c]=128>c?c<<1:c<<1^283}for(var e=0,j=0,c=0;256>c;c++){var k=j^j<<1^j<<2^j<<3^j<<4,k=k>>>8^k&255^99;l[e]=k; 28 | s[k]=e;var z=a[e],F=a[z],G=a[F],y=257*a[k]^16843008*k;t[e]=y<<24|y>>>8;r[e]=y<<16|y>>>16;w[e]=y<<8|y>>>24;v[e]=y;y=16843009*G^65537*F^257*z^16843008*e;b[k]=y<<24|y>>>8;x[k]=y<<16|y>>>16;q[k]=y<<8|y>>>24;n[k]=y;e?(e=z^a[a[a[G^z]]],j^=a[a[j]]):e=j=1}var H=[0,1,2,4,8,16,32,64,128,27,54],d=d.AES=p.extend({ly8q:function(){for(var a=this.J4N,c=a.words,d=a.sigBytes/4,a=4*((this.bhX2x=d+6)+1),e=this.bko2x=[],j=0;j>>24]<<24|l[k>>>16&255]<<16|l[k>>>8&255]<<8|l[k&255]):(k=k<<8|k>>>24,k=l[k>>>24]<<24|l[k>>>16&255]<<16|l[k>>>8&255]<<8|l[k&255],k^=H[j/d|0]<<24);e[j]=e[j-d]^k}}c=this.bkn2x=[];for(d=0;dd||4>=j?k:b[l[k>>>24]]^x[l[k>>>16&255]]^q[l[k>>>8&255]]^n[l[k&255]]}},encryptBlock:function(a,b){this.Fn4r(a,b,this.bko2x,t,r,w,v,l)},decryptBlock:function(a,c){var d=a[c+1];a[c+1]=a[c+3];a[c+3]=d;this.Fn4r(a,c,this.bkn2x,b,x,q,n,s);d=a[c+1];a[c+1]=a[c+3];a[c+3]=d},Fn4r:function(a,b,c,d,e,j,l,f){for(var m=this.bhX2x,g=a[b]^c[0],h=a[b+1]^c[1],k=a[b+2]^c[2],n=a[b+3]^c[3],p=4,r=1;r>>24]^e[h>>>16&255]^j[k>>>8&255]^l[n&255]^c[p++],s=d[h>>>24]^e[k>>>16&255]^j[n>>>8&255]^l[g&255]^c[p++],t=d[k>>>24]^e[n>>>16&255]^j[g>>>8&255]^l[h&255]^c[p++],n=d[n>>>24]^e[g>>>16&255]^j[h>>>8&255]^l[k&255]^c[p++],g=q,h=s,k=t}q=(f[g>>>24]<<24|f[h>>>16&255]<<16|f[k>>>8&255]<<8|f[n&255])^c[p++];s=(f[h>>>24]<<24|f[k>>>16&255]<<16|f[n>>>8&255]<<8|f[g&255])^c[p++];t=(f[k>>>24]<<24|f[n>>>16&255]<<16|f[g>>>8&255]<<8|f[h&255])^c[p++];n=(f[n>>>24]<<24|f[g>>>16&255]<<16|f[h>>>8&255]<<8|f[k&255])^c[p++];a[b]=q;a[b+1]=s;a[b+2]=t;a[b+3]=n},keySize:8});u.AES=p.lT8L(d)})(); 29 | const isPhone = !$.isNode() || $.isLoon() || $.isQuanX() || $.isSurge(); // 环境检测 30 | let users,index = 0,message = ""; 31 | let shareMsg = getData("shareMsg")? getData("shareMsg"):"好歌推荐~~" 32 | ,commentMsg = getData("commentMsg") ? getData("commentMsg") :"顶顶顶~~" 33 | ,reMsg = getData("reMsg")? getData("reMsg"):"感谢支持和意见~~" 34 | ,reCommentMsg = getData("reCommentMsg")?getData("reCommentMsg"):"感谢支持和意见~~"; 35 | 36 | // 初始化脚本 37 | console.log("【通知📢】 开始初始化脚本, 当前环境 : " + (isPhone ? "手机端" : "nodejs"),"开始执行!"); 38 | if (isPhone) { 39 | cookie = $.toStr(getData("cookie")).replaceAll("\n",""); 40 | users = [{ 41 | cookie:cookie, 42 | phone:"", 43 | password:"", 44 | UA:getData("UA") 45 | }]; 46 | }; 47 | 48 | 49 | 50 | if (!isPhone){ 51 | users = getData("users"); 52 | console.log("【通知📢】", "你提供了 " + users.length + " 个账号"); 53 | } 54 | 55 | !(async () => { 56 | for (let user of users) { 57 | index += 1; // 账号统计 58 | if (!await getCookie(user)) { 59 | continue; 60 | }; 61 | let info = await getMusicianInfo(); 62 | if (info.code == 600) { 63 | console.log("用户不是音乐人!"); 64 | continue; 65 | } 66 | message += "音乐人昵称:" + $.artistName + "\n"; 67 | let YDCount = $.YDCount; 68 | await flashTaskInfo(); 69 | await doTask(); 70 | console.log("\n\n-------------------------任务执行完成!---------------------------"); 71 | console.log("【通知📢】", "刷新任务列表!"); 72 | await flashTaskInfo(); 73 | await getReword(); 74 | // 刷新数据 75 | await getMusicianInfo(); 76 | $.getYD = $.YDCount - YDCount; 77 | message += "执行脚本获得云豆:" + ($.getYD) + "\n" + "当前云豆数量:" + $.YDCount + "\n\n\n"; 78 | } 79 | 80 | message += "有些任务已经下线,但是脚本获取任务列表时任然存在,不用管!\r\n此脚本目前只是执行:登录音乐人中心、发布动态、发布主创说、回复粉丝私信、回复粉丝评论、访问自己云圈 六个任务,其他任务请手动执行!"; 81 | message += "laoxinH的脚本仓库地址,获取更多🔥脚本和打赏请访问:https://github.com/laoxinH/MyScript\r\n💕感谢支持😊"; 82 | await sendNotify(); 83 | return $.done(); 84 | })(); 85 | // 格式化cookie 86 | async function getCookie(user){ 87 | let cookie; 88 | api.UA = user.UA; 89 | console.log("---------------------账号【"+ index +"】-------------------------"); 90 | message += "---------------------账号【"+ index +"】-------------------------\n"; 91 | let tempCk = user.cookie; 92 | if (!tempCk || tempCk == "" ) { 93 | message += "尚未填写cookie,nodejs用户请自行通过浏览器抓取并填写到wyy_config.js,quanx等ios用户打开网址将自动获取\n\n\n"; 94 | console.log($.name,"📢请打开: https://music.163.com 并登录获取cookie","nodejs用户请自行通过浏览器抓取并填写到wyy_config.js","quanx等ios用户打开网址将自动获取"); 95 | if (isPhone) { 96 | let opts = { 97 | 'open-url': 'https://music.163.com', 98 | 'media-url': 'https://github.com/laoxinH/MyScript/blob/main/Quantumult/wangyiyun/icon.png?raw=true' 99 | } 100 | $.msg($.name,"📢请打开: https://music.163.com 并登录获取cookie(手机用户切换到电脑网页即可登录)","点击此通知直达网址",opts); 101 | return false; 102 | } 103 | } else { 104 | // cookie检查 105 | cookie = tempCk; 106 | let reg_csrf = /__csrf=(\w)+/; 107 | let reg_music_u = /MUSIC_U=(\w)+/; 108 | if (reg_csrf.test(cookie) && reg_music_u.test(cookie)) { 109 | let csrf_token = cookie.match(/__csrf=(\w)+/)[0].substring(7); 110 | api.cookie = cookie; 111 | api.csrf_token = csrf_token; 112 | console.log("【通知】账号 " + index,"cookie格式化成功!"); 113 | let data = await api.getMusicianInfo(); 114 | if (data.info != false) { /// 检查cookie是否失效 115 | return true; 116 | } else { 117 | if (isPhone) { 118 | let opts = { 119 | 'open-url': 'https://music.163.com', 120 | 'media-url': 'https://github.com/laoxinH/MyScript/blob/main/Quantumult/wangyiyun/icon.png?raw=true' 121 | } 122 | setData("","wyy_cookie"); 123 | $.msg($.name,"📢cookie已失效,请重新获取: https://music.163.com 并登录获取cookie(手机用户切换到电脑网页即可登录)","点击此通知直达网址",opts); 124 | return false; 125 | } 126 | message += "cookie已失效;请打开;请打开: https://music.163.com 并登录获取cookie,nodejs用户请自行通过浏览器抓取并填写到wyy_config.js\n"; 127 | console.log($.name,"📢 cookie已失效;请打开: https://music.163.com 并登录获取cookie","nodejs用户请自行通过浏览器抓取并填写到wyy_config.js","quanx等ios用户打开网址将自动获取"); 128 | 129 | } 130 | } else { 131 | console.log("【错误❌】","账号 【" + index + "】 填写的cookie有误,参考:MUSIC_U=2da45fadcea83dbe492669abdc93166e004087dd3d78b6050a17a35e705925a4e6992f61dfe3f0151024f9e31; __csrf=e1f260e08c8b91351abd40466b14e;","请登录:https://music.163.com重新获取!"); 132 | message += "cookie格式有误;请打开;请打开: https://music.163.com 并登录获取cookie,nodejs用户请自行通过浏览器抓取并填写到wyy_config.js\n" + 133 | "参考格式:MUSIC_U=2da45fadcea83dbe492669abdc93166e004087dd3d78b6050a17a35e705925a4e6992f61dfe3f0151024f9e31; __csrf=e1f260e08c8b91351abd40466b14e;\n"; 134 | } 135 | } 136 | if (isPhone) return false; 137 | console.log("开始尝试账号密码登录!"); 138 | if (!user.phone || !user.password ) { 139 | console.log("【错误❌】","账号 " + index + " 登录失败","请到wyy_config.js填写账号和密码!"); 140 | message += "账号【" + index + "】cookie格式化出错,且未填写账号密码,详情请查看脚本日志\r\n请按照要求正确填写cookie或者填写账号密码登录!\n\n\n" 141 | return false; 142 | } 143 | cookie = "os=pc; osver=Microsoft-Windows-10-Professional-build-10586-64bit; appver=2.0.3.131777; channel=netease; __remember_me=true;"; 144 | api.cookie = cookie; 145 | let data = await api.login(user.phone,user.password); 146 | if (!data){ 147 | message += "登录失败!请到检查填写的账号和密码是否正确!如果检查账号密码无误仍然登录失败,请使用cookie登录!\n\n\n"; 148 | console.log("【错误❌】","账号 " + index + " 登录失败","请到检查填写的账号和密码是否正确! 如果检查账号密码无误任然登录失败,请使用cookie登录!"); 149 | return false; 150 | } else { 151 | console.log("账号密码登录成功!"); 152 | return true 153 | } 154 | } 155 | 156 | async function sendNotify(){ 157 | $.msg($.name,"【通知📢】本次执行获得云豆: " + ($.getYD || 0) + "; 当前总云豆: " + ($.YDCount || 0),message); 158 | if (!isPhone) { 159 | require("./sendNotify").sendNotify($.name,message); 160 | } 161 | } 162 | // 获取音乐人信息 163 | async function getMusicianInfo(){ 164 | console.log("【通知📢】开始获取音乐人账户信息"); 165 | let YDData = await api.getYDCount(); 166 | try{ 167 | $.YDCount = parseInt(YDData.data.data.cloudBean); 168 | let userData = await api.getMusicianInfo(); 169 | $.artistName = userData.data.data.artistName; 170 | $.artistId = userData.data.data.artistId; 171 | console.log("【通知📢】 音乐人昵称: "+$.artistName,"当前账户云豆数量: "+ $.YDCount); 172 | } catch (e) { 173 | // TODO 174 | } 175 | return YDData.msg; 176 | } 177 | // 刷新任务列表 178 | async function flashTaskInfo(){ 179 | let dayTaskData = await api.getMusicianDayTaskInfo(); 180 | let recommendTaskData = await api.getMusicianRecommendTaskInfo(); 181 | 182 | let taskList = []; 183 | let taskList1 = dayTaskData.data.data.list; 184 | let tasList2 = recommendTaskData.data.data.list; 185 | taskList = taskList1.concat(tasList2); 186 | let unfinishedTasks = [],a = 0; 187 | let finishedTasks = [],b = 0; 188 | for (let task of taskList) { 189 | //if (task.userId == 0) continue; 190 | if (task.status == 10 || task.status == 0) { 191 | console.log("【任务】: " + task.description + " | 未完成(进度:" + task.progressRate + "/" + (task.targetCount ? task.targetCount : 1) + ")"); 192 | unfinishedTasks[a] = task; 193 | a++; 194 | } 195 | if (task.status == 20) { 196 | console.log("【任务】: " + task.description + " | 已完成但未领取奖励 稍后将会领取"); 197 | finishedTasks[b] = task; 198 | b++; 199 | } 200 | if (task.status == 100) { 201 | console.log("【任务】: " + task.description + " | 已领取奖励 云豆数量: " + task.rewardWorth); 202 | } 203 | } 204 | $.unfinishedTasks = unfinishedTasks; 205 | $.finishedTasks = finishedTasks; 206 | } 207 | // 执行任务 208 | async function doTask() { 209 | $.doneTasks = []; 210 | console.log("【通知📢】", "待做任务数量: " + $.unfinishedTasks.length,"开始执行!"); 211 | // 执行任务 212 | for (let unfinishedTask of $.unfinishedTasks) { 213 | if (unfinishedTask.description.indexOf("签到") != -1) { 214 | await doSignInMusician().catch(e=>{console.error(e)}); 215 | console.log("休息一下~~", "等待10秒"); 216 | await $.wait(10000); 217 | } 218 | if (unfinishedTask.description.indexOf("动态") != -1) { 219 | await doShareBlog().catch(e=>{console.error(e)}); 220 | $.doneTasks.push(unfinishedTask); 221 | console.log("休息一下~~", "等待10秒"); 222 | await $.wait(10000); 223 | } 224 | if (unfinishedTask.description.indexOf("主创") != -1) { 225 | await doCommentYourself().catch(e=>{console.error(e)}); 226 | $.doneTasks.push(unfinishedTask); 227 | console.log("休息一下~~", "等待10秒"); 228 | await $.wait(10000); 229 | } 230 | if (unfinishedTask.description.indexOf("私信") != -1) { 231 | let count = unfinishedTask.targetCount - unfinishedTask.progressRate; 232 | console.log("已完成回复数量: " + unfinishedTask.progressRate, "还需回复: " + (unfinishedTask.targetCount - unfinishedTask.progressRate)); 233 | for (let i = 0; i < count; i++) { 234 | await doRePrivatrMessage().catch(e=>{console.error(e)}); 235 | console.log("休息一下~~", "等待10秒"); 236 | await $.wait(10000); 237 | } 238 | $.doneTasks.push(unfinishedTask); 239 | } 240 | if(unfinishedTask.description.indexOf("评论") != -1) { 241 | await doReplyMusicComment().catch(e=>{console.error(e)}); 242 | $.doneTasks.push(unfinishedTask); 243 | console.log("休息一下~~", "等待10秒"); 244 | await $.wait(10000); 245 | } 246 | if (unfinishedTask.description.indexOf("云圈") != -1) { 247 | await doViewMyCircle().catch(e=>{console.error(e)}); 248 | $.doneTasks.push(unfinishedTask); 249 | console.log("休息一下~~", "等待10秒"); 250 | await $.wait(10000); 251 | } 252 | if (unfinishedTask.description.indexOf("课程") != -1) { 253 | await doWatchLesson().catch(e=>{console.error(e)}); 254 | $.doneTasks.push(unfinishedTask); 255 | console.log("休息一下~~", "等待10秒"); 256 | await $.wait(10000); 257 | } 258 | } 259 | } 260 | // 发布动态任务 261 | async function doShareBlog(){ 262 | if (getData("doShareBlog") == false ? true : false) { 263 | console.log("【通知】 已关闭执行发布动态任务!"); 264 | return; 265 | } 266 | console.log("【通知】 开始执行发布动态任务!"); 267 | let data = await api.getRecommendedPlaylist(); 268 | let playLists = data.data.recommend; 269 | let index = Math.round(Math.random()*(playLists.length-1)); 270 | let playList = playLists[index]; 271 | let result = await api.shareBlog(shareMsg,playList.id); 272 | if (!result.info) { 273 | console.log("【错误❌】 动态发送失败! 原因:" + $.toStr(result.msg)); 274 | message += "❌动态发送失败!原因:" + $.toStr(result.msg) + "\n"; 275 | } else { 276 | console.log("动态发送成功!内容:" + shareMsg + " 歌单:" + playList.name); 277 | message += "✅动态发送成功!内容:" + shareMsg + " 歌单:" + playList.name + "\n"; 278 | } 279 | } 280 | // 音乐人签到 281 | async function doSignInMusician(){ 282 | if (getData("doSignInMusician") == false ? true : false) { 283 | console.log("【通知】 已关闭执行音乐人签到任务!"); 284 | return; 285 | } 286 | console.log("【通知】 开始执行音乐人签到任务!"); 287 | let result = await api.signInMusician(); 288 | if (result.info){ 289 | console.log(`✅音乐人签到成功!`); 290 | message += `✅音乐人签到成功!\n`; 291 | } else { 292 | console.log("【错误❌】 音乐人签到失败! 原因:" + $.toStr(result.msg)); 293 | message += "❌音乐人签到失败!\n原因:" + $.toStr(result.msg) + "\n"; 294 | } 295 | } 296 | // 回复评论 297 | async function doReplyMusicComment(){ 298 | if (getData("doReplyMusicComment") == false ? true : false) { 299 | console.log("【通知】 已关闭执行回复评论任务!"); 300 | return; 301 | } 302 | console.log("【通知】 开始执行回复粉丝评论任务!"); 303 | let myAlbumData = await api.getMyAlbum(); 304 | let myAlbumList = myAlbumData.data.data.list; 305 | let myAlbumIndex = Math.round(Math.random()*(myAlbumList.length-1)); 306 | let album = myAlbumList[myAlbumIndex]; 307 | let myMusicData = await api.getMusicsByAlbum(album.id); 308 | let musicIndex = Math.round(Math.random()*(myMusicData.length-1)); 309 | let myMusic = myMusicData[musicIndex]; 310 | // console.log(myMusic) 311 | console.log(`随机抽取的我的专辑:${album.name}\n随机抽取的音乐 : ${myMusic.name}`); 312 | 313 | let commentData = await api.getMusicComments(myMusic.id); 314 | let commentList = commentData.data.data.comments; 315 | /* let user = { 316 | name:listElement.user.nickname, 317 | cid : listElement.commentId, 318 | msg: listElement.content, 319 | mid:commentData.mid, 320 | mname:commentData.musicName 321 | }*/ 322 | let commentIndex = Math.round(Math.random()*(commentList.length - 1)); 323 | let comment = commentList[commentIndex]; 324 | console.log(`随机抽取的评论:${comment.content}--来自用户:${comment.user.nickname}`); 325 | let data = await api.replyComment(reCommentMsg,comment.commentId,myMusic.id); 326 | if (data.info) { 327 | console.log(`✅回复粉丝评论成功!回复内容:${reCommentMsg}`); 328 | message += `✅回复粉丝评论成功!\n回复音乐:${myMusic.name}\n回复内容:${reCommentMsg}\n回复用户:${comment.user.nickname}\n`; 329 | } else { 330 | console.log("【错误❌】 回复粉丝评论失败! 原因:" + $.toStr(data.msg)); 331 | message += "❌回复粉丝评论失败!\n原因:" + $.toStr(data.msg) + "\n"; 332 | } 333 | } 334 | 335 | // 回复粉丝私信 336 | async function doRePrivatrMessage(){ 337 | if (getData("doRePrivatrMessage") == false ? true : false) { 338 | console.log("【通知】 已关闭执行回复粉丝私信!"); 339 | return; 340 | } 341 | console.log("【通知】 开始执行回复回复粉丝私信任务!"); 342 | 343 | let privatrMessageData = await api.getPrivatrMessageList(); 344 | let msgList = privatrMessageData.data.msgs; 345 | 346 | let index = Math.round(Math.random()*(msgList.length-1)); 347 | let msg = msgList[index]; 348 | let data = await api.sendPrivatrMessage(reMsg,msg.fromUser.userId); 349 | if ( data.info){ 350 | console.log(`✅回复粉丝私信成功!\n回复用户:${msg.fromUser.nickname}\n回复内容:${reMsg}`); 351 | message += `✅回复粉丝私信成功!\n回复用户:${msg.fromUser.nickname}\n回复内容:${reMsg}\n`; 352 | } else { 353 | console.log("【错误❌】 回复粉丝私信失败! 原因:" + $.toStr(data.msg)); 354 | message += "❌回复粉丝私信失败!\n原因:" + $.toStr(data.msg) + "\n"; 355 | } 356 | } 357 | 358 | //访问我的圈 359 | async function doViewMyCircle(){ 360 | if (getData("doViewMyCircle") == false ? true : false) { 361 | console.log("【通知】 已关闭执行访问我的云圈!"); 362 | return; 363 | } 364 | console.log("【通知】 开始执行回复访问我的云圈任务!"); 365 | let data = await api.getMusicianHome($.artistId); 366 | let blocks = data.data.data.blocks; 367 | let resourceId = null; 368 | for (let block of blocks) { 369 | if (block.showType == "MY_CIRCLE_WITH_MORE") { 370 | let creatives = block.creatives; 371 | for (let creative of creatives) { 372 | let resources = creative.resources; 373 | for (let resource of resources){ 374 | if (resource.resourceType == "CIRCLE") { 375 | resourceId = resource.resourceId; 376 | break; 377 | } 378 | if (resourceId) break; 379 | } 380 | if (resourceId) break; 381 | } 382 | } 383 | if (resourceId) break; 384 | } 385 | let result = await api.getCircle(resourceId); 386 | if (result.info){ 387 | console.log(`✅访问自己的云圈成功!`); 388 | message += `✅访问自己的云圈成功!\n`; 389 | } else { 390 | console.log("【错误❌】 访问自己的云圈失败! 原因:" + $.toStr(result.msg)); 391 | message += "❌访问自己的云圈失败!\n原因:" + $.toStr(result.msg) + "\n"; 392 | } 393 | 394 | } 395 | //发布主创说 396 | async function doCommentYourself(){ 397 | if (getData("doCommentYourself") == false ? true : false) { 398 | console.log("【通知】 已关闭执行发布主创说!"); 399 | return; 400 | } 401 | console.log("【通知】 开始执行主创说任务!"); 402 | let myAlbumData = await api.getMyAlbum(); 403 | let myAlbumList = myAlbumData.data.data.list; 404 | let myAlbumIndex = Math.round(Math.random()*(myAlbumList.length-1)); 405 | let album = myAlbumList[myAlbumIndex]; 406 | let myMusicData = await api.getMusicsByAlbum(album.id); 407 | let musicIndex = Math.round(Math.random()*(myMusicData.length-1)); 408 | let myMusic = myMusicData[musicIndex]; 409 | 410 | let result = await api.commentMusic(commentMsg,myMusic.id); 411 | if (result.info){ 412 | console.log(`✅发布主创说成功!\n发布内容:${commentMsg}\n发布歌曲:${myMusic.name}`); 413 | message += `✅发布主创说成功!\n发布内容:${commentMsg}\n发布歌曲:${myMusic.name}\n`; 414 | } else { 415 | console.log("【错误❌】 发布主创说失败! 原因:" + $.toStr(result.msg)); 416 | message += "❌发布主创说失败!\n原因:" + $.toStr(result.msg) + "\n"; 417 | } 418 | } 419 | // 执行观看课程任务 420 | async function doWatchLesson(){ 421 | if (getData("doWatchLesson") == false ? true : false) { 422 | console.log("【通知】 已关闭执行观看课程任务!"); 423 | return; 424 | } 425 | console.log("【通知】 开始观看课程任务!"); 426 | let result = await api.watchLesson(); 427 | if (result.info) { 428 | console.log("✅观看课程成功!"); 429 | message += "✅观看课程成功!\n"; 430 | } else { 431 | console.log("【错误❌】 观看课程失败! 原因:" + $.toStr(result.msg)); 432 | message += "❌观看课程失败!\n原因:" + $.toStr(result.msg) + "\n"; 433 | } 434 | } 435 | //领取已完成奖励 436 | async function getReword(){ 437 | console.log("【通知📢】", "待领取奖励: " + $.finishedTasks.length,"开始执行!"); 438 | for (let i = 0; i < $.finishedTasks.length; i++) { 439 | let result = await api.drawReward($.finishedTasks[i]); 440 | if (result.info){ 441 | console.log(`✅领取云豆成功!${$.finishedTasks[i].description}`); 442 | message += `✅领取云豆成功!${$.finishedTasks[i].description}\n\n`; 443 | } else { 444 | console.log("【错误❌】 领取云豆失败!"+ $.finishedTasks[i].description +" 原因:" + $.toStr(result.msg)); 445 | message += "❌领取云豆失败!" + $.finishedTasks[i].description + "原因:" + $.toStr(result.msg) + "\n\n"; 446 | } 447 | 448 | } 449 | } 450 | function getData(key = ""){ 451 | if (isPhone) { 452 | key = "wyy_" + key; 453 | return $.getdata(key); 454 | } else { 455 | let config = require("./wyy_config.js").wangyi; 456 | return config[key]; 457 | } 458 | } 459 | 460 | function setData(){ 461 | if (isPhone){ 462 | key = "wyy_" + key; 463 | return $.setdata(value,key); 464 | } 465 | return null; 466 | } 467 | 468 | // 网易云音乐api 469 | function NCApi() { 470 | return new class { 471 | checkToken = "9ca17ae2e6ffcda170e2e6ee92f94fa7ad9db4e14e8ca88eb7d54f929e9fbbf13f8b8a97aef74d86aca7acc62af0feaec3b92a8dac8ad6f66db2eda2d7fb5e928f8ab7d44a8aabf8abc1648a9797d7c548e996ee9e"; 472 | csrf_token = ""; 473 | cookie = ""; 474 | UA = "" 475 | 476 | /** 477 | * 发送请求 478 | * @param url 479 | * @param data 480 | * @returns {Promise} 481 | */ 482 | async request(url,data = {},addCookie = ""){ 483 | 484 | data.csrf_token = this.csrf_token; 485 | let opts = this.getOpts(data,url,null,addCookie); 486 | return new Promise(resolve => { 487 | let result = { 488 | code:301, 489 | info:false, 490 | data:{}, 491 | msg:"" 492 | } 493 | $.post(opts,(err,res,data)=>{ 494 | if (err){ 495 | result.msg = err; 496 | resolve(result); 497 | } 498 | data = $.toObj(data); 499 | if (data != null && data.code == 200){ 500 | result.code = data.code; 501 | result.info = true; 502 | result.data = data; 503 | resolve(result); 504 | } else { 505 | // result.code = data.code; 506 | result.msg = data; 507 | resolve(result); 508 | } 509 | }) 510 | }) 511 | } 512 | 513 | /** 514 | * 登录 data.profile.nickname 515 | * @param username 516 | * @param password 517 | * @return {Promise} 518 | */ 519 | async login(username,password){ 520 | let data = { 521 | checkToken:this.checkToken, 522 | phone: parseInt(username), 523 | csrf_token:"", 524 | password: md5(password), 525 | rememberLogin: 'true' 526 | } 527 | let opts = this.getOpts(data,"https://music.163.com/weapi/w/login/cellphone"); 528 | opts.headers.Cookie = "os=pc; osver=Microsoft-Windows-10-Professional-build-10586-64bit; appver=2.0.3.131777; channel=netease; __remember_me=true;"; 529 | return new Promise(resolve => { 530 | $.post(opts,(err,res,data)=>{ 531 | if (err){ 532 | resolve(false); 533 | } 534 | data = $.toObj(data); 535 | if (data != null && data.code == 200){ 536 | let cookie = res.headers["set-cookie"] + ""; 537 | cookie = cookie.match(/MUSIC_U=.+?;/) + cookie.match(/__csrf=.+?;/); 538 | this.csrf_token = cookie.match(/__csrf=(\w)+/)[0].substring(7); 539 | this.cookie = cookie; 540 | resolve(cookie); 541 | } else { 542 | resolve(false); 543 | } 544 | }) 545 | }) 546 | } 547 | /** 548 | * 获取云豆数量 549 | * @return {Promise} 550 | */ 551 | async getYDCount(){ 552 | return await this.request("https://music.163.com/weapi/cloudbean/get"); 553 | } 554 | 555 | /** 556 | * 获取音乐人信息 557 | * @return {Promise} 558 | */ 559 | async getMusicianInfo(){ 560 | return await this.request("https://music.163.com/weapi/nmusician/entrance/user/musician/info/get"); 561 | } 562 | 563 | /** 564 | * 获取音乐人每日任务列表 565 | * @return {Promise} 566 | */ 567 | async getMusicianDayTaskInfo(){ 568 | return await this.request("https://music.163.com/weapi/nmusician/workbench/mission/cycle/list"); 569 | 570 | } 571 | 572 | /** 573 | * 获取音乐人推荐任务列表 574 | * @return {Promise} 575 | */ 576 | async getMusicianRecommendTaskInfo(){ 577 | return await this.request("https://music.163.com/weapi/nmusician/workbench/mission/stage/list"); 578 | 579 | } 580 | 581 | /** 582 | * 观看课程 583 | * @return {Promise} 584 | */ 585 | async watchLesson(){ 586 | return await this.request("https://music.163.com/weapi/nmusician/workbench/creator/watch/college/lesson"); 587 | } 588 | 589 | 590 | /** 591 | * 发带歌单的动态 592 | * @param msg 593 | * @param playListId 594 | * @returns {Promise} data.list(任务列表) 595 | */ 596 | 597 | 598 | async shareBlog(msg = "",playListId = 0,type = "palyList"){ 599 | let data = { 600 | id:playListId, //music.id 601 | msg: msg, 602 | type: "playlist", 603 | //uuid: "publish-" + +(new Date) + oL3x(5) 604 | }; 605 | return await this.request("https://music.163.com/weapi/share/friends/resource",data); 606 | } 607 | 608 | /** 609 | * 音乐人签到 610 | * @return {Promise} 611 | * @constructor 612 | */ 613 | async signInMusician(){ 614 | return await this.request("https://music.163.com/weapi/creator/user/access"); 615 | } 616 | 617 | /** 618 | * 音乐人主页 619 | * @param artistId 620 | * @return {Promise} 621 | */ 622 | async getMusicianHome(artistId = ""){ 623 | let data = { 624 | artistId :artistId 625 | } 626 | return await this.request("https://music.163.com/weapi/personal/home/page/artist",data); 627 | } 628 | 629 | /** 630 | * 访问云圈 631 | * @param circleId 632 | * @return {Promise} 633 | */ 634 | async getCircle(circleId = ""){ 635 | let data = { 636 | circleId:circleId 637 | } 638 | return await this.request("https://music.163.com/weapi/circle/get",data); 639 | } 640 | /** 641 | * 获取音乐中的评论 642 | * @param musicId 643 | * @return {Promise} 644 | */ 645 | async getMusicComments(musicId){ 646 | let data = { 647 | cursor: "-1", 648 | offset: "0", 649 | orderType: "1", 650 | pageNo: "1", 651 | pageSize: "20", 652 | rid: "R_SO_4_" + musicId, 653 | threadId: "R_SO_4_" + musicId 654 | } 655 | return await this.request("https://music.163.com/weapi/comment/resource/comments/get",data); 656 | } 657 | 658 | /** 659 | * 评论音乐 660 | * @param msg 661 | * @param musicId 662 | * @return {Promise} 663 | */ 664 | async commentMusic(msg = "",musicId){ 665 | let data = { 666 | // checkToken: this.checkToken, 667 | content: msg, 668 | threadId: "R_SO_4_" + musicId 669 | }; 670 | return await this.request("https://music.163.com/weapi/resource/comments/add",data,"os=android"); 671 | 672 | } 673 | 674 | /** 675 | * 回复评论 676 | * @param msg 677 | * @param cid 678 | * @param mid 679 | * @return {Promise} 680 | */ 681 | async replyComment(msg = "",cid = 0,mid = 0){ 682 | let data = { 683 | // checkToken: this.checkToken, 684 | commentId: cid, 685 | content: msg, 686 | threadId: "R_SO_4_" + mid 687 | } 688 | return await this.request("https://music.163.com/weapi/v1/resource/comments/reply",data,"os=android"); 689 | } 690 | 691 | /** 692 | * 获取我发布的音乐列表 693 | * @return data.data.list(音乐列表) 694 | */ 695 | async getMyAlbum(){ 696 | return await this.request("https://music.163.com/weapi/nmusician/production/common/artist/album/item/list/get"); 697 | } 698 | /** 699 | * 搜索指定数量的音乐 700 | * @param num 音乐数量 701 | * @param keyWord 关键字 702 | * @returns {Promise} data.result.songs 703 | */ 704 | async getMusic(num,keyWord) { 705 | let data = { 706 | hlposttag: "", 707 | hlpretag: "", 708 | isPub: "true", 709 | limit: num, 710 | offset: "0", 711 | s: keyWord, 712 | total: "true", 713 | type: "1" 714 | }; 715 | return await this.request("https://music.163.com/weapi/cloudsearch/get/web",data); 716 | } 717 | async 718 | 719 | /** 720 | * 获取每日推荐歌单 721 | * @returns {Promise} data.recommend(歌单列表) 722 | */ 723 | async getRecommendedPlaylist(){ 724 | return await this.request("https://music.163.com/weapi/discovery/recommend/resource"); 725 | } 726 | 727 | /** 728 | * 领取云豆奖励 729 | * @param taskData 730 | * @returns {Promise} taskData.rewardWorth(云豆数量) 731 | */ 732 | async drawReward(taskData = {}){ 733 | //console.log($.log(taskData)) 734 | let userMissionId = taskData.userMissionId; 735 | let period = taskData.period; 736 | let data = { 737 | period: period, 738 | userMissionId: userMissionId 739 | } 740 | return await this.request("https://music.163.com//weapi/nmusician/workbench/mission/reward/obtain/new",data); 741 | } 742 | 743 | /** 744 | * 获取每日推荐歌曲 745 | * @returns {Promise} data.recommend(歌曲列表) 746 | */ 747 | async getPersonalizedMusic(){ 748 | let url = "https://music.163.com/weapi/v2/discovery/recommend/songs"; 749 | let data = { 750 | offset: "0", 751 | total: "true" 752 | }; 753 | return await this.request(url,data); 754 | } 755 | 756 | /** 757 | * 通过专辑id获取专辑歌曲列表 758 | * @param albumId 759 | * @param num 760 | * @return {Promise} 761 | */ 762 | async getMusicsByAlbum(albumId = 0,num = 10){ 763 | let opts = this.getOpts("",`http://music.163.com/api/album/${albumId}?ext=true&id=${albumId}&offset=0&total=true&limit=${num}`); 764 | return new Promise(resolve => { 765 | $.get(opts,(err,res,data)=>{ 766 | if (err){ 767 | resolve(null); 768 | } 769 | data = $.toObj(data); 770 | if (data != null && data.code == 200){ 771 | resolve(data.album.songs); 772 | } else { 773 | resolve(null); 774 | } 775 | }); 776 | }) 777 | } 778 | 779 | /** 780 | * 获取私信列表 781 | * @returns {Promise}data.msgs(信息列表) 782 | */ 783 | async getPrivatrMessageList(){ 784 | return await this.request("https://music.163.com/weapi/msg/private/users"); 785 | } 786 | 787 | /** 788 | * 发送文本私信 789 | * @param msg 790 | * @param userId 791 | * @returns {Promise} 792 | */ 793 | async sendPrivatrMessage(msg = "",userId = ""){ 794 | let data = { 795 | //checkToken: this.checkToken, 796 | msg: msg, 797 | //time: `${new Date().getTime()}`, 798 | type: "text", 799 | userIds: "[\""+ userId +"\"]" 800 | } 801 | let url = "https://music.163.com/weapi/msg/private/send"; 802 | return await this.request(url,data); 803 | 804 | } 805 | 806 | // 生成加密的body(params通过aes加密encSecKey可以为固定) 807 | getBody(data) { 808 | let nonce = "0CoJUm6Qyw8W8jud", 809 | vi = "0102030405060708", 810 | secretKey="TA3YiYCfY2dDJQgg", 811 | encSecKey="84ca47bca10bad09a6b04c5c927ef077d9b9f1e37098aa3eac6ea70eb59df0aa28b691b7e75e4f1f9831754919ea784c8f74fbfadf2898b0be17849fd656060162857830e241aba44991601f137624094c114ea8d17bce815b0cd4e5b8e2fbaba978c6d1d14dc3d1faf852bdd28818031ccdaaa13a6018e1024e2aae98844210"; 812 | const key1 = CryptoJS.enc.Utf8.parse(nonce); 813 | const key2 = CryptoJS.enc.Utf8.parse(secretKey); 814 | const iv = CryptoJS.enc.Utf8.parse(vi); 815 | let srcs1 = CryptoJS.enc.Utf8.parse(data); 816 | let encrypted1 = CryptoJS.AES.encrypt(srcs1, key1, {iv: iv, mode: CryptoJS.mode.CBC}); 817 | let baseData = encrypted1.ciphertext.toString(CryptoJS.enc.Base64); 818 | let srcs2 = CryptoJS.enc.Utf8.parse(baseData); 819 | let encrypted2 = CryptoJS.AES.encrypt(srcs2, key2, {iv: iv, mode: CryptoJS.mode.CBC, padding: CryptoJS.pad.Pkcs7}); 820 | return "params=" + encodeURIComponent(encrypted2.ciphertext.toString(CryptoJS.enc.Base64)) + "&encSecKey=" + encSecKey; 821 | } 822 | 823 | 824 | // 获取请求参数 825 | getOpts(data,url,method,addCookie = "") { 826 | data = $.toStr(data); 827 | let opts = { 828 | "method": "post", 829 | "url": `${url}?csrf_token=${this.csrf_token}`, 830 | "body": this.getBody(data), 831 | headers: { 832 | Accept: "*/*", 833 | "Accept-Encoding": "gzip, deflate, br", 834 | "Accept-Language": "zh-CN,zh;q=0.9,en;q=0.8,en-GB;q=0.7,en-US;q=0.6,", 835 | Connection: "keep-alive", 836 | "Content-Type": "application/x-www-form-urlencoded", 837 | Cookie: this.cookie + addCookie, 838 | DNT: "1", 839 | Host: "music.163.com", 840 | Origin: "https://music.163.com", 841 | Referer: "https://music.163.com", 842 | "User-Agent": this.UA ? this.UA :"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/99.0.4844.74 Safari/537.36 Edg/99.0.1150.55" 843 | } 844 | }; 845 | 846 | return opts; 847 | } 848 | } 849 | } 850 | // md5 851 | function md5(md5str){var createMD5String=function(string){var x=Array();var k,AA,BB,CC,DD,a,b,c,d;var S11=7,S12=12,S13=17,S14=22;var S21=5,S22=9,S23=14,S24=20;var S31=4,S32=11,S33=16,S34=23;var S41=6,S42=10,S43=15,S44=21;string=uTF8Encode(string);x=convertToWordArray(string);a=1732584193;b=4023233417;c=2562383102;d=271733878;for(k=0;k>>(32-iShiftBits))};var addUnsigned=function(lX,lY){var lX4,lY4,lX8,lY8,lResult;lX8=(lX&2147483648);lY8=(lY&2147483648);lX4=(lX&1073741824);lY4=(lY&1073741824);lResult=(lX&1073741823)+(lY&1073741823);if(lX4&lY4){return(lResult^2147483648^lX8^lY8)}if(lX4|lY4){if(lResult&1073741824){return(lResult^3221225472^lX8^lY8)}else{return(lResult^1073741824^lX8^lY8)}}else{return(lResult^lX8^lY8)}};var F=function(x,y,z){return(x&y)|((~x)&z)};var G=function(x,y,z){return(x&z)|(y&(~z))};var H=function(x,y,z){return(x^y^z)};var I=function(x,y,z){return(y^(x|(~z)))};var FF=function(a,b,c,d,x,s,ac){a=addUnsigned(a,addUnsigned(addUnsigned(F(b,c,d),x),ac));return addUnsigned(rotateLeft(a,s),b)};var GG=function(a,b,c,d,x,s,ac){a=addUnsigned(a,addUnsigned(addUnsigned(G(b,c,d),x),ac));return addUnsigned(rotateLeft(a,s),b)};var HH=function(a,b,c,d,x,s,ac){a=addUnsigned(a,addUnsigned(addUnsigned(H(b,c,d),x),ac));return addUnsigned(rotateLeft(a,s),b)};var II=function(a,b,c,d,x,s,ac){a=addUnsigned(a,addUnsigned(addUnsigned(I(b,c,d),x),ac));return addUnsigned(rotateLeft(a,s),b)};var convertToWordArray=function(string){var lWordCount;var lMessageLength=string.length;var lNumberOfWordsTempOne=lMessageLength+8;var lNumberOfWordsTempTwo=(lNumberOfWordsTempOne-(lNumberOfWordsTempOne%64))/64;var lNumberOfWords=(lNumberOfWordsTempTwo+1)*16;var lWordArray=Array(lNumberOfWords-1);var lBytePosition=0;var lByteCount=0;while(lByteCount>>29;return lWordArray};var wordToHex=function(lValue){var WordToHexValue="",WordToHexValueTemp="",lByte,lCount;for(lCount=0;lCount<=3;lCount++){lByte=(lValue>>>(lCount*8))&255;WordToHexValueTemp="0"+lByte.toString(16); 852 | WordToHexValue=WordToHexValue+WordToHexValueTemp.substr(WordToHexValueTemp.length-2,2)}return WordToHexValue};var uTF8Encode=function(string){string=string.toString().replace(/\x0d\x0a/g,"\x0a");var output="";for(var n=0;n127)&&(c<2048)){output+=String.fromCharCode((c>>6)|192);output+=String.fromCharCode((c&63)|128)}else{output+=String.fromCharCode((c>>12)|224);output+=String.fromCharCode(((c>>6)&63)|128);output+=String.fromCharCode((c&63)|128)}}}return output};return createMD5String(md5str)}; 853 | // Env 854 | function Env(t,e){class s{constructor(t){this.env=t}send(t,e="GET"){t="string"==typeof t?{url:t}:t;let s=this.get;return"POST"===e&&(s=this.post),new Promise((e,i)=>{s.call(this,t,(t,s,r)=>{t?i(t):e(s)})})}get(t){return this.send.call(this.env,t)}post(t){return this.send.call(this.env,t,"POST")}}return new class{constructor(t,e){this.name=t,this.http=new s(this),this.data=null,this.dataFile="box.dat",this.logs=[],this.isMute=!1,this.isNeedRewrite=!1,this.logSeparator="\n",this.encoding="utf-8",this.startTime=(new Date).getTime(),Object.assign(this,e),this.log("",`\ud83d\udd14${this.name}, \u5f00\u59cb!`)}isNode(){return"undefined"!=typeof module&&!!module.exports}isQuanX(){return"undefined"!=typeof $task}isSurge(){return"undefined"!=typeof $httpClient&&"undefined"==typeof $loon}isLoon(){return"undefined"!=typeof $loon}isShadowrocket(){return"undefined"!=typeof $rocket}toObj(t,e=null){try{return JSON.parse(t)}catch{return e}}toStr(t,e=null){try{return JSON.stringify(t)}catch{return e}}getjson(t,e){let s=e;const i=this.getdata(t);if(i)try{s=JSON.parse(this.getdata(t))}catch{}return s}setjson(t,e){try{return this.setdata(JSON.stringify(t),e)}catch{return!1}}getScript(t){return new Promise(e=>{this.get({url:t},(t,s,i)=>e(i))})}runScript(t,e){return new Promise(s=>{let i=this.getdata("@chavy_boxjs_userCfgs.httpapi");i=i?i.replace(/\n/g,"").trim():i;let r=this.getdata("@chavy_boxjs_userCfgs.httpapi_timeout");r=r?1*r:20,r=e&&e.timeout?e.timeout:r;const[o,h]=i.split("@"),n={url:`http://${h}/v1/scripting/evaluate`,body:{script_text:t,mock_type:"cron",timeout:r},headers:{"X-Key":o,Accept:"*/*"}};this.post(n,(t,e,i)=>s(i))}).catch(t=>this.logErr(t))}loaddata(){if(!this.isNode())return{};{this.fs=this.fs?this.fs:require("fs"),this.path=this.path?this.path:require("path");const t=this.path.resolve(this.dataFile),e=this.path.resolve(process.cwd(),this.dataFile),s=this.fs.existsSync(t),i=!s&&this.fs.existsSync(e);if(!s&&!i)return{};{const i=s?t:e;try{return JSON.parse(this.fs.readFileSync(i))}catch(t){return{}}}}}writedata(){if(this.isNode()){this.fs=this.fs?this.fs:require("fs"),this.path=this.path?this.path:require("path");const t=this.path.resolve(this.dataFile),e=this.path.resolve(process.cwd(),this.dataFile),s=this.fs.existsSync(t),i=!s&&this.fs.existsSync(e),r=JSON.stringify(this.data);s?this.fs.writeFileSync(t,r):i?this.fs.writeFileSync(e,r):this.fs.writeFileSync(t,r)}}lodash_get(t,e,s){const i=e.replace(/\[(\d+)\]/g,".$1").split(".");let r=t;for(const t of i)if(r=Object(r)[t],void 0===r)return s;return r}lodash_set(t,e,s){return Object(t)!==t?t:(Array.isArray(e)||(e=e.toString().match(/[^.[\]]+/g)||[]),e.slice(0,-1).reduce((t,s,i)=>Object(t[s])===t[s]?t[s]:t[s]=Math.abs(e[i+1])>>0==+e[i+1]?[]:{},t)[e[e.length-1]]=s,t)}getdata(t){let e=this.getval(t);if(/^@/.test(t)){const[,s,i]=/^@(.*?)\.(.*?)$/.exec(t),r=s?this.getval(s):"";if(r)try{const t=JSON.parse(r);e=t?this.lodash_get(t,i,""):e}catch(t){e=""}}return e}setdata(t,e){let s=!1;if(/^@/.test(e)){const[,i,r]=/^@(.*?)\.(.*?)$/.exec(e),o=this.getval(i),h=i?"null"===o?null:o||"{}":"{}";try{const e=JSON.parse(h);this.lodash_set(e,r,t),s=this.setval(JSON.stringify(e),i)}catch(e){const o={};this.lodash_set(o,r,t),s=this.setval(JSON.stringify(o),i)}}else s=this.setval(t,e);return s}getval(t){return this.isSurge()||this.isLoon()?$persistentStore.read(t):this.isQuanX()?$prefs.valueForKey(t):this.isNode()?(this.data=this.loaddata(),this.data[t]):this.data&&this.data[t]||null}setval(t,e){return this.isSurge()||this.isLoon()?$persistentStore.write(t,e):this.isQuanX()?$prefs.setValueForKey(t,e):this.isNode()?(this.data=this.loaddata(),this.data[e]=t,this.writedata(),!0):this.data&&this.data[e]||null}initGotEnv(t){this.got=this.got?this.got:require("got"),this.cktough=this.cktough?this.cktough:require("tough-cookie"),this.ckjar=this.ckjar?this.ckjar:new this.cktough.CookieJar,t&&(t.headers=t.headers?t.headers:{},void 0===t.headers.Cookie&&void 0===t.cookieJar&&(t.cookieJar=this.ckjar))}get(t,e=(()=>{})){if(t.headers&&(delete t.headers["Content-Type"],delete t.headers["Content-Length"]),this.isSurge()||this.isLoon())this.isSurge()&&this.isNeedRewrite&&(t.headers=t.headers||{},Object.assign(t.headers,{"X-Surge-Skip-Scripting":!1})),$httpClient.get(t,(t,s,i)=>{!t&&s&&(s.body=i,s.statusCode=s.status),e(t,s,i)});else if(this.isQuanX())this.isNeedRewrite&&(t.opts=t.opts||{},Object.assign(t.opts,{hints:!1})),$task.fetch(t).then(t=>{const{statusCode:s,statusCode:i,headers:r,body:o}=t;e(null,{status:s,statusCode:i,headers:r,body:o},o)},t=>e(t));else if(this.isNode()){let s=require("iconv-lite");this.initGotEnv(t),this.got(t).on("redirect",(t,e)=>{try{if(t.headers["set-cookie"]){const s=t.headers["set-cookie"].map(this.cktough.Cookie.parse).toString();s&&this.ckjar.setCookieSync(s,null),e.cookieJar=this.ckjar}}catch(t){this.logErr(t)}}).then(t=>{const{statusCode:i,statusCode:r,headers:o,rawBody:h}=t;e(null,{status:i,statusCode:r,headers:o,rawBody:h},s.decode(h,this.encoding))},t=>{const{message:i,response:r}=t;e(i,r,r&&s.decode(r.rawBody,this.encoding))})}}post(t,e=(()=>{})){const s=t.method?t.method.toLocaleLowerCase():"post";if(t.body&&t.headers&&!t.headers["Content-Type"]&&(t.headers["Content-Type"]="application/x-www-form-urlencoded"),t.headers&&delete t.headers["Content-Length"],this.isSurge()||this.isLoon())this.isSurge()&&this.isNeedRewrite&&(t.headers=t.headers||{},Object.assign(t.headers,{"X-Surge-Skip-Scripting":!1})),$httpClient[s](t,(t,s,i)=>{!t&&s&&(s.body=i,s.statusCode=s.status),e(t,s,i)});else if(this.isQuanX())t.method=s,this.isNeedRewrite&&(t.opts=t.opts||{},Object.assign(t.opts,{hints:!1})),$task.fetch(t).then(t=>{const{statusCode:s,statusCode:i,headers:r,body:o}=t;e(null,{status:s,statusCode:i,headers:r,body:o},o)},t=>e(t));else if(this.isNode()){let i=require("iconv-lite");this.initGotEnv(t);const{url:r,...o}=t;this.got[s](r,o).then(t=>{const{statusCode:s,statusCode:r,headers:o,rawBody:h}=t;e(null,{status:s,statusCode:r,headers:o,rawBody:h},i.decode(h,this.encoding))},t=>{const{message:s,response:r}=t;e(s,r,r&&i.decode(r.rawBody,this.encoding))})}}time(t,e=null){const s=e?new Date(e):new Date;let i={"M+":s.getMonth()+1,"d+":s.getDate(),"H+":s.getHours(),"m+":s.getMinutes(),"s+":s.getSeconds(),"q+":Math.floor((s.getMonth()+3)/3),S:s.getMilliseconds()};/(y+)/.test(t)&&(t=t.replace(RegExp.$1,(s.getFullYear()+"").substr(4-RegExp.$1.length)));for(let e in i)new RegExp("("+e+")").test(t)&&(t=t.replace(RegExp.$1,1==RegExp.$1.length?i[e]:("00"+i[e]).substr((""+i[e]).length)));return t}msg(e=t,s="",i="",r){const o=t=>{if(!t)return t;if("string"==typeof t)return this.isLoon()?t:this.isQuanX()?{"open-url":t}:this.isSurge()?{url:t}:void 0;if("object"==typeof t){if(this.isLoon()){let e=t.openUrl||t.url||t["open-url"],s=t.mediaUrl||t["media-url"];return{openUrl:e,mediaUrl:s}}if(this.isQuanX()){let e=t["open-url"]||t.url||t.openUrl,s=t["media-url"]||t.mediaUrl;return{"open-url":e,"media-url":s}}if(this.isSurge()){let e=t.url||t.openUrl||t["open-url"];return{url:e}}}};if(this.isMute||(this.isSurge()||this.isLoon()?$notification.post(e,s,i,o(r)):this.isQuanX()&&$notify(e,s,i,o(r))),!this.isMuteLog){let t=["","==============\ud83d\udce3\u7cfb\u7edf\u901a\u77e5\ud83d\udce3=============="];t.push(e),s&&t.push(s),i&&t.push(i),console.log(t.join("\n")),this.logs=this.logs.concat(t)}}log(...t){t.length>0&&(this.logs=[...this.logs,...t]),console.log(t.join(this.logSeparator))}logErr(t,e){const s=!this.isSurge()&&!this.isQuanX()&&!this.isLoon();s?this.log("",`\u2757\ufe0f${this.name}, \u9519\u8bef!`,t.stack):this.log("",`\u2757\ufe0f${this.name}, \u9519\u8bef!`,t)}wait(t){return new Promise(e=>setTimeout(e,t))}done(t={}){const e=(new Date).getTime(),s=(e-this.startTime)/1e3;this.log("",`\ud83d\udd14${this.name}, \u7ed3\u675f! \ud83d\udd5b ${s} \u79d2`),this.log(),(this.isSurge()||this.isQuanX()||this.isLoon())&&$done(t)}}(t,e)} 855 | 856 | -------------------------------------------------------------------------------- /Quantumult/wozaixiaoyuan/cookie_wzxy.js: -------------------------------------------------------------------------------- 1 | /** 2 | * 我在校园健康打卡cookie获取脚本 3 | * 配置方式 4 | #quanx 5 | [rewrite_local] 6 | https:\/\/gw\.wozaixiaoyuan\.com\/basicinfo\/mobile\/my\/index url script-request-header https://raw.githubusercontent.com/laoxinH/MyScript/main/Quantumult/wozaixiaoyuan/cookie_wzxy.js 7 | 8 | [mitm] 9 | hostname = gw.woziaxiaoyuan.com 10 | * 11 | */ 12 | 13 | const $laoxin = new Env("我在校园cookie获取"); 14 | const cookieKey = 'wzxy_cookie'; 15 | const cookieVal = $request.headers['JWSESSION']; // 获取jwsession 16 | if (cookieVal) { 17 | const cookie = cookieVal; 18 | const UA = $request.headers["User-Agent"]; 19 | if ($laoxin.setdata(cookie, cookieKey)) { 20 | $laoxin.setdata(UA,"wzxy_UA"); 21 | $laoxin.msg(`${$laoxin.name}`, '获取JWSESSION: 成功', `cookie:${cookieVal}`, "获取成功"); 22 | $laoxin.log(`[${$laoxin.name}] 获取JWSESSION: 成功, cookie: ${cookieVal}`); 23 | } else { 24 | $laoxin.msg(`${$laoxin.name}`, '获取JWSESSION: 失败', `请重新获取`, "获取失败"); 25 | } 26 | } 27 | $laoxin.done(); 28 | 29 | function Env(t,e){class s{constructor(t){this.env=t}send(t,e="GET"){t="string"==typeof t?{url:t}:t;let s=this.get;return"POST"===e&&(s=this.post),new Promise((e,i)=>{s.call(this,t,(t,s,r)=>{t?i(t):e(s)})})}get(t){return this.send.call(this.env,t)}post(t){return this.send.call(this.env,t,"POST")}}return new class{constructor(t,e){this.name=t,this.http=new s(this),this.data=null,this.dataFile="box.dat",this.logs=[],this.isMute=!1,this.isNeedRewrite=!1,this.logSeparator="\n",this.encoding="utf-8",this.startTime=(new Date).getTime(),Object.assign(this,e),this.log("",`\ud83d\udd14${this.name}, \u5f00\u59cb!`)}isNode(){return"undefined"!=typeof module&&!!module.exports}isQuanX(){return"undefined"!=typeof $task}isSurge(){return"undefined"!=typeof $httpClient&&"undefined"==typeof $loon}isLoon(){return"undefined"!=typeof $loon}isShadowrocket(){return"undefined"!=typeof $rocket}toObj(t,e=null){try{return JSON.parse(t)}catch{return e}}toStr(t,e=null){try{return JSON.stringify(t)}catch{return e}}getjson(t,e){let s=e;const i=this.getdata(t);if(i)try{s=JSON.parse(this.getdata(t))}catch{}return s}setjson(t,e){try{return this.setdata(JSON.stringify(t),e)}catch{return!1}}getScript(t){return new Promise(e=>{this.get({url:t},(t,s,i)=>e(i))})}runScript(t,e){return new Promise(s=>{let i=this.getdata("@chavy_boxjs_userCfgs.httpapi");i=i?i.replace(/\n/g,"").trim():i;let r=this.getdata("@chavy_boxjs_userCfgs.httpapi_timeout");r=r?1*r:20,r=e&&e.timeout?e.timeout:r;const[o,h]=i.split("@"),n={url:`http://${h}/v1/scripting/evaluate`,body:{script_text:t,mock_type:"cron",timeout:r},headers:{"X-Key":o,Accept:"*/*"}};this.post(n,(t,e,i)=>s(i))}).catch(t=>this.logErr(t))}loaddata(){if(!this.isNode())return{};{this.fs=this.fs?this.fs:require("fs"),this.path=this.path?this.path:require("path");const t=this.path.resolve(this.dataFile),e=this.path.resolve(process.cwd(),this.dataFile),s=this.fs.existsSync(t),i=!s&&this.fs.existsSync(e);if(!s&&!i)return{};{const i=s?t:e;try{return JSON.parse(this.fs.readFileSync(i))}catch(t){return{}}}}}writedata(){if(this.isNode()){this.fs=this.fs?this.fs:require("fs"),this.path=this.path?this.path:require("path");const t=this.path.resolve(this.dataFile),e=this.path.resolve(process.cwd(),this.dataFile),s=this.fs.existsSync(t),i=!s&&this.fs.existsSync(e),r=JSON.stringify(this.data);s?this.fs.writeFileSync(t,r):i?this.fs.writeFileSync(e,r):this.fs.writeFileSync(t,r)}}lodash_get(t,e,s){const i=e.replace(/\[(\d+)\]/g,".$1").split(".");let r=t;for(const t of i)if(r=Object(r)[t],void 0===r)return s;return r}lodash_set(t,e,s){return Object(t)!==t?t:(Array.isArray(e)||(e=e.toString().match(/[^.[\]]+/g)||[]),e.slice(0,-1).reduce((t,s,i)=>Object(t[s])===t[s]?t[s]:t[s]=Math.abs(e[i+1])>>0==+e[i+1]?[]:{},t)[e[e.length-1]]=s,t)}getdata(t){let e=this.getval(t);if(/^@/.test(t)){const[,s,i]=/^@(.*?)\.(.*?)$/.exec(t),r=s?this.getval(s):"";if(r)try{const t=JSON.parse(r);e=t?this.lodash_get(t,i,""):e}catch(t){e=""}}return e}setdata(t,e){let s=!1;if(/^@/.test(e)){const[,i,r]=/^@(.*?)\.(.*?)$/.exec(e),o=this.getval(i),h=i?"null"===o?null:o||"{}":"{}";try{const e=JSON.parse(h);this.lodash_set(e,r,t),s=this.setval(JSON.stringify(e),i)}catch(e){const o={};this.lodash_set(o,r,t),s=this.setval(JSON.stringify(o),i)}}else s=this.setval(t,e);return s}getval(t){return this.isSurge()||this.isLoon()?$persistentStore.read(t):this.isQuanX()?$prefs.valueForKey(t):this.isNode()?(this.data=this.loaddata(),this.data[t]):this.data&&this.data[t]||null}setval(t,e){return this.isSurge()||this.isLoon()?$persistentStore.write(t,e):this.isQuanX()?$prefs.setValueForKey(t,e):this.isNode()?(this.data=this.loaddata(),this.data[e]=t,this.writedata(),!0):this.data&&this.data[e]||null}initGotEnv(t){this.got=this.got?this.got:require("got"),this.cktough=this.cktough?this.cktough:require("tough-cookie"),this.ckjar=this.ckjar?this.ckjar:new this.cktough.CookieJar,t&&(t.headers=t.headers?t.headers:{},void 0===t.headers.Cookie&&void 0===t.cookieJar&&(t.cookieJar=this.ckjar))}get(t,e=(()=>{})){if(t.headers&&(delete t.headers["Content-Type"],delete t.headers["Content-Length"]),this.isSurge()||this.isLoon())this.isSurge()&&this.isNeedRewrite&&(t.headers=t.headers||{},Object.assign(t.headers,{"X-Surge-Skip-Scripting":!1})),$httpClient.get(t,(t,s,i)=>{!t&&s&&(s.body=i,s.statusCode=s.status),e(t,s,i)});else if(this.isQuanX())this.isNeedRewrite&&(t.opts=t.opts||{},Object.assign(t.opts,{hints:!1})),$task.fetch(t).then(t=>{const{statusCode:s,statusCode:i,headers:r,body:o}=t;e(null,{status:s,statusCode:i,headers:r,body:o},o)},t=>e(t));else if(this.isNode()){let s=require("iconv-lite");this.initGotEnv(t),this.got(t).on("redirect",(t,e)=>{try{if(t.headers["set-cookie"]){const s=t.headers["set-cookie"].map(this.cktough.Cookie.parse).toString();s&&this.ckjar.setCookieSync(s,null),e.cookieJar=this.ckjar}}catch(t){this.logErr(t)}}).then(t=>{const{statusCode:i,statusCode:r,headers:o,rawBody:h}=t;e(null,{status:i,statusCode:r,headers:o,rawBody:h},s.decode(h,this.encoding))},t=>{const{message:i,response:r}=t;e(i,r,r&&s.decode(r.rawBody,this.encoding))})}}post(t,e=(()=>{})){const s=t.method?t.method.toLocaleLowerCase():"post";if(t.body&&t.headers&&!t.headers["Content-Type"]&&(t.headers["Content-Type"]="application/x-www-form-urlencoded"),t.headers&&delete t.headers["Content-Length"],this.isSurge()||this.isLoon())this.isSurge()&&this.isNeedRewrite&&(t.headers=t.headers||{},Object.assign(t.headers,{"X-Surge-Skip-Scripting":!1})),$httpClient[s](t,(t,s,i)=>{!t&&s&&(s.body=i,s.statusCode=s.status),e(t,s,i)});else if(this.isQuanX())t.method=s,this.isNeedRewrite&&(t.opts=t.opts||{},Object.assign(t.opts,{hints:!1})),$task.fetch(t).then(t=>{const{statusCode:s,statusCode:i,headers:r,body:o}=t;e(null,{status:s,statusCode:i,headers:r,body:o},o)},t=>e(t));else if(this.isNode()){let i=require("iconv-lite");this.initGotEnv(t);const{url:r,...o}=t;this.got[s](r,o).then(t=>{const{statusCode:s,statusCode:r,headers:o,rawBody:h}=t;e(null,{status:s,statusCode:r,headers:o,rawBody:h},i.decode(h,this.encoding))},t=>{const{message:s,response:r}=t;e(s,r,r&&i.decode(r.rawBody,this.encoding))})}}time(t,e=null){const s=e?new Date(e):new Date;let i={"M+":s.getMonth()+1,"d+":s.getDate(),"H+":s.getHours(),"m+":s.getMinutes(),"s+":s.getSeconds(),"q+":Math.floor((s.getMonth()+3)/3),S:s.getMilliseconds()};/(y+)/.test(t)&&(t=t.replace(RegExp.$1,(s.getFullYear()+"").substr(4-RegExp.$1.length)));for(let e in i)new RegExp("("+e+")").test(t)&&(t=t.replace(RegExp.$1,1==RegExp.$1.length?i[e]:("00"+i[e]).substr((""+i[e]).length)));return t}msg(e=t,s="",i="",r){const o=t=>{if(!t)return t;if("string"==typeof t)return this.isLoon()?t:this.isQuanX()?{"open-url":t}:this.isSurge()?{url:t}:void 0;if("object"==typeof t){if(this.isLoon()){let e=t.openUrl||t.url||t["open-url"],s=t.mediaUrl||t["media-url"];return{openUrl:e,mediaUrl:s}}if(this.isQuanX()){let e=t["open-url"]||t.url||t.openUrl,s=t["media-url"]||t.mediaUrl;return{"open-url":e,"media-url":s}}if(this.isSurge()){let e=t.url||t.openUrl||t["open-url"];return{url:e}}}};if(this.isMute||(this.isSurge()||this.isLoon()?$notification.post(e,s,i,o(r)):this.isQuanX()&&$notify(e,s,i,o(r))),!this.isMuteLog){let t=["","==============\ud83d\udce3\u7cfb\u7edf\u901a\u77e5\ud83d\udce3=============="];t.push(e),s&&t.push(s),i&&t.push(i),console.log(t.join("\n")),this.logs=this.logs.concat(t)}}log(...t){t.length>0&&(this.logs=[...this.logs,...t]),console.log(t.join(this.logSeparator))}logErr(t,e){const s=!this.isSurge()&&!this.isQuanX()&&!this.isLoon();s?this.log("",`\u2757\ufe0f${this.name}, \u9519\u8bef!`,t.stack):this.log("",`\u2757\ufe0f${this.name}, \u9519\u8bef!`,t)}wait(t){return new Promise(e=>setTimeout(e,t))}done(t={}){const e=(new Date).getTime(),s=(e-this.startTime)/1e3;this.log("",`\ud83d\udd14${this.name}, \u7ed3\u675f! \ud83d\udd5b ${s} \u79d2`),this.log(),(this.isSurge()||this.isQuanX()||this.isLoon())&&$done(t)}}(t,e)} 30 | -------------------------------------------------------------------------------- /Quantumult/wozaixiaoyuan/icon.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/laoxinH/MyScript/2580340cb5d866f29d3cbee4c43847a2d436a871/Quantumult/wozaixiaoyuan/icon.jpg -------------------------------------------------------------------------------- /Quantumult/wozaixiaoyuan/wzxy_health.js: -------------------------------------------------------------------------------- 1 | /** 2 | * 我在校园健康打卡 3 | * @author: github@laoxinH 4 | * @version: 1.0 5 | * 每天10点10分执行自动打卡 6 | ==============cookie获取方式=================== 7 | 打开我在校园微信小程序--"我的",脚本将会自动获取,当看到通知获取成功时即可 8 | ===============配置方式========================= 9 | ===#quanx==== 10 | [rewrite_local] 11 | https:\/\/gw\.wozaixiaoyuan\.com\/basicinfo\/mobile\/my\/index url script-request-header https://raw.githubusercontent.com/laoxinH/MyScript/main/Quantumult/wozaixiaoyuan/cookie_wzxy.js 12 | ======================================== 13 | [mitm] 14 | hostname = gw.woziaxiaoyuan.com 15 | ======================================== 16 | [task_local] 17 | 10 10 * * * https://raw.githubusercontent.com/laoxinH/MyScript/main/Quantumult/wozaixiaoyuan/wzxy_health.js, tag=我在校园健康打卡, img-url=https://github.com/laoxinH/MyScript/blob/main/Quantumult/wozaixiaoyuan/icon.jpg?raw=true, enabled=true 18 | 19 | =======boxjs订阅地址======= 20 | https://raw.githubusercontent.com/laoxinH/MyScript/main/boxjs/laoxin.boxjs.json 21 | **********************提示************************* 22 | * * 23 | ** *其中设涉及填写的内容,node需要手动填写,ios参考注释* ** 24 | * * 25 | ******* ***************** **************** 26 | * */ 27 | const $ = new Env("我在校园健康打卡"); 28 | 29 | const isPhone = !$.isNode() || $.isLoon() || $.isQuanX() || $.isSurge(); // 环境检测 30 | let message = ""; 31 | // 初始化脚本 32 | console.log("【通知📢】 开始初始化脚本, 当前环境 : " + (isPhone ? "手机端" : "nodejs"),"开始执行!"); 33 | let JWSESSION = getData("cookie"); 34 | let UA = getData("UA"); 35 | 36 | const api = new Api(JWSESSION,UA); 37 | 38 | 39 | 40 | !(async () => { 41 | let flag = await getUserInfo().catch(e=>{ 42 | console.log(e)}); 43 | if (flag) { 44 | await getRegNum().catch(e=>{ 45 | console.log(e)}); 46 | await register().catch(e=>{ 47 | console.log(e)}) 48 | } 49 | await sendNotify().catch(e=>{ 50 | console.log(e)}); 51 | $.done(); 52 | 53 | })() 54 | 55 | 56 | 57 | //签到 58 | async function register() { 59 | console.log("【通知📢】开始健康打卡!"); 60 | 61 | let longitude = getData("longitude"); 62 | let latitude = getData("latitude"); 63 | let result = await api.getLocation(latitude,longitude); 64 | //return; 65 | 66 | if (result.info) { 67 | let data = { 68 | answers: "" || $.toStr(getData("answers")), // 填写答案,格式["0","0","0","2","3","2"] 69 | longitude: "" || getData("longitude"), // 经度 70 | latitude: "" || getData("latitude"), // 纬度 71 | country: "" || result.country, // 国家 72 | city: "" || result.city, // 城市 73 | district: "" || result.district, // 区(县) 74 | province: "" || result.province, // 省 75 | township: "" || result.township, // 街道(镇) 如东城街道(大塘镇) 76 | street: "" || result.street, // 街 77 | areacode: "" || result.areacode // 区域代码 78 | } 79 | if (isPhone){ 80 | data.answers = data.answers.replaceAll("\\",""); 81 | data.answers = data.answers.replaceAll("\"",""); 82 | } 83 | 84 | let info = await api.save(data); 85 | if (info.info && info.data.code == 0){ 86 | $.subTitle = "✅打卡成功"; 87 | console.log("打卡成功!"); 88 | message += "【打卡】 成功!\n" + 89 | "位置: " + data.province + data.city + data.district + data.township + data.street + 90 | "\n日期: " + $.time("yyyy-MM-dd"); 91 | } else { 92 | $.subTitle = "❌打卡失败"; 93 | console.log("【错误❌】打卡失败!原因: " + $.toStr(info.data)); 94 | message += "【打卡】 失败! 原因: " + $.toStr(info.data) + "\n"; 95 | } 96 | } else { 97 | $.subTitle = "❌获取位置信息失败!"; 98 | console.log("【错误❌】获取位置信息失败! 原因: " + $.toStr(result.data)); 99 | message += "【打卡】 失败! 原因: 获取位置信息失败!\n"; 100 | 101 | } 102 | 103 | } 104 | 105 | // 获取签到次数 106 | async function getRegNum() { 107 | console.log("【通知📢】开始获取签到次数"); 108 | let data = await api.getHealthLatest(); 109 | if (data.info = true && data.data.code == 0){ 110 | data = data.data.data.list; 111 | $.log(`已签到次数:${data.length}`); 112 | message += "【打卡次数】 " + data.length + "\n"; 113 | } else { 114 | console.log("【错误❌】签到次数获取失败, 原因: " + $.toStr(data.data)); 115 | message += "【打卡次数】 获取失败, 原因: " + $.toStr(data.data) + "\n"; 116 | } 117 | } 118 | 119 | // 获取用户信息 120 | async function getUserInfo(){ 121 | console.log("【通知📢】开始获取用户信息"); 122 | //https://gw.wozaixiaoyuan.com/basicinfo/mobile/my/index 123 | 124 | let info = await api.getUserInfo(); 125 | if (info.info && info.data.code == 0){ 126 | let data = info.data.data; 127 | console.log("用户名: " + data.username); 128 | message += "【用户】 " + data.username + "\n"; 129 | return true; 130 | } else if (info.info && info.data.code == 102){ 131 | console.log("【错误❌】用户信息获取失败, 原因: cookie已失效"); 132 | $.subTitle = "cookie失效,请重新获取!" 133 | message += "cookie已失效,qunx等手机用户请打开我在校园小程序按照教程重新获取,nodejs用户请到配置文件中填写新的cookie\n"; 134 | setData(cookie,""); 135 | return false; 136 | } else { 137 | console.log("【错误❌】用户信息获取失败, 原因: " + $.toStr(info.data)); 138 | return true; 139 | } 140 | } 141 | 142 | async function sendNotify(){ 143 | $.msg($.name,$.subTitle,message); 144 | if (!isPhone) { 145 | require("./sendNotify").sendNotify($.name,message); 146 | } 147 | } 148 | 149 | /** 150 | * 获取配置信息 151 | * @param key 152 | * @return {*} 153 | */ 154 | function getData(key = ""){ 155 | if (isPhone) { 156 | key = "wzxy_" + key; 157 | return $.getdata(key); 158 | } else { 159 | let config = require("./wzxy_config.js"); 160 | return config[key]; 161 | } 162 | } 163 | function setData(key = "",value){ 164 | if (isPhone){ 165 | key = "wzxy_" + key; 166 | return $.setdata(value,key); 167 | } 168 | return null; 169 | } 170 | 171 | function Api(JWSESSION = "",UA = ""){ 172 | 173 | return new class { 174 | JWSESSION = JWSESSION; 175 | UA = UA 176 | // 发送请求 177 | async request(type = "",data = {}){ 178 | let opts =this.getRequestData(type,data); 179 | //delete opts.headers.Host; 180 | return new Promise(resolve => { 181 | $.post(opts,(err,resp,data)=>{ 182 | let result = { 183 | info: false, 184 | data: "" 185 | } 186 | if (err) { 187 | result.message = err; 188 | }; 189 | data = $.toObj(data); 190 | if (data){ 191 | result.info = true; 192 | result.data = data; 193 | } 194 | resolve(result); 195 | }); 196 | }); 197 | } 198 | 199 | // 获取用户信息 200 | async getUserInfo(){ 201 | return await this.request("basicinfo/mobile/my/index",null); 202 | }; 203 | 204 | // 获取签到历史 205 | async getHealthLatest(){ 206 | return await this.request("health/getHealthLatest.json",null); 207 | } 208 | 209 | // 签到 210 | async save(data = {}){ 211 | return await this.request("health/save.json",data); 212 | } 213 | 214 | // 获取位置信息 215 | async getLocation(latitude,longitude){ 216 | const url = `https://restapi.amap.com/v3/geocode/regeo?key=5df7fee749f489424dd417dfcb792b45&location=${longitude}%2C${latitude}&extensions=all&s=rsx&platform=WXJS&appname=5df7fee749f489424dd417dfcb792b45&sdkversion=1.2.0&logversion=2.0`; 217 | //$laoxin.msg("数据获取","data",url); 218 | let data = await this.request(url,null); 219 | 220 | let result = {}; 221 | if (data.info == true && data.data.status == 1){ 222 | data = data.data; 223 | result.info = true; 224 | result.areacode = data.regeocode.addressComponent.adcode; 225 | result.city = data.regeocode.addressComponent.city; 226 | result.country = data.regeocode.addressComponent.country; 227 | result.district = data.regeocode.addressComponent.district; 228 | result.province = data.regeocode.addressComponent.province; 229 | result.township = data.regeocode.addressComponent.township; 230 | result.street = data.regeocode.addressComponent.streetNumber.street; 231 | } else { 232 | result.info = false; 233 | result.data = data.data; 234 | } 235 | return result; 236 | } 237 | 238 | 239 | // 生成请求参数 240 | getRequestData(type, body = {}) { 241 | 242 | try{ 243 | let stringBody = ""; 244 | for (let key in body) { 245 | stringBody += (key + "=" + body[key] + "&"); 246 | } 247 | body = encodeURI(stringBody.substr(0, stringBody.length - 1)); 248 | 249 | } catch (e){ 250 | // TO DO... 251 | console.log("参数异常"); 252 | console.log(e) 253 | return null; 254 | } 255 | 256 | const url = type.indexOf("http") != -1 ? type : `https://student.wozaixiaoyuan.com/${type}`; 257 | const headers = { 258 | "Content-Type": "application/x-www-form-urlencoded", 259 | "Accept": "*/*", 260 | "Accept-Encoding": "gzip, deflate, br", 261 | "Accept-Language": "zh-cn", 262 | "Connection": "keep-alive", 263 | "User-Agent": this.UA ? this.UA : "Mozilla/5.0 (iPad; CPU OS 14_6 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148 MicroMessenger/8.0.9(0x18000929) NetType/WIFI Language/zh_CN", 264 | "Referer": "https://servicewechat.com/wxce6d08f781975d91/176/page-frame.html", 265 | //"token": "3b4ed663-8e59-44c2-b891-dcc70816315f", 266 | "Content-Length": "350", 267 | "Cookie": "[object Null]", 268 | "JWSESSION": this.JWSESSION 269 | }; 270 | if (url.indexOf("http") == -1) { 271 | headers.Host = "student.wozaixiaoyuan.com"; 272 | } 273 | return {url: url, headers: headers, body: body}; 274 | } 275 | 276 | } 277 | 278 | } 279 | 280 | function Env(t,e){class s{constructor(t){this.env=t}send(t,e="GET"){t="string"==typeof t?{url:t}:t;let s=this.get;return"POST"===e&&(s=this.post),new Promise((e,i)=>{s.call(this,t,(t,s,r)=>{t?i(t):e(s)})})}get(t){return this.send.call(this.env,t)}post(t){return this.send.call(this.env,t,"POST")}}return new class{constructor(t,e){this.name=t,this.http=new s(this),this.data=null,this.dataFile="box.dat",this.logs=[],this.isMute=!1,this.isNeedRewrite=!1,this.logSeparator="\n",this.encoding="utf-8",this.startTime=(new Date).getTime(),Object.assign(this,e),this.log("",`\ud83d\udd14${this.name}, \u5f00\u59cb!`)}isNode(){return"undefined"!=typeof module&&!!module.exports}isQuanX(){return"undefined"!=typeof $task}isSurge(){return"undefined"!=typeof $httpClient&&"undefined"==typeof $loon}isLoon(){return"undefined"!=typeof $loon}isShadowrocket(){return"undefined"!=typeof $rocket}toObj(t,e=null){try{return JSON.parse(t)}catch{return e}}toStr(t,e=null){try{return JSON.stringify(t)}catch{return e}}getjson(t,e){let s=e;const i=this.getdata(t);if(i)try{s=JSON.parse(this.getdata(t))}catch{}return s}setjson(t,e){try{return this.setdata(JSON.stringify(t),e)}catch{return!1}}getScript(t){return new Promise(e=>{this.get({url:t},(t,s,i)=>e(i))})}runScript(t,e){return new Promise(s=>{let i=this.getdata("@chavy_boxjs_userCfgs.httpapi");i=i?i.replace(/\n/g,"").trim():i;let r=this.getdata("@chavy_boxjs_userCfgs.httpapi_timeout");r=r?1*r:20,r=e&&e.timeout?e.timeout:r;const[o,h]=i.split("@"),n={url:`http://${h}/v1/scripting/evaluate`,body:{script_text:t,mock_type:"cron",timeout:r},headers:{"X-Key":o,Accept:"*/*"}};this.post(n,(t,e,i)=>s(i))}).catch(t=>this.logErr(t))}loaddata(){if(!this.isNode())return{};{this.fs=this.fs?this.fs:require("fs"),this.path=this.path?this.path:require("path");const t=this.path.resolve(this.dataFile),e=this.path.resolve(process.cwd(),this.dataFile),s=this.fs.existsSync(t),i=!s&&this.fs.existsSync(e);if(!s&&!i)return{};{const i=s?t:e;try{return JSON.parse(this.fs.readFileSync(i))}catch(t){return{}}}}}writedata(){if(this.isNode()){this.fs=this.fs?this.fs:require("fs"),this.path=this.path?this.path:require("path");const t=this.path.resolve(this.dataFile),e=this.path.resolve(process.cwd(),this.dataFile),s=this.fs.existsSync(t),i=!s&&this.fs.existsSync(e),r=JSON.stringify(this.data);s?this.fs.writeFileSync(t,r):i?this.fs.writeFileSync(e,r):this.fs.writeFileSync(t,r)}}lodash_get(t,e,s){const i=e.replace(/\[(\d+)\]/g,".$1").split(".");let r=t;for(const t of i)if(r=Object(r)[t],void 0===r)return s;return r}lodash_set(t,e,s){return Object(t)!==t?t:(Array.isArray(e)||(e=e.toString().match(/[^.[\]]+/g)||[]),e.slice(0,-1).reduce((t,s,i)=>Object(t[s])===t[s]?t[s]:t[s]=Math.abs(e[i+1])>>0==+e[i+1]?[]:{},t)[e[e.length-1]]=s,t)}getdata(t){let e=this.getval(t);if(/^@/.test(t)){const[,s,i]=/^@(.*?)\.(.*?)$/.exec(t),r=s?this.getval(s):"";if(r)try{const t=JSON.parse(r);e=t?this.lodash_get(t,i,""):e}catch(t){e=""}}return e}setdata(t,e){let s=!1;if(/^@/.test(e)){const[,i,r]=/^@(.*?)\.(.*?)$/.exec(e),o=this.getval(i),h=i?"null"===o?null:o||"{}":"{}";try{const e=JSON.parse(h);this.lodash_set(e,r,t),s=this.setval(JSON.stringify(e),i)}catch(e){const o={};this.lodash_set(o,r,t),s=this.setval(JSON.stringify(o),i)}}else s=this.setval(t,e);return s}getval(t){return this.isSurge()||this.isLoon()?$persistentStore.read(t):this.isQuanX()?$prefs.valueForKey(t):this.isNode()?(this.data=this.loaddata(),this.data[t]):this.data&&this.data[t]||null}setval(t,e){return this.isSurge()||this.isLoon()?$persistentStore.write(t,e):this.isQuanX()?$prefs.setValueForKey(t,e):this.isNode()?(this.data=this.loaddata(),this.data[e]=t,this.writedata(),!0):this.data&&this.data[e]||null}initGotEnv(t){this.got=this.got?this.got:require("got"),this.cktough=this.cktough?this.cktough:require("tough-cookie"),this.ckjar=this.ckjar?this.ckjar:new this.cktough.CookieJar,t&&(t.headers=t.headers?t.headers:{},void 0===t.headers.Cookie&&void 0===t.cookieJar&&(t.cookieJar=this.ckjar))}get(t,e=(()=>{})){if(t.headers&&(delete t.headers["Content-Type"],delete t.headers["Content-Length"]),this.isSurge()||this.isLoon())this.isSurge()&&this.isNeedRewrite&&(t.headers=t.headers||{},Object.assign(t.headers,{"X-Surge-Skip-Scripting":!1})),$httpClient.get(t,(t,s,i)=>{!t&&s&&(s.body=i,s.statusCode=s.status),e(t,s,i)});else if(this.isQuanX())this.isNeedRewrite&&(t.opts=t.opts||{},Object.assign(t.opts,{hints:!1})),$task.fetch(t).then(t=>{const{statusCode:s,statusCode:i,headers:r,body:o}=t;e(null,{status:s,statusCode:i,headers:r,body:o},o)},t=>e(t));else if(this.isNode()){let s=require("iconv-lite");this.initGotEnv(t),this.got(t).on("redirect",(t,e)=>{try{if(t.headers["set-cookie"]){const s=t.headers["set-cookie"].map(this.cktough.Cookie.parse).toString();s&&this.ckjar.setCookieSync(s,null),e.cookieJar=this.ckjar}}catch(t){this.logErr(t)}}).then(t=>{const{statusCode:i,statusCode:r,headers:o,rawBody:h}=t;e(null,{status:i,statusCode:r,headers:o,rawBody:h},s.decode(h,this.encoding))},t=>{const{message:i,response:r}=t;e(i,r,r&&s.decode(r.rawBody,this.encoding))})}}post(t,e=(()=>{})){const s=t.method?t.method.toLocaleLowerCase():"post";if(t.body&&t.headers&&!t.headers["Content-Type"]&&(t.headers["Content-Type"]="application/x-www-form-urlencoded"),t.headers&&delete t.headers["Content-Length"],this.isSurge()||this.isLoon())this.isSurge()&&this.isNeedRewrite&&(t.headers=t.headers||{},Object.assign(t.headers,{"X-Surge-Skip-Scripting":!1})),$httpClient[s](t,(t,s,i)=>{!t&&s&&(s.body=i,s.statusCode=s.status),e(t,s,i)});else if(this.isQuanX())t.method=s,this.isNeedRewrite&&(t.opts=t.opts||{},Object.assign(t.opts,{hints:!1})),$task.fetch(t).then(t=>{const{statusCode:s,statusCode:i,headers:r,body:o}=t;e(null,{status:s,statusCode:i,headers:r,body:o},o)},t=>e(t));else if(this.isNode()){let i=require("iconv-lite");this.initGotEnv(t);const{url:r,...o}=t;this.got[s](r,o).then(t=>{const{statusCode:s,statusCode:r,headers:o,rawBody:h}=t;e(null,{status:s,statusCode:r,headers:o,rawBody:h},i.decode(h,this.encoding))},t=>{const{message:s,response:r}=t;e(s,r,r&&i.decode(r.rawBody,this.encoding))})}}time(t,e=null){const s=e?new Date(e):new Date;let i={"M+":s.getMonth()+1,"d+":s.getDate(),"H+":s.getHours(),"m+":s.getMinutes(),"s+":s.getSeconds(),"q+":Math.floor((s.getMonth()+3)/3),S:s.getMilliseconds()};/(y+)/.test(t)&&(t=t.replace(RegExp.$1,(s.getFullYear()+"").substr(4-RegExp.$1.length)));for(let e in i)new RegExp("("+e+")").test(t)&&(t=t.replace(RegExp.$1,1==RegExp.$1.length?i[e]:("00"+i[e]).substr((""+i[e]).length)));return t}msg(e=t,s="",i="",r){const o=t=>{if(!t)return t;if("string"==typeof t)return this.isLoon()?t:this.isQuanX()?{"open-url":t}:this.isSurge()?{url:t}:void 0;if("object"==typeof t){if(this.isLoon()){let e=t.openUrl||t.url||t["open-url"],s=t.mediaUrl||t["media-url"];return{openUrl:e,mediaUrl:s}}if(this.isQuanX()){let e=t["open-url"]||t.url||t.openUrl,s=t["media-url"]||t.mediaUrl;return{"open-url":e,"media-url":s}}if(this.isSurge()){let e=t.url||t.openUrl||t["open-url"];return{url:e}}}};if(this.isMute||(this.isSurge()||this.isLoon()?$notification.post(e,s,i,o(r)):this.isQuanX()&&$notify(e,s,i,o(r))),!this.isMuteLog){let t=["","==============\ud83d\udce3\u7cfb\u7edf\u901a\u77e5\ud83d\udce3=============="];t.push(e),s&&t.push(s),i&&t.push(i),console.log(t.join("\n")),this.logs=this.logs.concat(t)}}log(...t){t.length>0&&(this.logs=[...this.logs,...t]),console.log(t.join(this.logSeparator))}logErr(t,e){const s=!this.isSurge()&&!this.isQuanX()&&!this.isLoon();s?this.log("",`\u2757\ufe0f${this.name}, \u9519\u8bef!`,t.stack):this.log("",`\u2757\ufe0f${this.name}, \u9519\u8bef!`,t)}wait(t){return new Promise(e=>setTimeout(e,t))}done(t={}){const e=(new Date).getTime(),s=(e-this.startTime)/1e3;this.log("",`\ud83d\udd14${this.name}, \u7ed3\u675f! \ud83d\udd5b ${s} \u79d2`),this.log(),(this.isSurge()||this.isQuanX()||this.isLoon())&&$done(t)}}(t,e)} 281 | -------------------------------------------------------------------------------- /Quantumult/wozaixiaoyuan/wzxy_leave.js: -------------------------------------------------------------------------------- 1 | lx = init("getLeave.js"); 2 | 3 | /**************** 4 | 5 | Quantumult X 配置参考,其他软件类似 6 | [rewrite] 7 | 脚本: getLeave.js 8 | 类型: script-response-body 9 | url: ^https://student\.wozaixiaoyuan\.com/leave2/getLeave\.json 10 | 11 | [Mitm] 12 | 主机名: student.wozaixiaoyuan.com 13 | 14 | ****************/ 15 | 16 | if (!lx.isResponse()) { 17 | lx.log("$response不存在,启动方式错误,应以rewrite和mitm方式启动"); 18 | lx.done() 19 | }; 20 | 21 | //自定义设置,根据需要自行更改,不填写则不会更改 22 | var user = { 23 | //指定假期开始时间结束时间 格式 "2021-06-28 10:00" 24 | //不指定则默认开始时间为当前 前1小时,结束时间当前 后2小时,不同时间打开会改变 25 | "start": "", 26 | "end": "", 27 | 28 | "state": 2,//假条状态 2应该是假期中 29 | "out": 1,//是否离校 1是 0否 30 | "studentName": "1313",//姓名,留空不变 31 | "studentId": "13131",//学生id,留空不变 32 | "type": "事假",//请假类型 事假 病假 实习 科研 出差 回家,留空不变 33 | "route": "13131",//外出地点,留空不变 34 | "location": "13113",//校区,销假地点,留空不变,注意格式[\"佛山三水校区\"] 35 | "tel": "13131",//紧急联系电话,留空不变 36 | "reason": "1313131",//请假理由,留空不变 37 | "userHead": "http://lorempixel.com/200/200/",//学生头像,默认随机,留空不变 38 | 39 | //下面这部分似乎不会在页面上显示 40 | "date": "",//请假提交时间,,留空不变 41 | "school": "",//学校,留空不变 42 | "college": "",//学院,留空不变 43 | "grade": "",//班级,留空不变 44 | "number": "",//学号,留空不变 45 | "phone": "",//电话,留空不变 46 | 47 | //下面这两条作用不明,懒得测试 48 | "scanHistory": [],//留空不变 49 | "imgs": [],//留空不变 50 | 51 | "teacher": "",//老师姓名,留空不变 52 | "approve": [ 53 | { 54 | "time": "",//审批时间,留空随机生成,格式12.21 11:10 55 | 56 | "state": 2,//审核状态 3拒绝 2通过 1审批中 57 | "userType": 4,//老师身份,4为辅导员,3为院级,2为校级 58 | "name": "lll",//老师姓名,留空不变 59 | "reason": "131313",//审批理由,留空不变 60 | "position": "131311",//老师学院,留空不变 61 | "head": "http://lorempixel.com/400/400/"//老师头像,默认随机,留空不变 62 | } 63 | ] 64 | }; 65 | 66 | Date.prototype.format=function(fmt){var o={"M+":this.getMonth()+1,"d+":this.getDate(),"h+":this.getHours(),"m+":this.getMinutes(),"s+":this.getSeconds(),"q+":Math.floor((this.getMonth()+3)/3),"S":this.getMilliseconds()};if(/(y+)/.test(fmt)){fmt=fmt.replace(RegExp.$1,(this.getFullYear()+"").substr(4-RegExp.$1.length))};for(var k in o){if(new RegExp("("+k+")").test(fmt)){fmt=fmt.replace(RegExp.$1,(RegExp.$1.length==1)?(o[k]):(("00"+o[k]).substr((""+o[k]).length)))}};return fmt}; 67 | 68 | function getFormatTime(time, flag) { 69 | if (flag === 1) { 70 | return time.format("yyyy-MM-dd hh:mm") 71 | } else { 72 | return time.format("MM-dd hh:mm") 73 | } 74 | }; 75 | 76 | //以下生成时间 77 | var time = new Date(); 78 | time.setMinutes(0, 0, 0); 79 | if (user["start"] == "" && user["end"] == "") { 80 | time.setHours(time.getHours() - 1); 81 | user["start"] = getFormatTime(time, 1);//开始时间 82 | time.setHours(time.getHours() + 3); 83 | user["end"] = getFormatTime(time, 1);//结束时间 84 | }; 85 | if (user["approve"][0]["time"] == "") {//批假时间 前一天随机时刻 86 | time.setHours(Math.floor(Math.random() * (22 - 9 + 1) + 9), Math.floor(Math.random() * 60)); 87 | time.setDate(time.getDate() - 1); 88 | user["approve"][0]["time"] = getFormatTime(time, 2); 89 | }; 90 | 91 | 92 | let data = { 93 | approve:[] 94 | }; 95 | 96 | for (x in user) {//读取用户自定义设置 97 | if (x != "approve") { 98 | if (user[x]) { 99 | data[x] = user[x]; 100 | } 101 | } 102 | }; 103 | for (y in user["approve"][0]) {//读取用户自定义设置 104 | if (user["approve"][0][y]) { 105 | data["approve"][0][y] = user["approve"][0][y]; 106 | } 107 | }; 108 | 109 | function init(name){const startTime=new Date().getTime();const isRequest=function(){return"undefined"!==typeof $request};const isResponse=function(){return"undefined"!==typeof $response};const isPost=function(){return"POST"===$request.method};const isGet=function(){return"GET"===$request.method};const isNode=function(){return'undefined'!==typeof module&&!!module.exports};const isQuanX=function(){return'undefined'!==typeof $task};const isSurge=function(){return'undefined'!==typeof $httpClient&&'undefined'===typeof $loon};const isLoon=function(){return'undefined'!==typeof $loon};const toObj=function(str,defaultValue=null){try{return JSON.parse(str)}catch{return defaultValue}};const toStr=function(obj,defaultValue=null){try{return JSON.stringify(obj)}catch{return defaultValue}};const msg=function(title,subtitle='',desc=''){if(isQuanX()){$notify(title,subtitle,desc)}else if(isSurge()||isLoon()){$notification.post(title,subtitle,desc)}};const log=function(...logs){if(logs.length>0){logs=[...logs]};console.log(logs.join("\n"))};const get=async function(opts,callback){if(isSurge()||isLoon()){await $httpClient.get(opts,function(err,res,body){if(!err&&res){res.body=body;res.statusCode=res.status};callback(err,res,body)})}else if(isQuanX()){opts.method="GET";await $task.fetch(opts).then(function(res){const{statusCode:status,statusCode,headers,body}=res;callback(null,{status,statusCode,headers,body},body)},function(err){callback(err)})}};const post=async function(opts,callback=function(){}){if(isSurge()||isLoon()){await $httpClient.post(opts,function(err,res,body){if(!err&&res){res.body=body;res.statusCode=res.status};callback(err,res,body)})}else if(isQuanX()){opts.method="POST";await $task.fetch(opts).then(function(res){const{statusCode:status,statusCode,headers,body}=res;callback(null,{status,statusCode,headers,body},body)},function(err){callback(err)})}};const r=function(key){if(isQuanX()){return $prefs.valueForKey(key)}else if(isSurge()||isLoon()){return $persistentStore.read(key)}};const w=function(val,key){if(isQuanX()){return $prefs.setValueForKey(val,key)}else if(isSurge()||isLoon()){return $persistentStore.write(val,key)}};const wait=function(time){return new Promise(function(resolve){setTimeout(resolve,time)})};const done=function(val={}){const endTime=new Date().getTime();const costTime=(endTime-startTime)/1000;log(name+" 结束运行,耗时:"+costTime);if(isQuanX()||isSurge()||isLoon()){$done(val)}};return{msg,log,get,post,done,r,w,wait,toObj,toStr,isLoon,isNode,isQuanX,isSurge,isRequest,isResponse,isPost,isGet};}; 110 | 111 | lx.done({ body: lx.toStr(bd) }); 112 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # 🐶这是我的脚本仓库,如果对你有帮助请点亮✨感谢支持 2 | 3 | ## 🔥特别声明: 4 | 5 | * 本仓库发布的Script项目中涉及的任何解锁和解密分析脚本,仅用于测试和学习研究,禁止用于商业用途,不能保证其合法性,准确性,完整性和有效性,请根据情况自行判断. 6 | 7 | * 本项目内所有资源文件,均可转载,但需要注明出处。 8 | 9 | * laoxinH 对使用本仓库脚本引发的问题概不负责,包括但不限于由任何脚本错误导致的任何损失或损害. 10 | 11 | * 间接使用脚本的任何用户,包括但不限于建立VPS或在某些行为违反国家/地区法律或相关法规的情况下进行传播, laoxinH 对于由此引起的任何隐私泄漏或其他后果概不负责. 12 | 13 | * 请勿将Script项目的任何内容用于商业或非法目的,否则后果自负. 14 | 15 | * 如果任何单位或个人认为该项目的脚本可能涉嫌侵犯其权利,则应及时通知并提供身份证明,所有权证明,我们将在收到认证文件后删除相关脚本. 16 | 17 | * 本仓库脚本可以随意访问修改,但你使用其他修改后的脚本如果出现问题请联系修改者. 18 | 19 | * 任何以任何方式查看此项目的人或直接或间接使用该Script项目的任何脚本的使用者都应仔细阅读此声明。laoxinH 保留随时更改或补充此免责声明的权利。一旦使用并复制了任何相关脚本或Script项目的规则,则视为您已接受此免责声明. 20 | 21 | **📢其他说明**
22 | > ***您使用或者复制了本仓库且本人制作的任何脚本,则视为`已接受`此声明,请仔细阅读***
23 | > ***如果脚本的实现方式你有更加方便的写法,或者有任何建议欢和脚本问题迎提交反馈,感谢支持😊*** 24 | 25 | ## 🚟Script脚本列表 26 | #### 说明 27 | 1. 其中 cookie_xxxx.js,圈x专用,用于获取对应脚本的cookie, 28 | 2. laoxin_config.js, nodejs专用,用于填写cookie和账号信息 29 | 3. 目前发布有我在校园健康打卡脚本和网易云音乐音乐人任务脚本。 30 | 31 | | 说明 | 名称 | 脚本 |教程 32 | | ---- | ------------------------------ | -------------------------------------------------------------------------------------------------------- |---| 33 | | 我在校园 | 我在校园签到 | [wzxy_health.js](https://github.com/laoxinH/MyScript/blob/main/Quantumult/wozaixiaoyuan/wzxy_health.js) |暂无 34 | | 网易云 | 网易云音乐人任务 | [wyy_yyr.js](https://github.com/laoxinH/MyScript/blob/main/Quantumult/wangyiyun/wyy_yyr.js) |已发布| 35 | 36 | 37 | **脚本兼容: [QuantumultX](https://apps.apple.com/us/app/quantumult-x/id1443988620), [Surge](https://apps.apple.com/us/app/surge-4/id1442620678), [Loon](https://apps.apple.com/us/app/loon/id1373567447), 小火箭, JSBox, Node.js** 38 | 39 | 40 | ## 📔食用方法 41 | 42 | 43 | ### 方法一:云服务器、腾讯云函数等等 44 | 45 | - 需自行有云服务器,云函数等 46 | - 腾讯云云函数 [网易云音乐教程](https://www.laoxin.top/index.php/2022/04/04/ncmusiciancloud/)(免费) 47 | 48 | 49 | 50 | 51 | ### 方法二:iOS系统的代理软件(QuantumultX, Surge, Loon, 小火箭) 52 | - 圈x教程 [网易云音乐Quantumult教程](https://www.laoxin.top/index.php/2022/04/04/ncmusicianqx/)(免费) 53 | 54 | 55 | ### 赞赏码(开发维护不易,请赏杯茶水费) 56 |
57 | 58 | ### 如果你有好的想法欢迎与我联系(如果有其他脚本需要编写可以[提交Issues](https://github.com/laoxinH/MyScript/issues)告诉我,当然不一定会写哦,这就看我有空没有啦~ 59 | 60 | ### 特别感谢(排名不分先后): 61 | * [@chavyleung](https://github.com/chavyleung) 62 | 63 | ### 更新说明 64 | ***2022-4-4 重构网易云脚本*** 65 | 66 | -------------------------------------------------------------------------------- /alpay.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/laoxinH/MyScript/2580340cb5d866f29d3cbee4c43847a2d436a871/alpay.jpg -------------------------------------------------------------------------------- /boxjs/laoxin.boxjs.json: -------------------------------------------------------------------------------- 1 | { 2 | "id": "laoxin.app.sub", 3 | "name": "laoxin 脚本订阅", 4 | "description": "BoxJS配置订阅", 5 | "author": "@laoxinH", 6 | "icon": "https://pan.laoxin.top/al1/images/header.jpg", 7 | "repo": "https://github.com/laoxinH/MyScript", 8 | "apps": [ 9 | { 10 | "id": "我在校园健康签到", 11 | "name": "日在校园签到", 12 | "keys": [ 13 | "wzxy_cookie", 14 | "wzxx_UA" 15 | ], 16 | "scripts": [ 17 | { 18 | "name": "我在校园健康打卡", 19 | "script": "https://lk.laoxinhxx.workers.dev/https://raw.githubusercontent.com/laoxinH/MyScript/main/Quantumult/wozaixiaoyuan/wzxy_health.js" 20 | } 21 | ], 22 | "settings": [ 23 | { 24 | "id": "wzxy_answers", 25 | "name": "答案", 26 | "val": "", 27 | "type": "text", 28 | "desc": "答案格式:[\"0\",\"0\",\"0\",\"2\",\"3\",\"无其他情况\"](0对应第一个选项,1对应第二个选项,以此类推)" 29 | }, 30 | { 31 | "id": "wzxy_longitude", 32 | "name": "经度", 33 | "val": "", 34 | "type": "text", 35 | "desc": "示列格式:31.666567" 36 | }, 37 | { 38 | "id": "wzxy_latitude", 39 | "name": "纬度", 40 | "val": "", 41 | "type": "text", 42 | "desc": "示列格式:106.769248" 43 | } 44 | ], 45 | "author": "@laoxinH", 46 | "repo": "https://github.com/laoxinH/MyScript", 47 | "icons": [ 48 | "https://pan.laoxin.top/al1/images/wzxy_icon.jpg", 49 | "https://pan.laoxin.top/al1/images/wzxy_icon.jpg" 50 | ] 51 | }, 52 | 53 | { 54 | "id": "网易云音乐人任务", 55 | "name": "音乐人赚云豆", 56 | "keys": [ 57 | "wyy_cookie", 58 | "wyy_UA" 59 | ], "scripts": [ 60 | { 61 | "name": "网易云音乐人任务", 62 | "script": "https://lk.laoxinhxx.workers.dev/https://raw.githubusercontent.com/laoxinH/MyScript/main/Quantumult/wangyiyun/wyy_yyr.js" 63 | }], 64 | "settings":[ 65 | { 66 | "id": "wyy_doSignInMusician", 67 | "name": "是否执行音乐人签到任务", 68 | "val": true, 69 | "type": "boolean", 70 | "desc": "开启表示执行,关闭表示不执行!" 71 | },{ 72 | "id": "wyy_doShareBlog", 73 | "name": "是否执行发布动态任务", 74 | "val": true, 75 | "type": "boolean", 76 | "desc": "开启表示执行,关闭表示不执行!" 77 | }, 78 | { 79 | "id": "wyy_shareMsg", 80 | "name": "动态发布内容", 81 | "val": "", 82 | "type": "text", 83 | "desc": "发布动态的文字内容,将会随机选择推荐歌单一起发布!" 84 | },{ 85 | "id": "wyy_doCommentYourself", 86 | "name": "是否执行发布主创说任务", 87 | "val": true, 88 | "type": "boolean", 89 | "desc": "开启表示执行,关闭表示不执行!" 90 | }, 91 | { 92 | "id": "wyy_commentMsg", 93 | "name": "动态主创说内容", 94 | "val": "", 95 | "type": "text", 96 | "desc": "发布主创说文字内容!" 97 | },{ 98 | "id": "wyy_doRePrivatrMessage", 99 | "name": "是否执行发送私信任务", 100 | "val": true, 101 | "type": "boolean", 102 | "desc": "开启表示执行,关闭表示不执行!" 103 | }, 104 | { 105 | "id": "wyy_reMsg", 106 | "name": "发送私信内容", 107 | "val": "", 108 | "type": "text", 109 | "desc": "发送私信的文字内容!" 110 | },{ 111 | "id": "wyy_doReplyMusicComment", 112 | "name": "是否执行回复粉丝评论任务", 113 | "val": true, 114 | "type": "boolean", 115 | "desc": "开启表示执行,关闭表示不执行!" 116 | },{ 117 | "id": "wyy_reCommentMsg", 118 | "name": "回复粉丝评论内容", 119 | "val": "", 120 | "type": "text", 121 | "desc": "回复粉丝私信文字内容!" 122 | },{ 123 | "id": "wyy_doViewMyCircle", 124 | "name": "是否执行访问自己云圈任务", 125 | "val": true, 126 | "type": "boolean", 127 | "desc": "开启表示执行,关闭表示不执行!" 128 | },{ 129 | "id": "wyy_doWatchLesson", 130 | "name": "是否执行观看课程任务", 131 | "val": true, 132 | "type": "boolean", 133 | "desc": "开启表示执行,关闭表示不执行!" 134 | } 135 | ] 136 | }], 137 | "author": "@laoxinH", 138 | "repo": "https://github.com/laoxinH/MyScript", 139 | "icons": [ 140 | "https://pan.laoxin.top/al1/images/icon.png", 141 | "https://pan.laoxin.top/al1/images/icon.png" 142 | ] 143 | } 144 | -------------------------------------------------------------------------------- /sendNotify.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @Last Modified time: 2021-5-1 15:00:54 3 | * sendNotify 推送通知功能 4 | * @param text 通知头 5 | * @param desp 通知体 6 | * @param params 某些推送通知方式点击弹窗可跳转, 例:{ url: 'https://abc.com' } 7 | * @param author 作者仓库等信息 例:`本脚本免费使用 By:xxx` 8 | * @returns {Promise} 9 | */ 10 | 11 | const querystring = require('querystring'); 12 | const $ = new Env(); 13 | const timeout = 15000; //超时时间(单位毫秒) 14 | // =======================================go-cqhttp通知设置区域=========================================== 15 | //gobot_url 填写请求地址http://127.0.0.1/send_private_msg 16 | //gobot_token 填写在go-cqhttp文件设置的访问密钥 17 | //gobot_qq 填写推送到个人QQ或者QQ群号 18 | //go-cqhttp相关API https://docs.go-cqhttp.org/api 19 | let GOBOT_URL = ''; // 推送到个人QQ: http://127.0.0.1/send_private_msg 群:http://127.0.0.1/send_group_msg 20 | let GOBOT_TOKEN = ''; //访问密钥 21 | let GOBOT_QQ = ''; // 如果GOBOT_URL设置 /send_private_msg 则需要填入 user_id=个人QQ 相反如果是 /send_group_msg 则需要填入 group_id=QQ群 22 | 23 | // =======================================微信server酱通知设置区域=========================================== 24 | //此处填你申请的SCKEY. 25 | //(环境变量名 PUSH_KEY) 26 | let SCKEY = ''; 27 | 28 | // =======================================Bark App通知设置区域=========================================== 29 | //此处填你BarkAPP的信息(IP/设备码,例如:https://api.day.app/XXXXXXXX) 30 | let BARK_PUSH = ''; 31 | //BARK app推送铃声,铃声列表去APP查看复制填写 32 | let BARK_SOUND = ''; 33 | //BARK app推送消息的分组, 默认为"QingLong" 34 | let BARK_GROUP = 'jd_scripts'; 35 | 36 | // =======================================telegram机器人通知设置区域=========================================== 37 | //此处填你telegram bot 的Token,telegram机器人通知推送必填项.例如:1077xxx4424:AAFjv0FcqxxxxxxgEMGfi22B4yh15R5uw 38 | //(环境变量名 TG_BOT_TOKEN) 39 | let TG_BOT_TOKEN = ''; 40 | //此处填你接收通知消息的telegram用户的id,telegram机器人通知推送必填项.例如:129xxx206 41 | //(环境变量名 TG_USER_ID) 42 | let TG_USER_ID = ''; 43 | //tg推送HTTP代理设置(不懂可忽略,telegram机器人通知推送功能中非必填) 44 | let TG_PROXY_HOST = ''; //例如:127.0.0.1(环境变量名:TG_PROXY_HOST) 45 | let TG_PROXY_PORT = ''; //例如:1080(环境变量名:TG_PROXY_PORT) 46 | let TG_PROXY_AUTH = ''; //tg代理配置认证参数 47 | //Telegram api自建的反向代理地址(不懂可忽略,telegram机器人通知推送功能中非必填),默认tg官方api(环境变量名:TG_API_HOST) 48 | let TG_API_HOST = 'api.telegram.org'; 49 | // =======================================钉钉机器人通知设置区域=========================================== 50 | //此处填你钉钉 bot 的webhook,例如:5a544165465465645d0f31dca676e7bd07415asdasd 51 | //(环境变量名 DD_BOT_TOKEN) 52 | let DD_BOT_TOKEN = ''; 53 | //密钥,机器人安全设置页面,加签一栏下面显示的SEC开头的字符串 54 | let DD_BOT_SECRET = ''; 55 | 56 | // =======================================企业微信机器人通知设置区域=========================================== 57 | //此处填你企业微信机器人的 webhook(详见文档 https://work.weixin.qq.com/api/doc/90000/90136/91770),例如:693a91f6-7xxx-4bc4-97a0-0ec2sifa5aaa 58 | //(环境变量名 QYWX_KEY) 59 | let QYWX_KEY = ''; 60 | 61 | // =======================================企业微信应用消息通知设置区域=========================================== 62 | /* 63 | 此处填你企业微信应用消息的值(详见文档 https://work.weixin.qq.com/api/doc/90000/90135/90236) 64 | 环境变量名 QYWX_AM依次填入 corpid,corpsecret,touser(注:多个成员ID使用|隔开),agentid,消息类型(选填,不填默认文本消息类型) 65 | 注意用,号隔开(英文输入法的逗号),例如:wwcff56746d9adwers,B-791548lnzXBE6_BWfxdf3kSTMJr9vFEPKAbh6WERQ,mingcheng,1000001,2COXgjH2UIfERF2zxrtUOKgQ9XklUqMdGSWLBoW_lSDAdafat 66 | 可选推送消息类型(推荐使用图文消息(mpnews)): 67 | - 文本卡片消息: 0 (数字零) 68 | - 文本消息: 1 (数字一) 69 | - 图文消息(mpnews): 素材库图片id, 可查看此教程(http://note.youdao.com/s/HMiudGkb)或者(https://note.youdao.com/ynoteshare1/index.html?id=1a0c8aff284ad28cbd011b29b3ad0191&type=note) 70 | */ 71 | let QYWX_AM = ''; 72 | 73 | // =======================================iGot聚合推送通知设置区域=========================================== 74 | //此处填您iGot的信息(推送key,例如:https://push.hellyw.com/XXXXXXXX) 75 | let IGOT_PUSH_KEY = ''; 76 | 77 | // =======================================push+设置区域======================================= 78 | //官方文档:http://www.pushplus.plus/ 79 | //PUSH_PLUS_TOKEN:微信扫码登录后一对一推送或一对多推送下面的token(您的Token),不提供PUSH_PLUS_USER则默认为一对一推送 80 | //PUSH_PLUS_USER: 一对多推送的“群组编码”(一对多推送下面->您的群组(如无则新建)->群组编码,如果您是创建群组人。也需点击“查看二维码”扫描绑定,否则不能接受群组消息推送) 81 | let PUSH_PLUS_TOKEN = ''; 82 | let PUSH_PLUS_USER = ''; 83 | 84 | //==========================云端环境变量的判断与接收========================= 85 | if (process.env.GOBOT_URL) { 86 | GOBOT_URL = process.env.GOBOT_URL; 87 | } 88 | if (process.env.GOBOT_TOKEN) { 89 | GOBOT_TOKEN = process.env.GOBOT_TOKEN; 90 | } 91 | if (process.env.GOBOT_QQ) { 92 | GOBOT_QQ = process.env.GOBOT_QQ; 93 | } 94 | 95 | if (process.env.PUSH_KEY) { 96 | SCKEY = process.env.PUSH_KEY; 97 | } 98 | 99 | if (process.env.QQ_SKEY) { 100 | QQ_SKEY = process.env.QQ_SKEY; 101 | } 102 | 103 | if (process.env.QQ_MODE) { 104 | QQ_MODE = process.env.QQ_MODE; 105 | } 106 | 107 | if (process.env.BARK_PUSH) { 108 | if (process.env.BARK_PUSH.indexOf('https') > -1 || process.env.BARK_PUSH.indexOf('http') > -1) { 109 | //兼容BARK自建用户 110 | BARK_PUSH = process.env.BARK_PUSH; 111 | } else { 112 | BARK_PUSH = `https://api.day.app/${process.env.BARK_PUSH}`; 113 | } 114 | if (process.env.BARK_SOUND) { 115 | BARK_SOUND = process.env.BARK_SOUND; 116 | } 117 | if (process.env.BARK_GROUP) { 118 | BARK_GROUP = process.env.BARK_GROUP; 119 | } 120 | } else { 121 | if (BARK_PUSH && BARK_PUSH.indexOf('https') === -1 && BARK_PUSH.indexOf('http') === -1) { 122 | //兼容BARK本地用户只填写设备码的情况 123 | BARK_PUSH = `https://api.day.app/${BARK_PUSH}`; 124 | } 125 | } 126 | if (process.env.TG_BOT_TOKEN) { 127 | TG_BOT_TOKEN = process.env.TG_BOT_TOKEN; 128 | } 129 | if (process.env.TG_USER_ID) { 130 | TG_USER_ID = process.env.TG_USER_ID; 131 | } 132 | if (process.env.TG_PROXY_AUTH) TG_PROXY_AUTH = process.env.TG_PROXY_AUTH; 133 | if (process.env.TG_PROXY_HOST) TG_PROXY_HOST = process.env.TG_PROXY_HOST; 134 | if (process.env.TG_PROXY_PORT) TG_PROXY_PORT = process.env.TG_PROXY_PORT; 135 | if (process.env.TG_API_HOST) TG_API_HOST = process.env.TG_API_HOST; 136 | 137 | if (process.env.DD_BOT_TOKEN) { 138 | DD_BOT_TOKEN = process.env.DD_BOT_TOKEN; 139 | if (process.env.DD_BOT_SECRET) { 140 | DD_BOT_SECRET = process.env.DD_BOT_SECRET; 141 | } 142 | } 143 | 144 | if (process.env.QYWX_KEY) { 145 | QYWX_KEY = process.env.QYWX_KEY; 146 | } 147 | 148 | if (process.env.QYWX_AM) { 149 | QYWX_AM = process.env.QYWX_AM; 150 | } 151 | 152 | if (process.env.IGOT_PUSH_KEY) { 153 | IGOT_PUSH_KEY = process.env.IGOT_PUSH_KEY; 154 | } 155 | 156 | if (process.env.PUSH_PLUS_TOKEN) { 157 | PUSH_PLUS_TOKEN = process.env.PUSH_PLUS_TOKEN; 158 | } 159 | if (process.env.PUSH_PLUS_USER) { 160 | PUSH_PLUS_USER = process.env.PUSH_PLUS_USER; 161 | } 162 | //==========================云端环境变量的判断与接收========================= 163 | 164 | /** 165 | * sendNotify 推送通知功能 166 | * @param text 通知头 167 | * @param desp 通知体 168 | * @param params 某些推送通知方式点击弹窗可跳转, 例:{ url: 'https://abc.com' } 169 | * @param author 作者仓库等信息 例:`本脚本免费使用 By:xxxx` 170 | * @returns {Promise} 171 | */ 172 | async function sendNotify(text, desp, params = {}) { 173 | //提供6种通知 174 | await Promise.all([ 175 | serverNotify(text, desp), //微信server酱 176 | pushPlusNotify(text, desp) //pushplus(推送加) 177 | ]) 178 | //由于上述两种微信通知需点击进去才能查看到详情,故text(标题内容)携带了账号序号以及昵称信息,方便不点击也可知道是哪个京东哪个活动 179 | text = text.match(/.*?(?=\s?-)/g) ? text.match(/.*?(?=\s?-)/g)[0] : text; 180 | await Promise.all([ 181 | BarkNotify(text, desp, params), //iOS Bark APP 182 | tgBotNotify(text, desp), //telegram 机器人 183 | ddBotNotify(text, desp), //钉钉机器人 184 | qywxBotNotify(text, desp), //企业微信机器人 185 | qywxamNotify(text, desp), //企业微信应用消息推送 186 | iGotNotify(text, desp, params), //iGot 187 | gobotNotify(text, desp),//go-cqhttp 188 | ]); 189 | } 190 | 191 | function gobotNotify(text, desp, time = 2100) { 192 | return new Promise((resolve) => { 193 | if (GOBOT_URL) { 194 | const options = { 195 | url: `${GOBOT_URL}?access_token=${GOBOT_TOKEN}&${GOBOT_QQ}`, 196 | json: { message: `${text}\n${desp}` }, 197 | headers: { 198 | 'Content-Type': 'application/json', 199 | }, 200 | timeout, 201 | }; 202 | setTimeout(() => { 203 | $.post(options, (err, resp, data) => { 204 | try { 205 | if (err) { 206 | console.log('发送go-cqhttp通知调用API失败!!\n'); 207 | console.log(err); 208 | } else { 209 | data = JSON.parse(data); 210 | if (data.retcode === 0) { 211 | console.log('go-cqhttp发送通知消息成功🎉\n'); 212 | } else if (data.retcode === 100) { 213 | console.log(`go-cqhttp发送通知消息异常: ${data.errmsg}\n`); 214 | } else { 215 | console.log( 216 | `go-cqhttp发送通知消息异常\n${JSON.stringify(data)}`, 217 | ); 218 | } 219 | } 220 | } catch (e) { 221 | $.logErr(e, resp); 222 | } finally { 223 | resolve(data); 224 | } 225 | }); 226 | }, time); 227 | } else { 228 | console.log('您未提供GOBOT的GOBOT_URL和GOBOT_TOKEN和GOBOT_QQ,取消GOBOT推送消息通知🚫\n'); 229 | resolve(); 230 | } 231 | }); 232 | } 233 | 234 | function serverNotify(text, desp, time = 2100) { 235 | return new Promise(resolve => { 236 | if (SCKEY) { 237 | //微信server酱推送通知一个\n不会换行,需要两个\n才能换行,故做此替换 238 | desp = desp.replace(/[\n\r]/g, '\n\n'); 239 | const options = { 240 | url: SCKEY.includes('SCT') ? `https://sctapi.ftqq.com/${SCKEY}.send` : `https://sc.ftqq.com/${SCKEY}.send`, 241 | body: `text=${text}&desp=${desp}`, 242 | headers: { 243 | 'Content-Type': 'application/x-www-form-urlencoded' 244 | }, 245 | timeout 246 | } 247 | setTimeout(() => { 248 | $.post(options, (err, resp, data) => { 249 | try { 250 | if (err) { 251 | console.log('发送通知调用API失败!!\n') 252 | console.log(err); 253 | } else { 254 | data = JSON.parse(data); 255 | //server酱和Server酱·Turbo版的返回json格式不太一样 256 | if (data.errno === 0 || data.data.errno === 0) { 257 | console.log('server酱发送通知消息成功🎉\n') 258 | } else if (data.errno === 1024) { 259 | // 一分钟内发送相同的内容会触发 260 | console.log(`server酱发送通知消息异常: ${data.errmsg}\n`) 261 | } else { 262 | console.log(`server酱发送通知消息异常\n${JSON.stringify(data)}`) 263 | } 264 | } 265 | } catch (e) { 266 | $.logErr(e, resp); 267 | } finally { 268 | resolve(data); 269 | } 270 | }) 271 | }, time) 272 | } else { 273 | console.log('\n\n您未提供server酱的SCKEY,取消微信推送消息通知🚫\n'); 274 | resolve() 275 | } 276 | }) 277 | } 278 | 279 | function CoolPush(text, desp) { 280 | return new Promise(resolve => { 281 | if (QQ_SKEY) { 282 | let options = { 283 | url: `https://push.xuthus.cc/${QQ_MODE}/${QQ_SKEY}`, 284 | headers: { 285 | 'Content-Type': 'application/json' 286 | } 287 | } 288 | 289 | // 已知敏感词 290 | text = text.replace(/京豆/g, "豆豆"); 291 | desp = desp.replace(/京豆/g, ""); 292 | desp = desp.replace(/🐶/g, ""); 293 | desp = desp.replace(/红包/g, "H包"); 294 | 295 | switch (QQ_MODE) { 296 | case "email": 297 | options.json = { 298 | "t": text, 299 | "c": desp, 300 | }; 301 | break; 302 | default: 303 | options.body = `${text}\n\n${desp}`; 304 | } 305 | 306 | let pushMode = function (t) { 307 | switch (t) { 308 | case "send": 309 | return "个人"; 310 | case "group": 311 | return "QQ群"; 312 | case "wx": 313 | return "微信"; 314 | case "ww": 315 | return "企业微信"; 316 | case "email": 317 | return "邮件"; 318 | default: 319 | return "未知方式" 320 | } 321 | } 322 | 323 | $.post(options, (err, resp, data) => { 324 | try { 325 | if (err) { 326 | console.log(`发送${pushMode(QQ_MODE)}通知调用API失败!!\n`) 327 | console.log(err); 328 | } else { 329 | data = JSON.parse(data); 330 | if (data.code === 200) { 331 | console.log(`酷推发送${pushMode(QQ_MODE)}通知消息成功🎉\n`) 332 | } else if (data.code === 400) { 333 | console.log(`QQ酷推(Cool Push)发送${pushMode(QQ_MODE)}推送失败:${data.msg}\n`) 334 | } else if (data.code === 503) { 335 | console.log(`QQ酷推出错,${data.message}:${data.data}\n`) 336 | } else { 337 | console.log(`酷推推送异常: ${JSON.stringify(data)}`); 338 | } 339 | } 340 | } catch (e) { 341 | $.logErr(e, resp); 342 | } finally { 343 | resolve(data); 344 | } 345 | }) 346 | } else { 347 | console.log('您未提供酷推的SKEY,取消QQ推送消息通知🚫\n'); 348 | resolve() 349 | } 350 | }) 351 | } 352 | 353 | function BarkNotify(text, desp, params = {}) { 354 | return new Promise(resolve => { 355 | if (BARK_PUSH) { 356 | const options = { 357 | url: `${BARK_PUSH}/${encodeURIComponent(text)}/${encodeURIComponent(desp)}?sound=${BARK_SOUND}&group=${BARK_GROUP}&${querystring.stringify(params)}`, 358 | headers: { 359 | 'Content-Type': 'application/x-www-form-urlencoded' 360 | }, 361 | timeout 362 | } 363 | $.get(options, (err, resp, data) => { 364 | try { 365 | if (err) { 366 | console.log('Bark APP发送通知调用API失败!!\n') 367 | console.log(err); 368 | } else { 369 | data = JSON.parse(data); 370 | if (data.code === 200) { 371 | console.log('Bark APP发送通知消息成功🎉\n') 372 | } else { 373 | console.log(`${data.message}\n`); 374 | } 375 | } 376 | } catch (e) { 377 | $.logErr(e, resp); 378 | } finally { 379 | resolve(); 380 | } 381 | }) 382 | } else { 383 | console.log('您未提供Bark的APP推送BARK_PUSH,取消Bark推送消息通知🚫\n'); 384 | resolve() 385 | } 386 | }) 387 | } 388 | 389 | function tgBotNotify(text, desp) { 390 | return new Promise(resolve => { 391 | if (TG_BOT_TOKEN && TG_USER_ID) { 392 | const options = { 393 | url: `https://${TG_API_HOST}/bot${TG_BOT_TOKEN}/sendMessage`, 394 | body: `chat_id=${TG_USER_ID}&text=${text}\n\n${desp}&disable_web_page_preview=true`, 395 | headers: { 396 | 'Content-Type': 'application/x-www-form-urlencoded' 397 | }, 398 | timeout 399 | } 400 | if (TG_PROXY_HOST && TG_PROXY_PORT) { 401 | const tunnel = require("tunnel"); 402 | const agent = { 403 | https: tunnel.httpsOverHttp({ 404 | proxy: { 405 | host: TG_PROXY_HOST, 406 | port: TG_PROXY_PORT * 1, 407 | proxyAuth: TG_PROXY_AUTH 408 | } 409 | }) 410 | } 411 | Object.assign(options, { agent }) 412 | } 413 | $.post(options, (err, resp, data) => { 414 | try { 415 | if (err) { 416 | console.log('telegram发送通知消息失败!!\n') 417 | console.log(err); 418 | } else { 419 | data = JSON.parse(data); 420 | if (data.ok) { 421 | console.log('Telegram发送通知消息成功🎉。\n') 422 | } else if (data.error_code === 400) { 423 | console.log('请主动给bot发送一条消息并检查接收用户ID是否正确。\n') 424 | } else if (data.error_code === 401) { 425 | console.log('Telegram bot token 填写错误。\n') 426 | } 427 | } 428 | } catch (e) { 429 | $.logErr(e, resp); 430 | } finally { 431 | resolve(data); 432 | } 433 | }) 434 | } else { 435 | console.log('您未提供telegram机器人推送所需的TG_BOT_TOKEN和TG_USER_ID,取消telegram推送消息通知🚫\n'); 436 | resolve() 437 | } 438 | }) 439 | } 440 | function ddBotNotify(text, desp) { 441 | return new Promise(resolve => { 442 | const options = { 443 | url: `https://oapi.dingtalk.com/robot/send?access_token=${DD_BOT_TOKEN}`, 444 | json: { 445 | "msgtype": "text", 446 | "text": { 447 | "content": ` ${text}\n\n${desp}` 448 | } 449 | }, 450 | headers: { 451 | 'Content-Type': 'application/json' 452 | }, 453 | timeout 454 | } 455 | if (DD_BOT_TOKEN && DD_BOT_SECRET) { 456 | const crypto = require('crypto'); 457 | const dateNow = Date.now(); 458 | const hmac = crypto.createHmac('sha256', DD_BOT_SECRET); 459 | hmac.update(`${dateNow}\n${DD_BOT_SECRET}`); 460 | const result = encodeURIComponent(hmac.digest('base64')); 461 | options.url = `${options.url}×tamp=${dateNow}&sign=${result}`; 462 | $.post(options, (err, resp, data) => { 463 | try { 464 | if (err) { 465 | console.log('钉钉发送通知消息失败!!\n') 466 | console.log(err); 467 | } else { 468 | data = JSON.parse(data); 469 | if (data.errcode === 0) { 470 | console.log('钉钉发送通知消息成功🎉。\n') 471 | } else { 472 | console.log(`${data.errmsg}\n`) 473 | } 474 | } 475 | } catch (e) { 476 | $.logErr(e, resp); 477 | } finally { 478 | resolve(data); 479 | } 480 | }) 481 | } else if (DD_BOT_TOKEN) { 482 | $.post(options, (err, resp, data) => { 483 | try { 484 | if (err) { 485 | console.log('钉钉发送通知消息失败!!\n') 486 | console.log(err); 487 | } else { 488 | data = JSON.parse(data); 489 | if (data.errcode === 0) { 490 | console.log('钉钉发送通知消息完成。\n') 491 | } else { 492 | console.log(`${data.errmsg}\n`) 493 | } 494 | } 495 | } catch (e) { 496 | $.logErr(e, resp); 497 | } finally { 498 | resolve(data); 499 | } 500 | }) 501 | } else { 502 | console.log('您未提供钉钉机器人推送所需的DD_BOT_TOKEN或者DD_BOT_SECRET,取消钉钉推送消息通知🚫\n'); 503 | resolve() 504 | } 505 | }) 506 | } 507 | 508 | function qywxBotNotify(text, desp) { 509 | return new Promise(resolve => { 510 | const options = { 511 | url: `https://qyapi.weixin.qq.com/cgi-bin/webhook/send?key=${QYWX_KEY}`, 512 | json: { 513 | msgtype: 'text', 514 | text: { 515 | content: ` ${text}\n\n${desp}`, 516 | }, 517 | }, 518 | headers: { 519 | 'Content-Type': 'application/json', 520 | }, 521 | timeout 522 | }; 523 | if (QYWX_KEY) { 524 | $.post(options, (err, resp, data) => { 525 | try { 526 | if (err) { 527 | console.log('企业微信发送通知消息失败!!\n'); 528 | console.log(err); 529 | } else { 530 | data = JSON.parse(data); 531 | if (data.errcode === 0) { 532 | console.log('企业微信发送通知消息成功🎉。\n'); 533 | } else { 534 | console.log(`${data.errmsg}\n`); 535 | } 536 | } 537 | } catch (e) { 538 | $.logErr(e, resp); 539 | } finally { 540 | resolve(data); 541 | } 542 | }); 543 | } else { 544 | console.log('您未提供企业微信机器人推送所需的QYWX_KEY,取消企业微信推送消息通知🚫\n'); 545 | resolve(); 546 | } 547 | }); 548 | } 549 | 550 | function ChangeUserId(desp) { 551 | const QYWX_AM_AY = QYWX_AM.split(','); 552 | if (QYWX_AM_AY[2]) { 553 | const userIdTmp = QYWX_AM_AY[2].split("|"); 554 | let userId = ""; 555 | for (let i = 0; i < userIdTmp.length; i++) { 556 | const count = "账号" + (i + 1); 557 | const count2 = "签到号 " + (i + 1); 558 | if (desp.match(count2)) { 559 | userId = userIdTmp[i]; 560 | } 561 | } 562 | if (!userId) userId = QYWX_AM_AY[2]; 563 | return userId; 564 | } else { 565 | return "@all"; 566 | } 567 | } 568 | 569 | function qywxamNotify(text, desp) { 570 | return new Promise(resolve => { 571 | if (QYWX_AM) { 572 | const QYWX_AM_AY = QYWX_AM.split(','); 573 | const options_accesstoken = { 574 | url: `https://qyapi.weixin.qq.com/cgi-bin/gettoken`, 575 | json: { 576 | corpid: `${QYWX_AM_AY[0]}`, 577 | corpsecret: `${QYWX_AM_AY[1]}`, 578 | }, 579 | headers: { 580 | 'Content-Type': 'application/json', 581 | }, 582 | timeout 583 | }; 584 | $.post(options_accesstoken, (err, resp, data) => { 585 | html = desp.replace(/\n/g, "
") 586 | var json = JSON.parse(data); 587 | accesstoken = json.access_token; 588 | let options; 589 | 590 | switch (QYWX_AM_AY[4]) { 591 | case '0': 592 | options = { 593 | msgtype: 'textcard', 594 | textcard: { 595 | title: `${text}`, 596 | description: `${desp}`, 597 | url: '', 598 | btntxt: '更多' 599 | } 600 | } 601 | break; 602 | 603 | case '1': 604 | options = { 605 | msgtype: 'text', 606 | text: { 607 | content: `${text}\n\n${desp}` 608 | } 609 | } 610 | break; 611 | 612 | default: 613 | options = { 614 | msgtype: 'mpnews', 615 | mpnews: { 616 | articles: [ 617 | { 618 | title: `${text}`, 619 | thumb_media_id: `${QYWX_AM_AY[4]}`, 620 | author: `智能助手`, 621 | content_source_url: ``, 622 | content: `${html}`, 623 | digest: `${desp}` 624 | } 625 | ] 626 | } 627 | } 628 | }; 629 | if (!QYWX_AM_AY[4]) { 630 | //如不提供第四个参数,则默认进行文本消息类型推送 631 | options = { 632 | msgtype: 'text', 633 | text: { 634 | content: `${text}\n\n${desp}` 635 | } 636 | } 637 | } 638 | options = { 639 | url: `https://qyapi.weixin.qq.com/cgi-bin/message/send?access_token=${accesstoken}`, 640 | json: { 641 | touser: `${ChangeUserId(desp)}`, 642 | agentid: `${QYWX_AM_AY[3]}`, 643 | safe: '0', 644 | ...options 645 | }, 646 | headers: { 647 | 'Content-Type': 'application/json', 648 | }, 649 | } 650 | 651 | $.post(options, (err, resp, data) => { 652 | try { 653 | if (err) { 654 | console.log('成员ID:' + ChangeUserId(desp) + '企业微信应用消息发送通知消息失败!!\n'); 655 | console.log(err); 656 | } else { 657 | data = JSON.parse(data); 658 | if (data.errcode === 0) { 659 | console.log('成员ID:' + ChangeUserId(desp) + '企业微信应用消息发送通知消息成功🎉。\n'); 660 | } else { 661 | console.log(`${data.errmsg}\n`); 662 | } 663 | } 664 | } catch (e) { 665 | $.logErr(e, resp); 666 | } finally { 667 | resolve(data); 668 | } 669 | }); 670 | }); 671 | } else { 672 | console.log('您未提供企业微信应用消息推送所需的QYWX_AM,取消企业微信应用消息推送消息通知🚫\n'); 673 | resolve(); 674 | } 675 | }); 676 | } 677 | 678 | function iGotNotify(text, desp, params = {}) { 679 | return new Promise(resolve => { 680 | if (IGOT_PUSH_KEY) { 681 | // 校验传入的IGOT_PUSH_KEY是否有效 682 | const IGOT_PUSH_KEY_REGX = new RegExp("^[a-zA-Z0-9]{24}$") 683 | if (!IGOT_PUSH_KEY_REGX.test(IGOT_PUSH_KEY)) { 684 | console.log('您所提供的IGOT_PUSH_KEY无效\n') 685 | resolve() 686 | return 687 | } 688 | const options = { 689 | url: `https://push.hellyw.com/${IGOT_PUSH_KEY.toLowerCase()}`, 690 | body: `title=${text}&content=${desp}&${querystring.stringify(params)}`, 691 | headers: { 692 | 'Content-Type': 'application/x-www-form-urlencoded' 693 | }, 694 | timeout 695 | } 696 | $.post(options, (err, resp, data) => { 697 | try { 698 | if (err) { 699 | console.log('发送通知调用API失败!!\n') 700 | console.log(err); 701 | } else { 702 | if (typeof data === 'string') data = JSON.parse(data); 703 | if (data.ret === 0) { 704 | console.log('iGot发送通知消息成功🎉\n') 705 | } else { 706 | console.log(`iGot发送通知消息失败:${data.errMsg}\n`) 707 | } 708 | } 709 | } catch (e) { 710 | $.logErr(e, resp); 711 | } finally { 712 | resolve(data); 713 | } 714 | }) 715 | } else { 716 | console.log('您未提供iGot的推送IGOT_PUSH_KEY,取消iGot推送消息通知🚫\n'); 717 | resolve() 718 | } 719 | }) 720 | } 721 | 722 | function pushPlusNotify(text, desp) { 723 | return new Promise(resolve => { 724 | if (PUSH_PLUS_TOKEN) { 725 | desp = desp.replace(/[\n\r]/g, '
'); // 默认为html, 不支持plaintext 726 | const body = { 727 | token: `${PUSH_PLUS_TOKEN}`, 728 | title: `${text}`, 729 | content: `${desp}`, 730 | topic: `${PUSH_PLUS_USER}` 731 | }; 732 | const options = { 733 | url: `http://www.pushplus.plus/send`, 734 | body: JSON.stringify(body), 735 | headers: { 736 | 'Content-Type': ' application/json' 737 | }, 738 | timeout 739 | } 740 | $.post(options, (err, resp, data) => { 741 | try { 742 | if (err) { 743 | console.log(`push+发送${PUSH_PLUS_USER ? '一对多' : '一对一'}通知消息失败!!\n`) 744 | console.log(err); 745 | } else { 746 | data = JSON.parse(data); 747 | if (data.code === 200) { 748 | console.log(`push+发送${PUSH_PLUS_USER ? '一对多' : '一对一'}通知消息完成。\n`) 749 | } else { 750 | console.log(`push+发送${PUSH_PLUS_USER ? '一对多' : '一对一'}通知消息失败:${data.msg}\n`) 751 | } 752 | } 753 | } catch (e) { 754 | $.logErr(e, resp); 755 | } finally { 756 | resolve(data); 757 | } 758 | }) 759 | } else { 760 | console.log('您未提供push+推送所需的PUSH_PLUS_TOKEN,取消push+推送消息通知🚫\n'); 761 | resolve() 762 | } 763 | }) 764 | } 765 | 766 | module.exports = { 767 | sendNotify, 768 | BARK_PUSH 769 | } 770 | // prettier-ignore 771 | function Env(t, s) { return new class { constructor(t, s) { this.name = t, this.data = null, this.dataFile = "box.dat", this.logs = [], this.logSeparator = "\n", this.startTime = (new Date).getTime(), Object.assign(this, s), this.log("", `\ud83d\udd14${this.name}, \u5f00\u59cb!`) } isNode() { return "undefined" != typeof module && !!module.exports } isQuanX() { return "undefined" != typeof $task } isSurge() { return "undefined" != typeof $httpClient && "undefined" == typeof $loon } isLoon() { return "undefined" != typeof $loon } getScript(t) { return new Promise(s => { $.get({ url: t }, (t, e, i) => s(i)) }) } runScript(t, s) { return new Promise(e => { let i = this.getdata("@chavy_boxjs_userCfgs.httpapi"); i = i ? i.replace(/\n/g, "").trim() : i; let o = this.getdata("@chavy_boxjs_userCfgs.httpapi_timeout"); o = o ? 1 * o : 20, o = s && s.timeout ? s.timeout : o; const [h, a] = i.split("@"), r = { url: `http://${a}/v1/scripting/evaluate`, body: { script_text: t, mock_type: "cron", timeout: o }, headers: { "X-Key": h, Accept: "*/*" } }; $.post(r, (t, s, i) => e(i)) }).catch(t => this.logErr(t)) } loaddata() { if (!this.isNode()) return {}; { this.fs = this.fs ? this.fs : require("fs"), this.path = this.path ? this.path : require("path"); const t = this.path.resolve(this.dataFile), s = this.path.resolve(process.cwd(), this.dataFile), e = this.fs.existsSync(t), i = !e && this.fs.existsSync(s); if (!e && !i) return {}; { const i = e ? t : s; try { return JSON.parse(this.fs.readFileSync(i)) } catch (t) { return {} } } } } writedata() { if (this.isNode()) { this.fs = this.fs ? this.fs : require("fs"), this.path = this.path ? this.path : require("path"); const t = this.path.resolve(this.dataFile), s = this.path.resolve(process.cwd(), this.dataFile), e = this.fs.existsSync(t), i = !e && this.fs.existsSync(s), o = JSON.stringify(this.data); e ? this.fs.writeFileSync(t, o) : i ? this.fs.writeFileSync(s, o) : this.fs.writeFileSync(t, o) } } lodash_get(t, s, e) { const i = s.replace(/\[(\d+)\]/g, ".$1").split("."); let o = t; for (const t of i) if (o = Object(o)[t], void 0 === o) return e; return o } lodash_set(t, s, e) { return Object(t) !== t ? t : (Array.isArray(s) || (s = s.toString().match(/[^.[\]]+/g) || []), s.slice(0, -1).reduce((t, e, i) => Object(t[e]) === t[e] ? t[e] : t[e] = Math.abs(s[i + 1]) >> 0 == +s[i + 1] ? [] : {}, t)[s[s.length - 1]] = e, t) } getdata(t) { let s = this.getval(t); if (/^@/.test(t)) { const [, e, i] = /^@(.*?)\.(.*?)$/.exec(t), o = e ? this.getval(e) : ""; if (o) try { const t = JSON.parse(o); s = t ? this.lodash_get(t, i, "") : s } catch (t) { s = "" } } return s } setdata(t, s) { let e = !1; if (/^@/.test(s)) { const [, i, o] = /^@(.*?)\.(.*?)$/.exec(s), h = this.getval(i), a = i ? "null" === h ? null : h || "{}" : "{}"; try { const s = JSON.parse(a); this.lodash_set(s, o, t), e = this.setval(JSON.stringify(s), i) } catch (s) { const h = {}; this.lodash_set(h, o, t), e = this.setval(JSON.stringify(h), i) } } else e = $.setval(t, s); return e } getval(t) { return this.isSurge() || this.isLoon() ? $persistentStore.read(t) : this.isQuanX() ? $prefs.valueForKey(t) : this.isNode() ? (this.data = this.loaddata(), this.data[t]) : this.data && this.data[t] || null } setval(t, s) { return this.isSurge() || this.isLoon() ? $persistentStore.write(t, s) : this.isQuanX() ? $prefs.setValueForKey(t, s) : this.isNode() ? (this.data = this.loaddata(), this.data[s] = t, this.writedata(), !0) : this.data && this.data[s] || null } initGotEnv(t) { this.got = this.got ? this.got : require("got"), this.cktough = this.cktough ? this.cktough : require("tough-cookie"), this.ckjar = this.ckjar ? this.ckjar : new this.cktough.CookieJar, t && (t.headers = t.headers ? t.headers : {}, void 0 === t.headers.Cookie && void 0 === t.cookieJar && (t.cookieJar = this.ckjar)) } get(t, s = (() => { })) { t.headers && (delete t.headers["Content-Type"], delete t.headers["Content-Length"]), this.isSurge() || this.isLoon() ? $httpClient.get(t, (t, e, i) => { !t && e && (e.body = i, e.statusCode = e.status), s(t, e, i) }) : this.isQuanX() ? $task.fetch(t).then(t => { const { statusCode: e, statusCode: i, headers: o, body: h } = t; s(null, { status: e, statusCode: i, headers: o, body: h }, h) }, t => s(t)) : this.isNode() && (this.initGotEnv(t), this.got(t).on("redirect", (t, s) => { try { const e = t.headers["set-cookie"].map(this.cktough.Cookie.parse).toString(); this.ckjar.setCookieSync(e, null), s.cookieJar = this.ckjar } catch (t) { this.logErr(t) } }).then(t => { const { statusCode: e, statusCode: i, headers: o, body: h } = t; s(null, { status: e, statusCode: i, headers: o, body: h }, h) }, t => s(t))) } post(t, s = (() => { })) { if (t.body && t.headers && !t.headers["Content-Type"] && (t.headers["Content-Type"] = "application/x-www-form-urlencoded"), delete t.headers["Content-Length"], this.isSurge() || this.isLoon()) $httpClient.post(t, (t, e, i) => { !t && e && (e.body = i, e.statusCode = e.status), s(t, e, i) }); else if (this.isQuanX()) t.method = "POST", $task.fetch(t).then(t => { const { statusCode: e, statusCode: i, headers: o, body: h } = t; s(null, { status: e, statusCode: i, headers: o, body: h }, h) }, t => s(t)); else if (this.isNode()) { this.initGotEnv(t); const { url: e, ...i } = t; this.got.post(e, i).then(t => { const { statusCode: e, statusCode: i, headers: o, body: h } = t; s(null, { status: e, statusCode: i, headers: o, body: h }, h) }, t => s(t)) } } time(t) { let s = { "M+": (new Date).getMonth() + 1, "d+": (new Date).getDate(), "H+": (new Date).getHours(), "m+": (new Date).getMinutes(), "s+": (new Date).getSeconds(), "q+": Math.floor(((new Date).getMonth() + 3) / 3), S: (new Date).getMilliseconds() }; /(y+)/.test(t) && (t = t.replace(RegExp.$1, ((new Date).getFullYear() + "").substr(4 - RegExp.$1.length))); for (let e in s) new RegExp("(" + e + ")").test(t) && (t = t.replace(RegExp.$1, 1 == RegExp.$1.length ? s[e] : ("00" + s[e]).substr(("" + s[e]).length))); return t } msg(s = t, e = "", i = "", o) { const h = t => !t || !this.isLoon() && this.isSurge() ? t : "string" == typeof t ? this.isLoon() ? t : this.isQuanX() ? { "open-url": t } : void 0 : "object" == typeof t && (t["open-url"] || t["media-url"]) ? this.isLoon() ? t["open-url"] : this.isQuanX() ? t : void 0 : void 0; $.isMute || (this.isSurge() || this.isLoon() ? $notification.post(s, e, i, h(o)) : this.isQuanX() && $notify(s, e, i, h(o))), this.logs.push("", "==============\ud83d\udce3\u7cfb\u7edf\u901a\u77e5\ud83d\udce3=============="), this.logs.push(s), e && this.logs.push(e), i && this.logs.push(i) } log(...t) { t.length > 0 ? this.logs = [...this.logs, ...t] : console.log(this.logs.join(this.logSeparator)) } logErr(t, s) { const e = !this.isSurge() && !this.isQuanX() && !this.isLoon(); e ? $.log("", `\u2757\ufe0f${this.name}, \u9519\u8bef!`, t.stack) : $.log("", `\u2757\ufe0f${this.name}, \u9519\u8bef!`, t) } wait(t) { return new Promise(s => setTimeout(s, t)) } done(t = {}) { const s = (new Date).getTime(), e = (s - this.startTime) / 1e3; this.log("", `\ud83d\udd14${this.name}, \u7ed3\u675f! \ud83d\udd5b ${e} \u79d2`), this.log(), (this.isSurge() || this.isQuanX() || this.isLoon()) && $done(t) } }(t, s) } 772 | --------------------------------------------------------------------------------