├── .gitignore ├── LICENSE ├── README.md ├── README.pdf ├── database └── robot.db ├── images ├── feizhai.jpg └── ybb.jpg ├── main.js ├── mirai ├── mcl-installer-1.0.1-linux-amd64 ├── mcl-installer-1.0.1-windows-amd64.exe └── mirai-api-http-v1.9.8.mirai.jar ├── package-lock.json ├── package.json ├── scripts ├── middleWare.js ├── repair.js ├── spider.js └── sql.js └── test.js /.gitignore: -------------------------------------------------------------------------------- 1 | # Byte-compiled / optimized / DLL files 2 | __pycache__/ 3 | *.py[cod] 4 | *$py.class 5 | 6 | # C extensions 7 | *.so 8 | 9 | # Distribution / packaging 10 | .Python 11 | build/ 12 | develop-eggs/ 13 | dist/ 14 | downloads/ 15 | eggs/ 16 | .eggs/ 17 | lib/ 18 | lib64/ 19 | parts/ 20 | sdist/ 21 | var/ 22 | wheels/ 23 | pip-wheel-metadata/ 24 | share/python-wheels/ 25 | *.egg-info/ 26 | .installed.cfg 27 | *.egg 28 | MANIFEST 29 | 30 | # PyInstaller 31 | # Usually these files are written by a python script from a template 32 | # before PyInstaller builds the exe, so as to inject date/other infos into it. 33 | *.manifest 34 | *.spec 35 | 36 | # Installer logs 37 | pip-log.txt 38 | pip-delete-this-directory.txt 39 | 40 | # Unit test / coverage reports 41 | htmlcov/ 42 | .tox/ 43 | .nox/ 44 | .coverage 45 | .coverage.* 46 | .cache 47 | nosetests.xml 48 | coverage.xml 49 | *.cover 50 | *.py,cover 51 | .hypothesis/ 52 | .pytest_cache/ 53 | 54 | # Translations 55 | *.mo 56 | *.pot 57 | 58 | # Django stuff: 59 | *.log 60 | local_settings.py 61 | db.sqlite3 62 | db.sqlite3-journal 63 | 64 | # Flask stuff: 65 | instance/ 66 | .webassets-cache 67 | 68 | # Scrapy stuff: 69 | .scrapy 70 | 71 | # Sphinx documentation 72 | docs/_build/ 73 | 74 | # PyBuilder 75 | target/ 76 | 77 | # Jupyter Notebook 78 | .ipynb_checkpoints 79 | 80 | # IPython 81 | profile_default/ 82 | ipython_config.py 83 | 84 | # pyenv 85 | .python-version 86 | 87 | # pipenv 88 | # According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control. 89 | # However, in case of collaboration, if having platform-specific dependencies or dependencies 90 | # having no cross-platform support, pipenv may install dependencies that don't work, or not 91 | # install all needed dependencies. 92 | #Pipfile.lock 93 | 94 | # PEP 582; used by e.g. github.com/David-OConnor/pyflow 95 | __pypackages__/ 96 | 97 | # Celery stuff 98 | celerybeat-schedule 99 | celerybeat.pid 100 | 101 | # SageMath parsed files 102 | *.sage.py 103 | 104 | # Environments 105 | .env 106 | .venv 107 | env/ 108 | venv/ 109 | ENV/ 110 | env.bak/ 111 | venv.bak/ 112 | 113 | # Spyder project settings 114 | .spyderproject 115 | .spyproject 116 | 117 | # Rope project settings 118 | .ropeproject 119 | 120 | # mkdocs documentation 121 | /site 122 | 123 | # mypy 124 | .mypy_cache/ 125 | .dmypy.json 126 | dmypy.json 127 | 128 | # Pyre type checker 129 | .pyre/ 130 | 131 | 132 | /node_modules -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | GNU AFFERO GENERAL PUBLIC LICENSE 2 | Version 3, 19 November 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 Affero General Public License is a free, copyleft license for 11 | software and other kinds of works, specifically designed to ensure 12 | cooperation with the community in the case of network server software. 13 | 14 | The licenses for most software and other practical works are designed 15 | to take away your freedom to share and change the works. By contrast, 16 | our General Public Licenses are intended to guarantee your freedom to 17 | share and change all versions of a program--to make sure it remains free 18 | software for all its users. 19 | 20 | When we speak of free software, we are referring to freedom, not 21 | price. Our General Public Licenses are designed to make sure that you 22 | have the freedom to distribute copies of free software (and charge for 23 | them if you wish), that you receive source code or can get it if you 24 | want it, that you can change the software or use pieces of it in new 25 | free programs, and that you know you can do these things. 26 | 27 | Developers that use our General Public Licenses protect your rights 28 | with two steps: (1) assert copyright on the software, and (2) offer 29 | you this License which gives you legal permission to copy, distribute 30 | and/or modify the software. 31 | 32 | A secondary benefit of defending all users' freedom is that 33 | improvements made in alternate versions of the program, if they 34 | receive widespread use, become available for other developers to 35 | incorporate. Many developers of free software are heartened and 36 | encouraged by the resulting cooperation. However, in the case of 37 | software used on network servers, this result may fail to come about. 38 | The GNU General Public License permits making a modified version and 39 | letting the public access it on a server without ever releasing its 40 | source code to the public. 41 | 42 | The GNU Affero General Public License is designed specifically to 43 | ensure that, in such cases, the modified source code becomes available 44 | to the community. It requires the operator of a network server to 45 | provide the source code of the modified version running there to the 46 | users of that server. Therefore, public use of a modified version, on 47 | a publicly accessible server, gives the public access to the source 48 | code of the modified version. 49 | 50 | An older license, called the Affero General Public License and 51 | published by Affero, was designed to accomplish similar goals. This is 52 | a different license, not a version of the Affero GPL, but Affero has 53 | released a new version of the Affero GPL which permits relicensing under 54 | this license. 55 | 56 | The precise terms and conditions for copying, distribution and 57 | modification follow. 58 | 59 | TERMS AND CONDITIONS 60 | 61 | 0. Definitions. 62 | 63 | "This License" refers to version 3 of the GNU Affero General Public License. 64 | 65 | "Copyright" also means copyright-like laws that apply to other kinds of 66 | works, such as semiconductor masks. 67 | 68 | "The Program" refers to any copyrightable work licensed under this 69 | License. Each licensee is addressed as "you". "Licensees" and 70 | "recipients" may be individuals or organizations. 71 | 72 | To "modify" a work means to copy from or adapt all or part of the work 73 | in a fashion requiring copyright permission, other than the making of an 74 | exact copy. The resulting work is called a "modified version" of the 75 | earlier work or a work "based on" the earlier work. 76 | 77 | A "covered work" means either the unmodified Program or a work based 78 | on the Program. 79 | 80 | To "propagate" a work means to do anything with it that, without 81 | permission, would make you directly or secondarily liable for 82 | infringement under applicable copyright law, except executing it on a 83 | computer or modifying a private copy. Propagation includes copying, 84 | distribution (with or without modification), making available to the 85 | public, and in some countries other activities as well. 86 | 87 | To "convey" a work means any kind of propagation that enables other 88 | parties to make or receive copies. Mere interaction with a user through 89 | a computer network, with no transfer of a copy, is not conveying. 90 | 91 | An interactive user interface displays "Appropriate Legal Notices" 92 | to the extent that it includes a convenient and prominently visible 93 | feature that (1) displays an appropriate copyright notice, and (2) 94 | tells the user that there is no warranty for the work (except to the 95 | extent that warranties are provided), that licensees may convey the 96 | work under this License, and how to view a copy of this License. If 97 | the interface presents a list of user commands or options, such as a 98 | menu, a prominent item in the list meets this criterion. 99 | 100 | 1. Source Code. 101 | 102 | The "source code" for a work means the preferred form of the work 103 | for making modifications to it. "Object code" means any non-source 104 | form of a work. 105 | 106 | A "Standard Interface" means an interface that either is an official 107 | standard defined by a recognized standards body, or, in the case of 108 | interfaces specified for a particular programming language, one that 109 | is widely used among developers working in that language. 110 | 111 | The "System Libraries" of an executable work include anything, other 112 | than the work as a whole, that (a) is included in the normal form of 113 | packaging a Major Component, but which is not part of that Major 114 | Component, and (b) serves only to enable use of the work with that 115 | Major Component, or to implement a Standard Interface for which an 116 | implementation is available to the public in source code form. A 117 | "Major Component", in this context, means a major essential component 118 | (kernel, window system, and so on) of the specific operating system 119 | (if any) on which the executable work runs, or a compiler used to 120 | produce the work, or an object code interpreter used to run it. 121 | 122 | The "Corresponding Source" for a work in object code form means all 123 | the source code needed to generate, install, and (for an executable 124 | work) run the object code and to modify the work, including scripts to 125 | control those activities. However, it does not include the work's 126 | System Libraries, or general-purpose tools or generally available free 127 | programs which are used unmodified in performing those activities but 128 | which are not part of the work. For example, Corresponding Source 129 | includes interface definition files associated with source files for 130 | the work, and the source code for shared libraries and dynamically 131 | linked subprograms that the work is specifically designed to require, 132 | such as by intimate data communication or control flow between those 133 | subprograms and other parts of the work. 134 | 135 | The Corresponding Source need not include anything that users 136 | can regenerate automatically from other parts of the Corresponding 137 | Source. 138 | 139 | The Corresponding Source for a work in source code form is that 140 | same work. 141 | 142 | 2. Basic Permissions. 143 | 144 | All rights granted under this License are granted for the term of 145 | copyright on the Program, and are irrevocable provided the stated 146 | conditions are met. This License explicitly affirms your unlimited 147 | permission to run the unmodified Program. The output from running a 148 | covered work is covered by this License only if the output, given its 149 | content, constitutes a covered work. This License acknowledges your 150 | rights of fair use or other equivalent, as provided by copyright law. 151 | 152 | You may make, run and propagate covered works that you do not 153 | convey, without conditions so long as your license otherwise remains 154 | in force. You may convey covered works to others for the sole purpose 155 | of having them make modifications exclusively for you, or provide you 156 | with facilities for running those works, provided that you comply with 157 | the terms of this License in conveying all material for which you do 158 | not control copyright. Those thus making or running the covered works 159 | for you must do so exclusively on your behalf, under your direction 160 | and control, on terms that prohibit them from making any copies of 161 | your copyrighted material outside their relationship with you. 162 | 163 | Conveying under any other circumstances is permitted solely under 164 | the conditions stated below. Sublicensing is not allowed; section 10 165 | makes it unnecessary. 166 | 167 | 3. Protecting Users' Legal Rights From Anti-Circumvention Law. 168 | 169 | No covered work shall be deemed part of an effective technological 170 | measure under any applicable law fulfilling obligations under article 171 | 11 of the WIPO copyright treaty adopted on 20 December 1996, or 172 | similar laws prohibiting or restricting circumvention of such 173 | measures. 174 | 175 | When you convey a covered work, you waive any legal power to forbid 176 | circumvention of technological measures to the extent such circumvention 177 | is effected by exercising rights under this License with respect to 178 | the covered work, and you disclaim any intention to limit operation or 179 | modification of the work as a means of enforcing, against the work's 180 | users, your or third parties' legal rights to forbid circumvention of 181 | technological measures. 182 | 183 | 4. Conveying Verbatim Copies. 184 | 185 | You may convey verbatim copies of the Program's source code as you 186 | receive it, in any medium, provided that you conspicuously and 187 | appropriately publish on each copy an appropriate copyright notice; 188 | keep intact all notices stating that this License and any 189 | non-permissive terms added in accord with section 7 apply to the code; 190 | keep intact all notices of the absence of any warranty; and give all 191 | recipients a copy of this License along with the Program. 192 | 193 | You may charge any price or no price for each copy that you convey, 194 | and you may offer support or warranty protection for a fee. 195 | 196 | 5. Conveying Modified Source Versions. 197 | 198 | You may convey a work based on the Program, or the modifications to 199 | produce it from the Program, in the form of source code under the 200 | terms of section 4, provided that you also meet all of these conditions: 201 | 202 | a) The work must carry prominent notices stating that you modified 203 | it, and giving a relevant date. 204 | 205 | b) The work must carry prominent notices stating that it is 206 | released under this License and any conditions added under section 207 | 7. This requirement modifies the requirement in section 4 to 208 | "keep intact all notices". 209 | 210 | c) You must license the entire work, as a whole, under this 211 | License to anyone who comes into possession of a copy. This 212 | License will therefore apply, along with any applicable section 7 213 | additional terms, to the whole of the work, and all its parts, 214 | regardless of how they are packaged. This License gives no 215 | permission to license the work in any other way, but it does not 216 | invalidate such permission if you have separately received it. 217 | 218 | d) If the work has interactive user interfaces, each must display 219 | Appropriate Legal Notices; however, if the Program has interactive 220 | interfaces that do not display Appropriate Legal Notices, your 221 | work need not make them do so. 222 | 223 | A compilation of a covered work with other separate and independent 224 | works, which are not by their nature extensions of the covered work, 225 | and which are not combined with it such as to form a larger program, 226 | in or on a volume of a storage or distribution medium, is called an 227 | "aggregate" if the compilation and its resulting copyright are not 228 | used to limit the access or legal rights of the compilation's users 229 | beyond what the individual works permit. Inclusion of a covered work 230 | in an aggregate does not cause this License to apply to the other 231 | parts of the aggregate. 232 | 233 | 6. Conveying Non-Source Forms. 234 | 235 | You may convey a covered work in object code form under the terms 236 | of sections 4 and 5, provided that you also convey the 237 | machine-readable Corresponding Source under the terms of this License, 238 | in one of these ways: 239 | 240 | a) Convey the object code in, or embodied in, a physical product 241 | (including a physical distribution medium), accompanied by the 242 | Corresponding Source fixed on a durable physical medium 243 | customarily used for software interchange. 244 | 245 | b) Convey the object code in, or embodied in, a physical product 246 | (including a physical distribution medium), accompanied by a 247 | written offer, valid for at least three years and valid for as 248 | long as you offer spare parts or customer support for that product 249 | model, to give anyone who possesses the object code either (1) a 250 | copy of the Corresponding Source for all the software in the 251 | product that is covered by this License, on a durable physical 252 | medium customarily used for software interchange, for a price no 253 | more than your reasonable cost of physically performing this 254 | conveying of source, or (2) access to copy the 255 | Corresponding Source from a network server at no charge. 256 | 257 | c) Convey individual copies of the object code with a copy of the 258 | written offer to provide the Corresponding Source. This 259 | alternative is allowed only occasionally and noncommercially, and 260 | only if you received the object code with such an offer, in accord 261 | with subsection 6b. 262 | 263 | d) Convey the object code by offering access from a designated 264 | place (gratis or for a charge), and offer equivalent access to the 265 | Corresponding Source in the same way through the same place at no 266 | further charge. You need not require recipients to copy the 267 | Corresponding Source along with the object code. If the place to 268 | copy the object code is a network server, the Corresponding Source 269 | may be on a different server (operated by you or a third party) 270 | that supports equivalent copying facilities, provided you maintain 271 | clear directions next to the object code saying where to find the 272 | Corresponding Source. Regardless of what server hosts the 273 | Corresponding Source, you remain obligated to ensure that it is 274 | available for as long as needed to satisfy these requirements. 275 | 276 | e) Convey the object code using peer-to-peer transmission, provided 277 | you inform other peers where the object code and Corresponding 278 | Source of the work are being offered to the general public at no 279 | charge under subsection 6d. 280 | 281 | A separable portion of the object code, whose source code is excluded 282 | from the Corresponding Source as a System Library, need not be 283 | included in conveying the object code work. 284 | 285 | A "User Product" is either (1) a "consumer product", which means any 286 | tangible personal property which is normally used for personal, family, 287 | or household purposes, or (2) anything designed or sold for incorporation 288 | into a dwelling. In determining whether a product is a consumer product, 289 | doubtful cases shall be resolved in favor of coverage. For a particular 290 | product received by a particular user, "normally used" refers to a 291 | typical or common use of that class of product, regardless of the status 292 | of the particular user or of the way in which the particular user 293 | actually uses, or expects or is expected to use, the product. A product 294 | is a consumer product regardless of whether the product has substantial 295 | commercial, industrial or non-consumer uses, unless such uses represent 296 | the only significant mode of use of the product. 297 | 298 | "Installation Information" for a User Product means any methods, 299 | procedures, authorization keys, or other information required to install 300 | and execute modified versions of a covered work in that User Product from 301 | a modified version of its Corresponding Source. The information must 302 | suffice to ensure that the continued functioning of the modified object 303 | code is in no case prevented or interfered with solely because 304 | modification has been made. 305 | 306 | If you convey an object code work under this section in, or with, or 307 | specifically for use in, a User Product, and the conveying occurs as 308 | part of a transaction in which the right of possession and use of the 309 | User Product is transferred to the recipient in perpetuity or for a 310 | fixed term (regardless of how the transaction is characterized), the 311 | Corresponding Source conveyed under this section must be accompanied 312 | by the Installation Information. But this requirement does not apply 313 | if neither you nor any third party retains the ability to install 314 | modified object code on the User Product (for example, the work has 315 | been installed in ROM). 316 | 317 | The requirement to provide Installation Information does not include a 318 | requirement to continue to provide support service, warranty, or updates 319 | for a work that has been modified or installed by the recipient, or for 320 | the User Product in which it has been modified or installed. Access to a 321 | network may be denied when the modification itself materially and 322 | adversely affects the operation of the network or violates the rules and 323 | protocols for communication across the network. 324 | 325 | Corresponding Source conveyed, and Installation Information provided, 326 | in accord with this section must be in a format that is publicly 327 | documented (and with an implementation available to the public in 328 | source code form), and must require no special password or key for 329 | unpacking, reading or copying. 330 | 331 | 7. Additional Terms. 332 | 333 | "Additional permissions" are terms that supplement the terms of this 334 | License by making exceptions from one or more of its conditions. 335 | Additional permissions that are applicable to the entire Program shall 336 | be treated as though they were included in this License, to the extent 337 | that they are valid under applicable law. If additional permissions 338 | apply only to part of the Program, that part may be used separately 339 | under those permissions, but the entire Program remains governed by 340 | this License without regard to the additional permissions. 341 | 342 | When you convey a copy of a covered work, you may at your option 343 | remove any additional permissions from that copy, or from any part of 344 | it. (Additional permissions may be written to require their own 345 | removal in certain cases when you modify the work.) You may place 346 | additional permissions on material, added by you to a covered work, 347 | for which you have or can give appropriate copyright permission. 348 | 349 | Notwithstanding any other provision of this License, for material you 350 | add to a covered work, you may (if authorized by the copyright holders of 351 | that material) supplement the terms of this License with terms: 352 | 353 | a) Disclaiming warranty or limiting liability differently from the 354 | terms of sections 15 and 16 of this License; or 355 | 356 | b) Requiring preservation of specified reasonable legal notices or 357 | author attributions in that material or in the Appropriate Legal 358 | Notices displayed by works containing it; or 359 | 360 | c) Prohibiting misrepresentation of the origin of that material, or 361 | requiring that modified versions of such material be marked in 362 | reasonable ways as different from the original version; or 363 | 364 | d) Limiting the use for publicity purposes of names of licensors or 365 | authors of the material; or 366 | 367 | e) Declining to grant rights under trademark law for use of some 368 | trade names, trademarks, or service marks; or 369 | 370 | f) Requiring indemnification of licensors and authors of that 371 | material by anyone who conveys the material (or modified versions of 372 | it) with contractual assumptions of liability to the recipient, for 373 | any liability that these contractual assumptions directly impose on 374 | those licensors and authors. 375 | 376 | All other non-permissive additional terms are considered "further 377 | restrictions" within the meaning of section 10. If the Program as you 378 | received it, or any part of it, contains a notice stating that it is 379 | governed by this License along with a term that is a further 380 | restriction, you may remove that term. If a license document contains 381 | a further restriction but permits relicensing or conveying under this 382 | License, you may add to a covered work material governed by the terms 383 | of that license document, provided that the further restriction does 384 | not survive such relicensing or conveying. 385 | 386 | If you add terms to a covered work in accord with this section, you 387 | must place, in the relevant source files, a statement of the 388 | additional terms that apply to those files, or a notice indicating 389 | where to find the applicable terms. 390 | 391 | Additional terms, permissive or non-permissive, may be stated in the 392 | form of a separately written license, or stated as exceptions; 393 | the above requirements apply either way. 394 | 395 | 8. Termination. 396 | 397 | You may not propagate or modify a covered work except as expressly 398 | provided under this License. Any attempt otherwise to propagate or 399 | modify it is void, and will automatically terminate your rights under 400 | this License (including any patent licenses granted under the third 401 | paragraph of section 11). 402 | 403 | However, if you cease all violation of this License, then your 404 | license from a particular copyright holder is reinstated (a) 405 | provisionally, unless and until the copyright holder explicitly and 406 | finally terminates your license, and (b) permanently, if the copyright 407 | holder fails to notify you of the violation by some reasonable means 408 | prior to 60 days after the cessation. 409 | 410 | Moreover, your license from a particular copyright holder is 411 | reinstated permanently if the copyright holder notifies you of the 412 | violation by some reasonable means, this is the first time you have 413 | received notice of violation of this License (for any work) from that 414 | copyright holder, and you cure the violation prior to 30 days after 415 | your receipt of the notice. 416 | 417 | Termination of your rights under this section does not terminate the 418 | licenses of parties who have received copies or rights from you under 419 | this License. If your rights have been terminated and not permanently 420 | reinstated, you do not qualify to receive new licenses for the same 421 | material under section 10. 422 | 423 | 9. Acceptance Not Required for Having Copies. 424 | 425 | You are not required to accept this License in order to receive or 426 | run a copy of the Program. Ancillary propagation of a covered work 427 | occurring solely as a consequence of using peer-to-peer transmission 428 | to receive a copy likewise does not require acceptance. However, 429 | nothing other than this License grants you permission to propagate or 430 | modify any covered work. These actions infringe copyright if you do 431 | not accept this License. Therefore, by modifying or propagating a 432 | covered work, you indicate your acceptance of this License to do so. 433 | 434 | 10. Automatic Licensing of Downstream Recipients. 435 | 436 | Each time you convey a covered work, the recipient automatically 437 | receives a license from the original licensors, to run, modify and 438 | propagate that work, subject to this License. You are not responsible 439 | for enforcing compliance by third parties with this License. 440 | 441 | An "entity transaction" is a transaction transferring control of an 442 | organization, or substantially all assets of one, or subdividing an 443 | organization, or merging organizations. If propagation of a covered 444 | work results from an entity transaction, each party to that 445 | transaction who receives a copy of the work also receives whatever 446 | licenses to the work the party's predecessor in interest had or could 447 | give under the previous paragraph, plus a right to possession of the 448 | Corresponding Source of the work from the predecessor in interest, if 449 | the predecessor has it or can get it with reasonable efforts. 450 | 451 | You may not impose any further restrictions on the exercise of the 452 | rights granted or affirmed under this License. For example, you may 453 | not impose a license fee, royalty, or other charge for exercise of 454 | rights granted under this License, and you may not initiate litigation 455 | (including a cross-claim or counterclaim in a lawsuit) alleging that 456 | any patent claim is infringed by making, using, selling, offering for 457 | sale, or importing the Program or any portion of it. 458 | 459 | 11. Patents. 460 | 461 | A "contributor" is a copyright holder who authorizes use under this 462 | License of the Program or a work on which the Program is based. The 463 | work thus licensed is called the contributor's "contributor version". 464 | 465 | A contributor's "essential patent claims" are all patent claims 466 | owned or controlled by the contributor, whether already acquired or 467 | hereafter acquired, that would be infringed by some manner, permitted 468 | by this License, of making, using, or selling its contributor version, 469 | but do not include claims that would be infringed only as a 470 | consequence of further modification of the contributor version. For 471 | purposes of this definition, "control" includes the right to grant 472 | patent sublicenses in a manner consistent with the requirements of 473 | this License. 474 | 475 | Each contributor grants you a non-exclusive, worldwide, royalty-free 476 | patent license under the contributor's essential patent claims, to 477 | make, use, sell, offer for sale, import and otherwise run, modify and 478 | propagate the contents of its contributor version. 479 | 480 | In the following three paragraphs, a "patent license" is any express 481 | agreement or commitment, however denominated, not to enforce a patent 482 | (such as an express permission to practice a patent or covenant not to 483 | sue for patent infringement). To "grant" such a patent license to a 484 | party means to make such an agreement or commitment not to enforce a 485 | patent against the party. 486 | 487 | If you convey a covered work, knowingly relying on a patent license, 488 | and the Corresponding Source of the work is not available for anyone 489 | to copy, free of charge and under the terms of this License, through a 490 | publicly available network server or other readily accessible means, 491 | then you must either (1) cause the Corresponding Source to be so 492 | available, or (2) arrange to deprive yourself of the benefit of the 493 | patent license for this particular work, or (3) arrange, in a manner 494 | consistent with the requirements of this License, to extend the patent 495 | license to downstream recipients. "Knowingly relying" means you have 496 | actual knowledge that, but for the patent license, your conveying the 497 | covered work in a country, or your recipient's use of the covered work 498 | in a country, would infringe one or more identifiable patents in that 499 | country that you have reason to believe are valid. 500 | 501 | If, pursuant to or in connection with a single transaction or 502 | arrangement, you convey, or propagate by procuring conveyance of, a 503 | covered work, and grant a patent license to some of the parties 504 | receiving the covered work authorizing them to use, propagate, modify 505 | or convey a specific copy of the covered work, then the patent license 506 | you grant is automatically extended to all recipients of the covered 507 | work and works based on it. 508 | 509 | A patent license is "discriminatory" if it does not include within 510 | the scope of its coverage, prohibits the exercise of, or is 511 | conditioned on the non-exercise of one or more of the rights that are 512 | specifically granted under this License. You may not convey a covered 513 | work if you are a party to an arrangement with a third party that is 514 | in the business of distributing software, under which you make payment 515 | to the third party based on the extent of your activity of conveying 516 | the work, and under which the third party grants, to any of the 517 | parties who would receive the covered work from you, a discriminatory 518 | patent license (a) in connection with copies of the covered work 519 | conveyed by you (or copies made from those copies), or (b) primarily 520 | for and in connection with specific products or compilations that 521 | contain the covered work, unless you entered into that arrangement, 522 | or that patent license was granted, prior to 28 March 2007. 523 | 524 | Nothing in this License shall be construed as excluding or limiting 525 | any implied license or other defenses to infringement that may 526 | otherwise be available to you under applicable patent law. 527 | 528 | 12. No Surrender of Others' Freedom. 529 | 530 | If conditions are imposed on you (whether by court order, agreement or 531 | otherwise) that contradict the conditions of this License, they do not 532 | excuse you from the conditions of this License. If you cannot convey a 533 | covered work so as to satisfy simultaneously your obligations under this 534 | License and any other pertinent obligations, then as a consequence you may 535 | not convey it at all. For example, if you agree to terms that obligate you 536 | to collect a royalty for further conveying from those to whom you convey 537 | the Program, the only way you could satisfy both those terms and this 538 | License would be to refrain entirely from conveying the Program. 539 | 540 | 13. Remote Network Interaction; Use with the GNU General Public License. 541 | 542 | Notwithstanding any other provision of this License, if you modify the 543 | Program, your modified version must prominently offer all users 544 | interacting with it remotely through a computer network (if your version 545 | supports such interaction) an opportunity to receive the Corresponding 546 | Source of your version by providing access to the Corresponding Source 547 | from a network server at no charge, through some standard or customary 548 | means of facilitating copying of software. This Corresponding Source 549 | shall include the Corresponding Source for any work covered by version 3 550 | of the GNU General Public License that is incorporated pursuant to the 551 | following paragraph. 552 | 553 | Notwithstanding any other provision of this License, you have 554 | permission to link or combine any covered work with a work licensed 555 | under version 3 of the GNU General Public License into a single 556 | combined work, and to convey the resulting work. The terms of this 557 | License will continue to apply to the part which is the covered work, 558 | but the work with which it is combined will remain governed by version 559 | 3 of the GNU General Public License. 560 | 561 | 14. Revised Versions of this License. 562 | 563 | The Free Software Foundation may publish revised and/or new versions of 564 | the GNU Affero General Public License from time to time. Such new versions 565 | will be similar in spirit to the present version, but may differ in detail to 566 | address new problems or concerns. 567 | 568 | Each version is given a distinguishing version number. If the 569 | Program specifies that a certain numbered version of the GNU Affero General 570 | Public License "or any later version" applies to it, you have the 571 | option of following the terms and conditions either of that numbered 572 | version or of any later version published by the Free Software 573 | Foundation. If the Program does not specify a version number of the 574 | GNU Affero General Public License, you may choose any version ever published 575 | by the Free Software Foundation. 576 | 577 | If the Program specifies that a proxy can decide which future 578 | versions of the GNU Affero General Public License can be used, that proxy's 579 | public statement of acceptance of a version permanently authorizes you 580 | to choose that version for the Program. 581 | 582 | Later license versions may give you additional or different 583 | permissions. However, no additional obligations are imposed on any 584 | author or copyright holder as a result of your choosing to follow a 585 | later version. 586 | 587 | 15. Disclaimer of Warranty. 588 | 589 | THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY 590 | APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT 591 | HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY 592 | OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, 593 | THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 594 | PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM 595 | IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF 596 | ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 597 | 598 | 16. Limitation of Liability. 599 | 600 | IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING 601 | WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS 602 | THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY 603 | GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE 604 | USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF 605 | DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD 606 | PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), 607 | EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF 608 | SUCH DAMAGES. 609 | 610 | 17. Interpretation of Sections 15 and 16. 611 | 612 | If the disclaimer of warranty and limitation of liability provided 613 | above cannot be given local legal effect according to their terms, 614 | reviewing courts shall apply local law that most closely approximates 615 | an absolute waiver of all civil liability in connection with the 616 | Program, unless a warranty or assumption of liability accompanies a 617 | copy of the Program in return for a fee. 618 | 619 | END OF TERMS AND CONDITIONS 620 | 621 | How to Apply These Terms to Your New Programs 622 | 623 | If you develop a new program, and you want it to be of the greatest 624 | possible use to the public, the best way to achieve this is to make it 625 | free software which everyone can redistribute and change under these terms. 626 | 627 | To do so, attach the following notices to the program. It is safest 628 | to attach them to the start of each source file to most effectively 629 | state the exclusion of warranty; and each file should have at least 630 | the "copyright" line and a pointer to where the full notice is found. 631 | 632 | 633 | Copyright (C) 634 | 635 | This program is free software: you can redistribute it and/or modify 636 | it under the terms of the GNU Affero General Public License as published by 637 | the Free Software Foundation, either version 3 of the License, or 638 | (at your option) any later version. 639 | 640 | This program is distributed in the hope that it will be useful, 641 | but WITHOUT ANY WARRANTY; without even the implied warranty of 642 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 643 | GNU Affero General Public License for more details. 644 | 645 | You should have received a copy of the GNU Affero General Public License 646 | along with this program. If not, see . 647 | 648 | Also add information on how to contact you by electronic and paper mail. 649 | 650 | If your software can interact with users remotely through a computer 651 | network, you should also make sure that it provides a way for users to 652 | get its source. For example, if your program is a web application, its 653 | interface could display a "Source" link that leads users to an archive 654 | of the code. There are many ways you could offer source, and different 655 | solutions will be better for different programs; see section 13 for the 656 | specific requirements. 657 | 658 | You should also get your employer (if you work as a programmer) or school, 659 | if any, to sign a "copyright disclaimer" for the program, if necessary. 660 | For more information on this, and how to apply and follow the GNU AGPL, see 661 | . -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # BiliBot 2 | 3 | bilibot是一个可以监控bilibiliUP直播以及动态的QQ机器人,并附有关键词回复等功能 4 | 5 | ## 二代目 6 | 7 | 在使用的酷Q框架关闭后,BiliBot二代目使用了另外一个框架——mirai 8 | 9 | BiliBot二代目使用的有: 10 | 11 | mirai:https://github.com/mamoe/mirai 12 | 13 | mirai-http-api:https://github.com/project-mirai/mirai-api-http 14 | 15 | node-mirai-sdk:https://github.com/RedBeanN/node-mirai 16 | 17 | # 环境配置 18 | 19 | (README.pdf中有图文解说) 20 | 21 | ## Java 22 | 23 | mirai运行需要java环境,所以首先要安装java环境 24 | 25 | ### linux之ubuntu安装java 26 | 27 | 进入ubuntu终端后在命令行输入`sudo apt install openjdk-11-jdk` 28 | 29 | 安装成功后输入`java -version`查看java版本,判断java是否安装成功 30 | 31 | ## node 32 | 33 | BiliBot二代目开发使用的框架为node的mirai-http-api插件,所以需要安装node.js 34 | 35 | ### linux之ubuntu安装node 36 | 37 | 教程地址:https://www.cnblogs.com/niuben/p/12938501.html 38 | 39 | 1.进入将要安装node的文件夹,输入以下命令下载node安装包: 40 | 41 | `wget https://nodejs.org/dist/v14.15.5/node-v14.15.5-linux-x64.tar.xz` 42 | 43 | 2.解压node安装包: 44 | 45 | `tar -xvf node-v14.15.5-linux-x64.tar.xz` 46 | 47 | 3.配置软连接,全局都可以使用node 48 | 49 | ```bash 50 | mv node-v14.15.5-linux-x64 node // 修改解压包名称 51 | 52 | ln -s /安装node的文件夹/node /usr/bin/node --将node源文件映射到usr/bin下的node文件 53 | 54 | ln -s /安装node的文件夹/node/bin/npm /usr/bin/npm 55 | ``` 56 | 57 | 4.配置node文件安装路径 58 | 59 | ```bash 60 | mkdir node_global 61 | 62 | mkdir node_cache 63 | 64 | npm config set prefix "node_global" 65 | 66 | npm config set cache "node_cache" 67 | ``` 68 | 69 | 5.查看node版本判断是否安装成功 70 | 71 | ```bash 72 | node -v 73 | ``` 74 | 75 | # 运行 76 | 77 | ## 安装mirai 78 | 79 | 找到mirai文件夹,根据你的操作系统选择“mcl-installer-1.0.1-linux-amd64”或是“mcl-installer-1.0.1-windows-amd64.exe”,运行后再根据电脑的环境选择对应的版本 80 | 81 | ### window系统安装mcl 82 | 83 | 将“mcl-installer-1.0.1-windows-amd64.exe”放入向要安装mirai的文件夹中运行,再根据系统环境的选择对应的mirai安装包 84 | 85 | ### linux之ubuntu安装mcl 86 | 87 | 在ubuntu终端进入将要安装mirai的文件夹输入以下命令: 88 | 89 | ```bash 90 | curl -LJO https://github.com/iTXTech/mcl-installer/releases/download/v1.0.2/mcl-installer-1.0.2-linux-amd64 91 | sudo chmod +x mcl-installer-1.0.2-linux-amd64 92 | sudo ./mcl-installer-1.0.2-linux-amd64 93 | ``` 94 | 95 | 再根据系统的环境选择对应的mirai安装包 96 | 97 | ## 安装mirai-http-api 98 | 99 | mirai安装完成后需要先运行一遍以生成“plugins”文件夹: 100 | 101 | 1.进入mirai的安装目录。 102 | 103 | 2.window系统需要在命令行中输入`.\mcl`运行mirai; 104 | 105 | linux系统则要在命令行中输入以下命令行: 106 | 107 | ```bash 108 | sudo chmod +x mcl 109 | sudo ./mcl 110 | ``` 111 | 112 | 3.运行mcl后,输入`/autologin add bot的QQ号 bot的密码`,添加自动登陆的QQ号 113 | 114 | 4.接着安装mirai-api-http:退出mirai,将mirai文件夹中的“mirai-api-http-v1.9.8.mirai.jar”放入“/mirai安装文件夹/plugins”文件夹,再运行mcl就能使用mirai-http了 115 | 116 | 5.再对mirai-api-http进行配置,进入文件夹”/mirai的安装文件夹/config/net.mamoe.mirai-api-http/“,修改”setting.yml”配置文件中的authKey等信息 117 | 118 | ## 运行main.js 119 | 120 | 1.根据mirai的配置,在main.js中对main.js的配置进行自定义。 121 | 122 | 2.接着安装node项目的依赖项: 123 | 124 | ```bash 125 | sudo npm install --registry=https://registry.npm.taobao.org --unsafe-perm 126 | ``` 127 | 128 | 3.接着在命令行中输入`node main.js`即可运行bot,输入`sudo nohup node main.js >/dev/null 2>&1 &`可以后台运行bot且不使用输出日志 129 | 130 | # 其它 131 | 132 | 后台运行mcl:`sudo nohup ./mcl >/dev/null 2>&1 &`,可以不使用输入日志 133 | -------------------------------------------------------------------------------- /README.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wenwed/biliBot/79a4b8fc0f3170367a1cc1a51355be5168e87cd6/README.pdf -------------------------------------------------------------------------------- /database/robot.db: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wenwed/biliBot/79a4b8fc0f3170367a1cc1a51355be5168e87cd6/database/robot.db -------------------------------------------------------------------------------- /images/feizhai.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wenwed/biliBot/79a4b8fc0f3170367a1cc1a51355be5168e87cd6/images/feizhai.jpg -------------------------------------------------------------------------------- /images/ybb.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wenwed/biliBot/79a4b8fc0f3170367a1cc1a51355be5168e87cd6/images/ybb.jpg -------------------------------------------------------------------------------- /main.js: -------------------------------------------------------------------------------- 1 | const Mirai = require("node-mirai-sdk"); 2 | // const { Plain, At } = Mirai.MessageComponent; 3 | const repair = require("./scripts/repair.js"); 4 | 5 | /** 6 | * 服务端设置(*) 7 | * host: mirai-api-http 的地址和端口,默认是 http://127.0.0.1:8080 8 | * authKey: mirai-api-http 的 authKey,建议手动指定 9 | * qq: 当前 BOT 对应的 QQ 号 10 | * enableWebsocket: 是否开启 WebSocket,需要和 mirai-api-http 的设置一致 11 | */ 12 | const bot = new Mirai({ 13 | host: 'http://127.0.0.1:8080', 14 | authKey: '在mirai-api-http的setting.yml中自己定义的authkey', 15 | qq: 你的QQ号, 16 | enableWebsocket: false, 17 | }); 18 | 19 | // auth 认证(*) 20 | bot.onSignal('authed', () => { 21 | console.log(`Authed with session key ${bot.sessionKey}`); 22 | bot.verify(); 23 | }); 24 | 25 | // session 校验回调 26 | bot.onSignal('verified', async () => { 27 | console.log(`Verified with session key ${bot.sessionKey}`); 28 | 29 | // 获取好友列表,需要等待 session 校验之后 (verified) 才能调用 SDK 中的主动接口 30 | const friendList = await bot.getFriendList(); 31 | console.log(`There are ${friendList.length} friends in bot`); 32 | // 运行bilibili爬虫 33 | repair.startBiliSpider(bot); 34 | }); 35 | 36 | // 接受消息,发送消息(*) 37 | bot.onMessage(async message => { 38 | const { type, sender, messageChain, reply, quoteReply, recall } = message; 39 | 40 | //如果为群组消息 41 | if (type === "GroupMessage") { 42 | repair.repairGroup(bot, message, sender, messageChain, reply, quoteReply, recall); 43 | } 44 | // 如果消息为好友消息,使用好友消息处理函数 45 | else if (type === "FriendMessage") { 46 | repair.repairPerson(bot, message, sender, messageChain, reply, quoteReply, recall); 47 | } 48 | }); 49 | 50 | /* 开始监听消息(*) 51 | * 'all' - 监听好友和群 52 | * 'friend' - 只监听好友 53 | * 'group' - 只监听群 54 | * 'temp' - 只监听临时会话 55 | */ 56 | bot.listen('all'); 57 | 58 | // 退出前向 mirai-http-api 发送释放指令(*) 59 | process.on('exit', () => { 60 | bot.release(); 61 | }); -------------------------------------------------------------------------------- /mirai/mcl-installer-1.0.1-linux-amd64: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wenwed/biliBot/79a4b8fc0f3170367a1cc1a51355be5168e87cd6/mirai/mcl-installer-1.0.1-linux-amd64 -------------------------------------------------------------------------------- /mirai/mcl-installer-1.0.1-windows-amd64.exe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wenwed/biliBot/79a4b8fc0f3170367a1cc1a51355be5168e87cd6/mirai/mcl-installer-1.0.1-windows-amd64.exe -------------------------------------------------------------------------------- /mirai/mirai-api-http-v1.9.8.mirai.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wenwed/biliBot/79a4b8fc0f3170367a1cc1a51355be5168e87cd6/mirai/mirai-api-http-v1.9.8.mirai.jar -------------------------------------------------------------------------------- /package-lock.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "bilibot", 3 | "version": "1.0.0", 4 | "lockfileVersion": 1, 5 | "requires": true, 6 | "dependencies": { 7 | "abbrev": { 8 | "version": "1.1.1", 9 | "resolved": "https://registry.npm.taobao.org/abbrev/download/abbrev-1.1.1.tgz", 10 | "integrity": "sha1-+PLIh60Qv2f2NPAFtph/7TF5qsg=" 11 | }, 12 | "ajv": { 13 | "version": "6.12.6", 14 | "resolved": "https://registry.npm.taobao.org/ajv/download/ajv-6.12.6.tgz?cache=0&sync_timestamp=1613033036883&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fajv%2Fdownload%2Fajv-6.12.6.tgz", 15 | "integrity": "sha1-uvWmLoArB9l3A0WG+MO69a3ybfQ=", 16 | "optional": true, 17 | "requires": { 18 | "fast-deep-equal": "^3.1.1", 19 | "fast-json-stable-stringify": "^2.0.0", 20 | "json-schema-traverse": "^0.4.1", 21 | "uri-js": "^4.2.2" 22 | } 23 | }, 24 | "ansi-regex": { 25 | "version": "2.1.1", 26 | "resolved": "https://registry.npm.taobao.org/ansi-regex/download/ansi-regex-2.1.1.tgz", 27 | "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=" 28 | }, 29 | "aproba": { 30 | "version": "1.2.0", 31 | "resolved": "https://registry.npm.taobao.org/aproba/download/aproba-1.2.0.tgz", 32 | "integrity": "sha1-aALmJk79GMeQobDVF/DyYnvyyUo=" 33 | }, 34 | "are-we-there-yet": { 35 | "version": "1.1.5", 36 | "resolved": "https://registry.npm.taobao.org/are-we-there-yet/download/are-we-there-yet-1.1.5.tgz", 37 | "integrity": "sha1-SzXClE8GKov82mZBB2A1D+nd/CE=", 38 | "requires": { 39 | "delegates": "^1.0.0", 40 | "readable-stream": "^2.0.6" 41 | } 42 | }, 43 | "asn1": { 44 | "version": "0.2.4", 45 | "resolved": "https://registry.npm.taobao.org/asn1/download/asn1-0.2.4.tgz", 46 | "integrity": "sha1-jSR136tVO7M+d7VOWeiAu4ziMTY=", 47 | "optional": true, 48 | "requires": { 49 | "safer-buffer": "~2.1.0" 50 | } 51 | }, 52 | "assert-plus": { 53 | "version": "1.0.0", 54 | "resolved": "https://registry.npm.taobao.org/assert-plus/download/assert-plus-1.0.0.tgz", 55 | "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=", 56 | "optional": true 57 | }, 58 | "asynckit": { 59 | "version": "0.4.0", 60 | "resolved": "https://registry.npm.taobao.org/asynckit/download/asynckit-0.4.0.tgz", 61 | "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=" 62 | }, 63 | "aws-sign2": { 64 | "version": "0.7.0", 65 | "resolved": "https://registry.npm.taobao.org/aws-sign2/download/aws-sign2-0.7.0.tgz", 66 | "integrity": "sha1-tG6JCTSpWR8tL2+G1+ap8bP+dqg=", 67 | "optional": true 68 | }, 69 | "aws4": { 70 | "version": "1.11.0", 71 | "resolved": "https://registry.npm.taobao.org/aws4/download/aws4-1.11.0.tgz?cache=0&sync_timestamp=1604101340021&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Faws4%2Fdownload%2Faws4-1.11.0.tgz", 72 | "integrity": "sha1-1h9G2DslGSUOJ4Ta9bCUeai0HFk=", 73 | "optional": true 74 | }, 75 | "axios": { 76 | "version": "0.21.1", 77 | "resolved": "https://registry.npm.taobao.org/axios/download/axios-0.21.1.tgz?cache=0&sync_timestamp=1608609188013&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Faxios%2Fdownload%2Faxios-0.21.1.tgz", 78 | "integrity": "sha1-IlY0gZYvTWvemnbVFu8OXTwJsrg=", 79 | "requires": { 80 | "follow-redirects": "^1.10.0" 81 | } 82 | }, 83 | "balanced-match": { 84 | "version": "1.0.0", 85 | "resolved": "https://registry.npm.taobao.org/balanced-match/download/balanced-match-1.0.0.tgz", 86 | "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=" 87 | }, 88 | "bcrypt-pbkdf": { 89 | "version": "1.0.2", 90 | "resolved": "https://registry.npm.taobao.org/bcrypt-pbkdf/download/bcrypt-pbkdf-1.0.2.tgz", 91 | "integrity": "sha1-pDAdOJtqQ/m2f/PKEaP2Y342Dp4=", 92 | "optional": true, 93 | "requires": { 94 | "tweetnacl": "^0.14.3" 95 | } 96 | }, 97 | "block-stream": { 98 | "version": "0.0.9", 99 | "resolved": "https://registry.npm.taobao.org/block-stream/download/block-stream-0.0.9.tgz", 100 | "integrity": "sha1-E+v+d4oDIFz+A3UUgeu0szAMEmo=", 101 | "optional": true, 102 | "requires": { 103 | "inherits": "~2.0.0" 104 | } 105 | }, 106 | "brace-expansion": { 107 | "version": "1.1.11", 108 | "resolved": "https://registry.npm.taobao.org/brace-expansion/download/brace-expansion-1.1.11.tgz?cache=0&sync_timestamp=1601898201980&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fbrace-expansion%2Fdownload%2Fbrace-expansion-1.1.11.tgz", 109 | "integrity": "sha1-PH/L9SnYcibz0vUrlm/1Jx60Qd0=", 110 | "requires": { 111 | "balanced-match": "^1.0.0", 112 | "concat-map": "0.0.1" 113 | } 114 | }, 115 | "caseless": { 116 | "version": "0.12.0", 117 | "resolved": "https://registry.npm.taobao.org/caseless/download/caseless-0.12.0.tgz", 118 | "integrity": "sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw=", 119 | "optional": true 120 | }, 121 | "chownr": { 122 | "version": "1.1.4", 123 | "resolved": "https://registry.npm.taobao.org/chownr/download/chownr-1.1.4.tgz", 124 | "integrity": "sha1-b8nXtC0ypYNZYzdmbn0ICE2izGs=" 125 | }, 126 | "code-point-at": { 127 | "version": "1.1.0", 128 | "resolved": "https://registry.npm.taobao.org/code-point-at/download/code-point-at-1.1.0.tgz", 129 | "integrity": "sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c=" 130 | }, 131 | "combined-stream": { 132 | "version": "1.0.8", 133 | "resolved": "https://registry.npm.taobao.org/combined-stream/download/combined-stream-1.0.8.tgz", 134 | "integrity": "sha1-w9RaizT9cwYxoRCoolIGgrMdWn8=", 135 | "requires": { 136 | "delayed-stream": "~1.0.0" 137 | } 138 | }, 139 | "concat-map": { 140 | "version": "0.0.1", 141 | "resolved": "https://registry.npm.taobao.org/concat-map/download/concat-map-0.0.1.tgz", 142 | "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=" 143 | }, 144 | "console-control-strings": { 145 | "version": "1.1.0", 146 | "resolved": "https://registry.npm.taobao.org/console-control-strings/download/console-control-strings-1.1.0.tgz", 147 | "integrity": "sha1-PXz0Rk22RG6mRL9LOVB/mFEAjo4=" 148 | }, 149 | "core-util-is": { 150 | "version": "1.0.2", 151 | "resolved": "https://registry.npm.taobao.org/core-util-is/download/core-util-is-1.0.2.tgz", 152 | "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=" 153 | }, 154 | "dashdash": { 155 | "version": "1.14.1", 156 | "resolved": "https://registry.npm.taobao.org/dashdash/download/dashdash-1.14.1.tgz?cache=0&sync_timestamp=1601073602368&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fdashdash%2Fdownload%2Fdashdash-1.14.1.tgz", 157 | "integrity": "sha1-hTz6D3y+L+1d4gMmuN1YEDX24vA=", 158 | "optional": true, 159 | "requires": { 160 | "assert-plus": "^1.0.0" 161 | } 162 | }, 163 | "debug": { 164 | "version": "3.2.7", 165 | "resolved": "https://registry.npm.taobao.org/debug/download/debug-3.2.7.tgz?cache=0&sync_timestamp=1607566571506&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fdebug%2Fdownload%2Fdebug-3.2.7.tgz", 166 | "integrity": "sha1-clgLfpFF+zm2Z2+cXl+xALk0F5o=", 167 | "requires": { 168 | "ms": "^2.1.1" 169 | } 170 | }, 171 | "deep-extend": { 172 | "version": "0.6.0", 173 | "resolved": "https://registry.npm.taobao.org/deep-extend/download/deep-extend-0.6.0.tgz", 174 | "integrity": "sha1-xPp8lUBKF6nD6Mp+FTcxK3NjMKw=" 175 | }, 176 | "delayed-stream": { 177 | "version": "1.0.0", 178 | "resolved": "https://registry.npm.taobao.org/delayed-stream/download/delayed-stream-1.0.0.tgz", 179 | "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=" 180 | }, 181 | "delegates": { 182 | "version": "1.0.0", 183 | "resolved": "https://registry.npm.taobao.org/delegates/download/delegates-1.0.0.tgz", 184 | "integrity": "sha1-hMbhWbgZBP3KWaDvRM2HDTElD5o=" 185 | }, 186 | "detect-libc": { 187 | "version": "1.0.3", 188 | "resolved": "https://registry.npm.taobao.org/detect-libc/download/detect-libc-1.0.3.tgz", 189 | "integrity": "sha1-+hN8S9aY7fVc1c0CrFWfkaTEups=" 190 | }, 191 | "ecc-jsbn": { 192 | "version": "0.1.2", 193 | "resolved": "https://registry.npm.taobao.org/ecc-jsbn/download/ecc-jsbn-0.1.2.tgz", 194 | "integrity": "sha1-OoOpBOVDUyh4dMVkt1SThoSamMk=", 195 | "optional": true, 196 | "requires": { 197 | "jsbn": "~0.1.0", 198 | "safer-buffer": "^2.1.0" 199 | } 200 | }, 201 | "extend": { 202 | "version": "3.0.2", 203 | "resolved": "https://registry.npm.taobao.org/extend/download/extend-3.0.2.tgz", 204 | "integrity": "sha1-+LETa0Bx+9jrFAr/hYsQGewpFfo=", 205 | "optional": true 206 | }, 207 | "extsprintf": { 208 | "version": "1.3.0", 209 | "resolved": "https://registry.npm.taobao.org/extsprintf/download/extsprintf-1.3.0.tgz", 210 | "integrity": "sha1-lpGEQOMEGnpBT4xS48V06zw+HgU=", 211 | "optional": true 212 | }, 213 | "fast-deep-equal": { 214 | "version": "3.1.3", 215 | "resolved": "https://registry.npm.taobao.org/fast-deep-equal/download/fast-deep-equal-3.1.3.tgz", 216 | "integrity": "sha1-On1WtVnWy8PrUSMlJE5hmmXGxSU=", 217 | "optional": true 218 | }, 219 | "fast-json-stable-stringify": { 220 | "version": "2.1.0", 221 | "resolved": "https://registry.npm.taobao.org/fast-json-stable-stringify/download/fast-json-stable-stringify-2.1.0.tgz", 222 | "integrity": "sha1-h0v2nG9ATCtdmcSBNBOZ/VWJJjM=", 223 | "optional": true 224 | }, 225 | "follow-redirects": { 226 | "version": "1.13.2", 227 | "resolved": "https://registry.npm.taobao.org/follow-redirects/download/follow-redirects-1.13.2.tgz?cache=0&sync_timestamp=1611606737937&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Ffollow-redirects%2Fdownload%2Ffollow-redirects-1.13.2.tgz", 228 | "integrity": "sha1-3XPI7/wScoulz0JZ12DqX7g+MUc=" 229 | }, 230 | "forever-agent": { 231 | "version": "0.6.1", 232 | "resolved": "https://registry.npm.taobao.org/forever-agent/download/forever-agent-0.6.1.tgz", 233 | "integrity": "sha1-+8cfDEGt6zf5bFd60e1C2P2sypE=", 234 | "optional": true 235 | }, 236 | "form-data": { 237 | "version": "3.0.0", 238 | "resolved": "https://registry.npm.taobao.org/form-data/download/form-data-3.0.0.tgz", 239 | "integrity": "sha1-MbfjnIXxNVtxOe4MZHzw3n+DxoI=", 240 | "requires": { 241 | "asynckit": "^0.4.0", 242 | "combined-stream": "^1.0.8", 243 | "mime-types": "^2.1.12" 244 | } 245 | }, 246 | "fs-minipass": { 247 | "version": "1.2.7", 248 | "resolved": "https://registry.npm.taobao.org/fs-minipass/download/fs-minipass-1.2.7.tgz", 249 | "integrity": "sha1-zP+FcIQef+QmVpPaiJNsVa7X98c=", 250 | "requires": { 251 | "minipass": "^2.6.0" 252 | } 253 | }, 254 | "fs.realpath": { 255 | "version": "1.0.0", 256 | "resolved": "https://registry.npm.taobao.org/fs.realpath/download/fs.realpath-1.0.0.tgz", 257 | "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=" 258 | }, 259 | "fstream": { 260 | "version": "1.0.12", 261 | "resolved": "https://registry.npm.taobao.org/fstream/download/fstream-1.0.12.tgz", 262 | "integrity": "sha1-Touo7i1Ivk99DeUFRVVI6uWTIEU=", 263 | "optional": true, 264 | "requires": { 265 | "graceful-fs": "^4.1.2", 266 | "inherits": "~2.0.0", 267 | "mkdirp": ">=0.5 0", 268 | "rimraf": "2" 269 | } 270 | }, 271 | "gauge": { 272 | "version": "2.7.4", 273 | "resolved": "https://registry.npm.taobao.org/gauge/download/gauge-2.7.4.tgz", 274 | "integrity": "sha1-LANAXHU4w51+s3sxcCLjJfsBi/c=", 275 | "requires": { 276 | "aproba": "^1.0.3", 277 | "console-control-strings": "^1.0.0", 278 | "has-unicode": "^2.0.0", 279 | "object-assign": "^4.1.0", 280 | "signal-exit": "^3.0.0", 281 | "string-width": "^1.0.1", 282 | "strip-ansi": "^3.0.1", 283 | "wide-align": "^1.1.0" 284 | } 285 | }, 286 | "getpass": { 287 | "version": "0.1.7", 288 | "resolved": "https://registry.npm.taobao.org/getpass/download/getpass-0.1.7.tgz", 289 | "integrity": "sha1-Xv+OPmhNVprkyysSgmBOi6YhSfo=", 290 | "optional": true, 291 | "requires": { 292 | "assert-plus": "^1.0.0" 293 | } 294 | }, 295 | "glob": { 296 | "version": "7.1.6", 297 | "resolved": "https://registry.npm.taobao.org/glob/download/glob-7.1.6.tgz?cache=0&sync_timestamp=1573203677246&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fglob%2Fdownload%2Fglob-7.1.6.tgz", 298 | "integrity": "sha1-FB8zuBp8JJLhJVlDB0gMRmeSeKY=", 299 | "requires": { 300 | "fs.realpath": "^1.0.0", 301 | "inflight": "^1.0.4", 302 | "inherits": "2", 303 | "minimatch": "^3.0.4", 304 | "once": "^1.3.0", 305 | "path-is-absolute": "^1.0.0" 306 | } 307 | }, 308 | "graceful-fs": { 309 | "version": "4.2.6", 310 | "resolved": "https://registry.npm.taobao.org/graceful-fs/download/graceful-fs-4.2.6.tgz", 311 | "integrity": "sha1-/wQLKwhTsjw9MQJ1I3BvGIXXa+4=", 312 | "optional": true 313 | }, 314 | "har-schema": { 315 | "version": "2.0.0", 316 | "resolved": "https://registry.npm.taobao.org/har-schema/download/har-schema-2.0.0.tgz", 317 | "integrity": "sha1-qUwiJOvKwEeCoNkDVSHyRzW37JI=", 318 | "optional": true 319 | }, 320 | "har-validator": { 321 | "version": "5.1.5", 322 | "resolved": "https://registry.npm.taobao.org/har-validator/download/har-validator-5.1.5.tgz?cache=0&sync_timestamp=1596082838391&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fhar-validator%2Fdownload%2Fhar-validator-5.1.5.tgz", 323 | "integrity": "sha1-HwgDufjLIMD6E4It8ezds2veHv0=", 324 | "optional": true, 325 | "requires": { 326 | "ajv": "^6.12.3", 327 | "har-schema": "^2.0.0" 328 | } 329 | }, 330 | "has-unicode": { 331 | "version": "2.0.1", 332 | "resolved": "https://registry.npm.taobao.org/has-unicode/download/has-unicode-2.0.1.tgz", 333 | "integrity": "sha1-4Ob+aijPUROIVeCG0Wkedx3iqLk=" 334 | }, 335 | "http-signature": { 336 | "version": "1.2.0", 337 | "resolved": "https://registry.npm.taobao.org/http-signature/download/http-signature-1.2.0.tgz?cache=0&sync_timestamp=1600868441269&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fhttp-signature%2Fdownload%2Fhttp-signature-1.2.0.tgz", 338 | "integrity": "sha1-muzZJRFHcvPZW2WmCruPfBj7rOE=", 339 | "optional": true, 340 | "requires": { 341 | "assert-plus": "^1.0.0", 342 | "jsprim": "^1.2.2", 343 | "sshpk": "^1.7.0" 344 | } 345 | }, 346 | "iconv-lite": { 347 | "version": "0.4.24", 348 | "resolved": "https://registry.npm.taobao.org/iconv-lite/download/iconv-lite-0.4.24.tgz?cache=0&sync_timestamp=1594184250387&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Ficonv-lite%2Fdownload%2Ficonv-lite-0.4.24.tgz", 349 | "integrity": "sha1-ICK0sl+93CHS9SSXSkdKr+czkIs=", 350 | "requires": { 351 | "safer-buffer": ">= 2.1.2 < 3" 352 | } 353 | }, 354 | "ignore-walk": { 355 | "version": "3.0.3", 356 | "resolved": "https://registry.npm.taobao.org/ignore-walk/download/ignore-walk-3.0.3.tgz", 357 | "integrity": "sha1-AX4kRxhL/q3nwjjkrv3R6PlbHjc=", 358 | "requires": { 359 | "minimatch": "^3.0.4" 360 | } 361 | }, 362 | "inflight": { 363 | "version": "1.0.6", 364 | "resolved": "https://registry.npm.taobao.org/inflight/download/inflight-1.0.6.tgz", 365 | "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", 366 | "requires": { 367 | "once": "^1.3.0", 368 | "wrappy": "1" 369 | } 370 | }, 371 | "inherits": { 372 | "version": "2.0.4", 373 | "resolved": "https://registry.npm.taobao.org/inherits/download/inherits-2.0.4.tgz", 374 | "integrity": "sha1-D6LGT5MpF8NDOg3tVTY6rjdBa3w=" 375 | }, 376 | "ini": { 377 | "version": "1.3.8", 378 | "resolved": "https://registry.npm.taobao.org/ini/download/ini-1.3.8.tgz?cache=0&sync_timestamp=1607907801722&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fini%2Fdownload%2Fini-1.3.8.tgz", 379 | "integrity": "sha1-op2kJbSIBvNHZ6Tvzjlyaa8oQyw=" 380 | }, 381 | "is-fullwidth-code-point": { 382 | "version": "1.0.0", 383 | "resolved": "https://registry.npm.taobao.org/is-fullwidth-code-point/download/is-fullwidth-code-point-1.0.0.tgz", 384 | "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", 385 | "requires": { 386 | "number-is-nan": "^1.0.0" 387 | } 388 | }, 389 | "is-typedarray": { 390 | "version": "1.0.0", 391 | "resolved": "https://registry.npm.taobao.org/is-typedarray/download/is-typedarray-1.0.0.tgz", 392 | "integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=", 393 | "optional": true 394 | }, 395 | "isarray": { 396 | "version": "1.0.0", 397 | "resolved": "https://registry.npm.taobao.org/isarray/download/isarray-1.0.0.tgz", 398 | "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=" 399 | }, 400 | "isexe": { 401 | "version": "2.0.0", 402 | "resolved": "https://registry.npm.taobao.org/isexe/download/isexe-2.0.0.tgz", 403 | "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=", 404 | "optional": true 405 | }, 406 | "isstream": { 407 | "version": "0.1.2", 408 | "resolved": "https://registry.npm.taobao.org/isstream/download/isstream-0.1.2.tgz", 409 | "integrity": "sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo=", 410 | "optional": true 411 | }, 412 | "jsbn": { 413 | "version": "0.1.1", 414 | "resolved": "https://registry.npm.taobao.org/jsbn/download/jsbn-0.1.1.tgz", 415 | "integrity": "sha1-peZUwuWi3rXyAdls77yoDA7y9RM=", 416 | "optional": true 417 | }, 418 | "json-schema": { 419 | "version": "0.2.3", 420 | "resolved": "https://registry.npm.taobao.org/json-schema/download/json-schema-0.2.3.tgz?cache=0&sync_timestamp=1609553686459&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fjson-schema%2Fdownload%2Fjson-schema-0.2.3.tgz", 421 | "integrity": "sha1-tIDIkuWaLwWVTOcnvT8qTogvnhM=", 422 | "optional": true 423 | }, 424 | "json-schema-traverse": { 425 | "version": "0.4.1", 426 | "resolved": "https://registry.npm.taobao.org/json-schema-traverse/download/json-schema-traverse-0.4.1.tgz?cache=0&sync_timestamp=1607998035113&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fjson-schema-traverse%2Fdownload%2Fjson-schema-traverse-0.4.1.tgz", 427 | "integrity": "sha1-afaofZUTq4u4/mO9sJecRI5oRmA=", 428 | "optional": true 429 | }, 430 | "json-stringify-safe": { 431 | "version": "5.0.1", 432 | "resolved": "https://registry.npm.taobao.org/json-stringify-safe/download/json-stringify-safe-5.0.1.tgz", 433 | "integrity": "sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus=", 434 | "optional": true 435 | }, 436 | "jsprim": { 437 | "version": "1.4.1", 438 | "resolved": "https://registry.npm.taobao.org/jsprim/download/jsprim-1.4.1.tgz", 439 | "integrity": "sha1-MT5mvB5cwG5Di8G3SZwuXFastqI=", 440 | "optional": true, 441 | "requires": { 442 | "assert-plus": "1.0.0", 443 | "extsprintf": "1.3.0", 444 | "json-schema": "0.2.3", 445 | "verror": "1.10.0" 446 | } 447 | }, 448 | "mime-db": { 449 | "version": "1.45.0", 450 | "resolved": "https://registry.npm.taobao.org/mime-db/download/mime-db-1.45.0.tgz?cache=0&sync_timestamp=1600831145015&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fmime-db%2Fdownload%2Fmime-db-1.45.0.tgz", 451 | "integrity": "sha1-zO7aIczXw6dF66LezVXUtz54eeo=" 452 | }, 453 | "mime-types": { 454 | "version": "2.1.28", 455 | "resolved": "https://registry.npm.taobao.org/mime-types/download/mime-types-2.1.28.tgz?cache=0&sync_timestamp=1609559894106&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fmime-types%2Fdownload%2Fmime-types-2.1.28.tgz", 456 | "integrity": "sha1-EWDEdX6rLFNjiI4AUnPs950qDs0=", 457 | "requires": { 458 | "mime-db": "1.45.0" 459 | } 460 | }, 461 | "minimatch": { 462 | "version": "3.0.4", 463 | "resolved": "https://registry.npm.taobao.org/minimatch/download/minimatch-3.0.4.tgz", 464 | "integrity": "sha1-UWbihkV/AzBgZL5Ul+jbsMPTIIM=", 465 | "requires": { 466 | "brace-expansion": "^1.1.7" 467 | } 468 | }, 469 | "minimist": { 470 | "version": "1.2.5", 471 | "resolved": "https://registry.npm.taobao.org/minimist/download/minimist-1.2.5.tgz?cache=0&sync_timestamp=1584060927134&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fminimist%2Fdownload%2Fminimist-1.2.5.tgz", 472 | "integrity": "sha1-Z9ZgFLZqaoqqDAg8X9WN9OTpdgI=" 473 | }, 474 | "minipass": { 475 | "version": "2.9.0", 476 | "resolved": "https://registry.npm.taobao.org/minipass/download/minipass-2.9.0.tgz", 477 | "integrity": "sha1-5xN2Ln0+Mv7YAxFc+T4EvKn8yaY=", 478 | "requires": { 479 | "safe-buffer": "^5.1.2", 480 | "yallist": "^3.0.0" 481 | } 482 | }, 483 | "minizlib": { 484 | "version": "1.3.3", 485 | "resolved": "https://registry.npm.taobao.org/minizlib/download/minizlib-1.3.3.tgz", 486 | "integrity": "sha1-IpDeloGKNMKVUcio0wEha9Zahh0=", 487 | "requires": { 488 | "minipass": "^2.9.0" 489 | } 490 | }, 491 | "mkdirp": { 492 | "version": "0.5.5", 493 | "resolved": "https://registry.npm.taobao.org/mkdirp/download/mkdirp-0.5.5.tgz?cache=0&sync_timestamp=1587535418745&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fmkdirp%2Fdownload%2Fmkdirp-0.5.5.tgz", 494 | "integrity": "sha1-2Rzv1i0UNsoPQWIOJRKI1CAJne8=", 495 | "requires": { 496 | "minimist": "^1.2.5" 497 | } 498 | }, 499 | "ms": { 500 | "version": "2.1.3", 501 | "resolved": "https://registry.npm.taobao.org/ms/download/ms-2.1.3.tgz?cache=0&sync_timestamp=1607433872491&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fms%2Fdownload%2Fms-2.1.3.tgz", 502 | "integrity": "sha1-V0yBOM4dK1hh8LRFedut1gxmFbI=" 503 | }, 504 | "needle": { 505 | "version": "2.6.0", 506 | "resolved": "https://registry.npm.taobao.org/needle/download/needle-2.6.0.tgz", 507 | "integrity": "sha1-JNu1XyUJ4jJLSpnWH0E5ggE8zb4=", 508 | "requires": { 509 | "debug": "^3.2.6", 510 | "iconv-lite": "^0.4.4", 511 | "sax": "^1.2.4" 512 | } 513 | }, 514 | "node-addon-api": { 515 | "version": "2.0.0", 516 | "resolved": "https://registry.npm.taobao.org/node-addon-api/download/node-addon-api-2.0.0.tgz?cache=0&sync_timestamp=1608165738569&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fnode-addon-api%2Fdownload%2Fnode-addon-api-2.0.0.tgz", 517 | "integrity": "sha1-+a+413epFSUkSwF3XqDdvhElSDs=" 518 | }, 519 | "node-gyp": { 520 | "version": "3.8.0", 521 | "resolved": "https://registry.npm.taobao.org/node-gyp/download/node-gyp-3.8.0.tgz?cache=0&sync_timestamp=1602898543148&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fnode-gyp%2Fdownload%2Fnode-gyp-3.8.0.tgz", 522 | "integrity": "sha1-VAMEJhwzDoDQ1e3OJTpoyzlkIYw=", 523 | "optional": true, 524 | "requires": { 525 | "fstream": "^1.0.0", 526 | "glob": "^7.0.3", 527 | "graceful-fs": "^4.1.2", 528 | "mkdirp": "^0.5.0", 529 | "nopt": "2 || 3", 530 | "npmlog": "0 || 1 || 2 || 3 || 4", 531 | "osenv": "0", 532 | "request": "^2.87.0", 533 | "rimraf": "2", 534 | "semver": "~5.3.0", 535 | "tar": "^2.0.0", 536 | "which": "1" 537 | } 538 | }, 539 | "node-mirai-sdk": { 540 | "version": "0.2.3", 541 | "resolved": "https://registry.npm.taobao.org/node-mirai-sdk/download/node-mirai-sdk-0.2.3.tgz", 542 | "integrity": "sha1-o+BKZKLE6OIxNsr594tbl9oxF6I=", 543 | "requires": { 544 | "axios": "^0.21.1", 545 | "form-data": "^3.0.0", 546 | "ws": "^7.2.3" 547 | } 548 | }, 549 | "node-pre-gyp": { 550 | "version": "0.11.0", 551 | "resolved": "https://registry.npm.taobao.org/node-pre-gyp/download/node-pre-gyp-0.11.0.tgz", 552 | "integrity": "sha1-2x8zIVJy9pLNOPAyOOPptHxd0FQ=", 553 | "requires": { 554 | "detect-libc": "^1.0.2", 555 | "mkdirp": "^0.5.1", 556 | "needle": "^2.2.1", 557 | "nopt": "^4.0.1", 558 | "npm-packlist": "^1.1.6", 559 | "npmlog": "^4.0.2", 560 | "rc": "^1.2.7", 561 | "rimraf": "^2.6.1", 562 | "semver": "^5.3.0", 563 | "tar": "^4" 564 | }, 565 | "dependencies": { 566 | "nopt": { 567 | "version": "4.0.3", 568 | "resolved": "https://registry.npm.taobao.org/nopt/download/nopt-4.0.3.tgz?cache=0&sync_timestamp=1597649892953&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fnopt%2Fdownload%2Fnopt-4.0.3.tgz", 569 | "integrity": "sha1-o3XK2dAv2SEnjZVMIlTVqlfhXkg=", 570 | "requires": { 571 | "abbrev": "1", 572 | "osenv": "^0.1.4" 573 | } 574 | }, 575 | "tar": { 576 | "version": "4.4.13", 577 | "resolved": "https://registry.npm.taobao.org/tar/download/tar-4.4.13.tgz?cache=0&sync_timestamp=1610045888507&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Ftar%2Fdownload%2Ftar-4.4.13.tgz", 578 | "integrity": "sha1-Q7NkvFKIjVVSmGN7ENYHkCVKtSU=", 579 | "requires": { 580 | "chownr": "^1.1.1", 581 | "fs-minipass": "^1.2.5", 582 | "minipass": "^2.8.6", 583 | "minizlib": "^1.2.1", 584 | "mkdirp": "^0.5.0", 585 | "safe-buffer": "^5.1.2", 586 | "yallist": "^3.0.3" 587 | } 588 | } 589 | } 590 | }, 591 | "nopt": { 592 | "version": "3.0.6", 593 | "resolved": "https://registry.npm.taobao.org/nopt/download/nopt-3.0.6.tgz?cache=0&sync_timestamp=1597649892953&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fnopt%2Fdownload%2Fnopt-3.0.6.tgz", 594 | "integrity": "sha1-xkZdvwirzU2zWTF/eaxopkayj/k=", 595 | "optional": true, 596 | "requires": { 597 | "abbrev": "1" 598 | } 599 | }, 600 | "npm-bundled": { 601 | "version": "1.1.1", 602 | "resolved": "https://registry.npm.taobao.org/npm-bundled/download/npm-bundled-1.1.1.tgz", 603 | "integrity": "sha1-Ht1XCGWpTNsbyCIHdeKUZsn7I0s=", 604 | "requires": { 605 | "npm-normalize-package-bin": "^1.0.1" 606 | } 607 | }, 608 | "npm-normalize-package-bin": { 609 | "version": "1.0.1", 610 | "resolved": "https://registry.npm.taobao.org/npm-normalize-package-bin/download/npm-normalize-package-bin-1.0.1.tgz", 611 | "integrity": "sha1-bnmkHyP9I1wGIyGCKNp9nCO49uI=" 612 | }, 613 | "npm-packlist": { 614 | "version": "1.4.8", 615 | "resolved": "https://registry.npm.taobao.org/npm-packlist/download/npm-packlist-1.4.8.tgz?cache=0&sync_timestamp=1603319937404&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fnpm-packlist%2Fdownload%2Fnpm-packlist-1.4.8.tgz", 616 | "integrity": "sha1-Vu5swTW5+YrT1Rwcldoiu7my7z4=", 617 | "requires": { 618 | "ignore-walk": "^3.0.1", 619 | "npm-bundled": "^1.0.1", 620 | "npm-normalize-package-bin": "^1.0.1" 621 | } 622 | }, 623 | "npmlog": { 624 | "version": "4.1.2", 625 | "resolved": "https://registry.npm.taobao.org/npmlog/download/npmlog-4.1.2.tgz", 626 | "integrity": "sha1-CKfyqL9zRgR3mp76StXMcXq7lUs=", 627 | "requires": { 628 | "are-we-there-yet": "~1.1.2", 629 | "console-control-strings": "~1.1.0", 630 | "gauge": "~2.7.3", 631 | "set-blocking": "~2.0.0" 632 | } 633 | }, 634 | "number-is-nan": { 635 | "version": "1.0.1", 636 | "resolved": "https://registry.npm.taobao.org/number-is-nan/download/number-is-nan-1.0.1.tgz?cache=0&sync_timestamp=1581061498787&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fnumber-is-nan%2Fdownload%2Fnumber-is-nan-1.0.1.tgz", 637 | "integrity": "sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0=" 638 | }, 639 | "oauth-sign": { 640 | "version": "0.9.0", 641 | "resolved": "https://registry.npm.taobao.org/oauth-sign/download/oauth-sign-0.9.0.tgz", 642 | "integrity": "sha1-R6ewFrqmi1+g7PPe4IqFxnmsZFU=", 643 | "optional": true 644 | }, 645 | "object-assign": { 646 | "version": "4.1.1", 647 | "resolved": "https://registry.npm.taobao.org/object-assign/download/object-assign-4.1.1.tgz", 648 | "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=" 649 | }, 650 | "once": { 651 | "version": "1.4.0", 652 | "resolved": "https://registry.npm.taobao.org/once/download/once-1.4.0.tgz", 653 | "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", 654 | "requires": { 655 | "wrappy": "1" 656 | } 657 | }, 658 | "os-homedir": { 659 | "version": "1.0.2", 660 | "resolved": "https://registry.npm.taobao.org/os-homedir/download/os-homedir-1.0.2.tgz", 661 | "integrity": "sha1-/7xJiDNuDoM94MFox+8VISGqf7M=" 662 | }, 663 | "os-tmpdir": { 664 | "version": "1.0.2", 665 | "resolved": "https://registry.npm.taobao.org/os-tmpdir/download/os-tmpdir-1.0.2.tgz", 666 | "integrity": "sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ=" 667 | }, 668 | "osenv": { 669 | "version": "0.1.5", 670 | "resolved": "https://registry.npm.taobao.org/osenv/download/osenv-0.1.5.tgz", 671 | "integrity": "sha1-hc36+uso6Gd/QW4odZK18/SepBA=", 672 | "requires": { 673 | "os-homedir": "^1.0.0", 674 | "os-tmpdir": "^1.0.0" 675 | } 676 | }, 677 | "path-is-absolute": { 678 | "version": "1.0.1", 679 | "resolved": "https://registry.npm.taobao.org/path-is-absolute/download/path-is-absolute-1.0.1.tgz", 680 | "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=" 681 | }, 682 | "performance-now": { 683 | "version": "2.1.0", 684 | "resolved": "https://registry.npm.taobao.org/performance-now/download/performance-now-2.1.0.tgz", 685 | "integrity": "sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns=", 686 | "optional": true 687 | }, 688 | "process-nextick-args": { 689 | "version": "2.0.1", 690 | "resolved": "https://registry.npm.taobao.org/process-nextick-args/download/process-nextick-args-2.0.1.tgz", 691 | "integrity": "sha1-eCDZsWEgzFXKmud5JoCufbptf+I=" 692 | }, 693 | "psl": { 694 | "version": "1.8.0", 695 | "resolved": "https://registry.npm.taobao.org/psl/download/psl-1.8.0.tgz", 696 | "integrity": "sha1-kyb4vPsBOtzABf3/BWrM4CDlHCQ=", 697 | "optional": true 698 | }, 699 | "punycode": { 700 | "version": "2.1.1", 701 | "resolved": "https://registry.npm.taobao.org/punycode/download/punycode-2.1.1.tgz", 702 | "integrity": "sha1-tYsBCsQMIsVldhbI0sLALHv0eew=", 703 | "optional": true 704 | }, 705 | "qs": { 706 | "version": "6.5.2", 707 | "resolved": "https://registry.npm.taobao.org/qs/download/qs-6.5.2.tgz?cache=0&sync_timestamp=1610598229410&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fqs%2Fdownload%2Fqs-6.5.2.tgz", 708 | "integrity": "sha1-yzroBuh0BERYTvFUzo7pjUA/PjY=", 709 | "optional": true 710 | }, 711 | "rc": { 712 | "version": "1.2.8", 713 | "resolved": "https://registry.npm.taobao.org/rc/download/rc-1.2.8.tgz?cache=0&sync_timestamp=1593529723659&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Frc%2Fdownload%2Frc-1.2.8.tgz", 714 | "integrity": "sha1-zZJL9SAKB1uDwYjNa54hG3/A0+0=", 715 | "requires": { 716 | "deep-extend": "^0.6.0", 717 | "ini": "~1.3.0", 718 | "minimist": "^1.2.0", 719 | "strip-json-comments": "~2.0.1" 720 | } 721 | }, 722 | "readable-stream": { 723 | "version": "2.3.7", 724 | "resolved": "https://registry.npm.taobao.org/readable-stream/download/readable-stream-2.3.7.tgz", 725 | "integrity": "sha1-Hsoc9xGu+BTAT2IlKjamL2yyO1c=", 726 | "requires": { 727 | "core-util-is": "~1.0.0", 728 | "inherits": "~2.0.3", 729 | "isarray": "~1.0.0", 730 | "process-nextick-args": "~2.0.0", 731 | "safe-buffer": "~5.1.1", 732 | "string_decoder": "~1.1.1", 733 | "util-deprecate": "~1.0.1" 734 | } 735 | }, 736 | "request": { 737 | "version": "2.88.2", 738 | "resolved": "https://registry.npm.taobao.org/request/download/request-2.88.2.tgz", 739 | "integrity": "sha1-1zyRhzHLWofaBH4gcjQUb2ZNErM=", 740 | "optional": true, 741 | "requires": { 742 | "aws-sign2": "~0.7.0", 743 | "aws4": "^1.8.0", 744 | "caseless": "~0.12.0", 745 | "combined-stream": "~1.0.6", 746 | "extend": "~3.0.2", 747 | "forever-agent": "~0.6.1", 748 | "form-data": "~2.3.2", 749 | "har-validator": "~5.1.3", 750 | "http-signature": "~1.2.0", 751 | "is-typedarray": "~1.0.0", 752 | "isstream": "~0.1.2", 753 | "json-stringify-safe": "~5.0.1", 754 | "mime-types": "~2.1.19", 755 | "oauth-sign": "~0.9.0", 756 | "performance-now": "^2.1.0", 757 | "qs": "~6.5.2", 758 | "safe-buffer": "^5.1.2", 759 | "tough-cookie": "~2.5.0", 760 | "tunnel-agent": "^0.6.0", 761 | "uuid": "^3.3.2" 762 | }, 763 | "dependencies": { 764 | "form-data": { 765 | "version": "2.3.3", 766 | "resolved": "https://registry.npm.taobao.org/form-data/download/form-data-2.3.3.tgz", 767 | "integrity": "sha1-3M5SwF9kTymManq5Nr1yTO/786Y=", 768 | "optional": true, 769 | "requires": { 770 | "asynckit": "^0.4.0", 771 | "combined-stream": "^1.0.6", 772 | "mime-types": "^2.1.12" 773 | } 774 | } 775 | } 776 | }, 777 | "rimraf": { 778 | "version": "2.7.1", 779 | "resolved": "https://registry.npm.taobao.org/rimraf/download/rimraf-2.7.1.tgz", 780 | "integrity": "sha1-NXl/E6f9rcVmFCwp1PB8ytSD4+w=", 781 | "requires": { 782 | "glob": "^7.1.3" 783 | } 784 | }, 785 | "safe-buffer": { 786 | "version": "5.1.2", 787 | "resolved": "https://registry.npm.taobao.org/safe-buffer/download/safe-buffer-5.1.2.tgz", 788 | "integrity": "sha1-mR7GnSluAxN0fVm9/St0XDX4go0=" 789 | }, 790 | "safer-buffer": { 791 | "version": "2.1.2", 792 | "resolved": "https://registry.npm.taobao.org/safer-buffer/download/safer-buffer-2.1.2.tgz", 793 | "integrity": "sha1-RPoWGwGHuVSd2Eu5GAL5vYOFzWo=" 794 | }, 795 | "sax": { 796 | "version": "1.2.4", 797 | "resolved": "https://registry.npm.taobao.org/sax/download/sax-1.2.4.tgz?cache=0&sync_timestamp=1593529670203&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fsax%2Fdownload%2Fsax-1.2.4.tgz", 798 | "integrity": "sha1-KBYjTiN4vdxOU1T6tcqold9xANk=" 799 | }, 800 | "semver": { 801 | "version": "5.3.0", 802 | "resolved": "https://registry.npm.taobao.org/semver/download/semver-5.3.0.tgz?cache=0&sync_timestamp=1606854810932&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fsemver%2Fdownload%2Fsemver-5.3.0.tgz", 803 | "integrity": "sha1-myzl094C0XxgEq0yaqa00M9U+U8=" 804 | }, 805 | "set-blocking": { 806 | "version": "2.0.0", 807 | "resolved": "https://registry.npm.taobao.org/set-blocking/download/set-blocking-2.0.0.tgz", 808 | "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=" 809 | }, 810 | "signal-exit": { 811 | "version": "3.0.3", 812 | "resolved": "https://registry.npm.taobao.org/signal-exit/download/signal-exit-3.0.3.tgz", 813 | "integrity": "sha1-oUEMLt2PB3sItOJTyOrPyvBXRhw=" 814 | }, 815 | "sqlite3": { 816 | "version": "5.0.0", 817 | "resolved": "https://registry.npm.taobao.org/sqlite3/download/sqlite3-5.0.0.tgz", 818 | "integrity": "sha1-G/7yFRxrxIo6sabBJgiLuN0jNWY=", 819 | "requires": { 820 | "node-addon-api": "2.0.0", 821 | "node-gyp": "3.x", 822 | "node-pre-gyp": "^0.11.0" 823 | } 824 | }, 825 | "sshpk": { 826 | "version": "1.16.1", 827 | "resolved": "https://registry.npm.taobao.org/sshpk/download/sshpk-1.16.1.tgz", 828 | "integrity": "sha1-+2YcC+8ps520B2nuOfpwCT1vaHc=", 829 | "optional": true, 830 | "requires": { 831 | "asn1": "~0.2.3", 832 | "assert-plus": "^1.0.0", 833 | "bcrypt-pbkdf": "^1.0.0", 834 | "dashdash": "^1.12.0", 835 | "ecc-jsbn": "~0.1.1", 836 | "getpass": "^0.1.1", 837 | "jsbn": "~0.1.0", 838 | "safer-buffer": "^2.0.2", 839 | "tweetnacl": "~0.14.0" 840 | } 841 | }, 842 | "string-width": { 843 | "version": "1.0.2", 844 | "resolved": "https://registry.npm.taobao.org/string-width/download/string-width-1.0.2.tgz", 845 | "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", 846 | "requires": { 847 | "code-point-at": "^1.0.0", 848 | "is-fullwidth-code-point": "^1.0.0", 849 | "strip-ansi": "^3.0.0" 850 | } 851 | }, 852 | "string_decoder": { 853 | "version": "1.1.1", 854 | "resolved": "https://registry.npm.taobao.org/string_decoder/download/string_decoder-1.1.1.tgz", 855 | "integrity": "sha1-nPFhG6YmhdcDCunkujQUnDrwP8g=", 856 | "requires": { 857 | "safe-buffer": "~5.1.0" 858 | } 859 | }, 860 | "strip-ansi": { 861 | "version": "3.0.1", 862 | "resolved": "https://registry.npm.taobao.org/strip-ansi/download/strip-ansi-3.0.1.tgz", 863 | "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", 864 | "requires": { 865 | "ansi-regex": "^2.0.0" 866 | } 867 | }, 868 | "strip-json-comments": { 869 | "version": "2.0.1", 870 | "resolved": "https://registry.npm.taobao.org/strip-json-comments/download/strip-json-comments-2.0.1.tgz?cache=0&sync_timestamp=1594567555399&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fstrip-json-comments%2Fdownload%2Fstrip-json-comments-2.0.1.tgz", 871 | "integrity": "sha1-PFMZQukIwml8DsNEhYwobHygpgo=" 872 | }, 873 | "tar": { 874 | "version": "2.2.2", 875 | "resolved": "https://registry.npm.taobao.org/tar/download/tar-2.2.2.tgz?cache=0&sync_timestamp=1610045888507&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Ftar%2Fdownload%2Ftar-2.2.2.tgz", 876 | "integrity": "sha1-DKiEhWLHKZuLRG/2pNYM27I+3EA=", 877 | "optional": true, 878 | "requires": { 879 | "block-stream": "*", 880 | "fstream": "^1.0.12", 881 | "inherits": "2" 882 | } 883 | }, 884 | "tough-cookie": { 885 | "version": "2.5.0", 886 | "resolved": "https://registry.npm.taobao.org/tough-cookie/download/tough-cookie-2.5.0.tgz", 887 | "integrity": "sha1-zZ+yoKodWhK0c72fuW+j3P9lreI=", 888 | "optional": true, 889 | "requires": { 890 | "psl": "^1.1.28", 891 | "punycode": "^2.1.1" 892 | } 893 | }, 894 | "tunnel-agent": { 895 | "version": "0.6.0", 896 | "resolved": "https://registry.npm.taobao.org/tunnel-agent/download/tunnel-agent-0.6.0.tgz", 897 | "integrity": "sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0=", 898 | "optional": true, 899 | "requires": { 900 | "safe-buffer": "^5.0.1" 901 | } 902 | }, 903 | "tweetnacl": { 904 | "version": "0.14.5", 905 | "resolved": "https://registry.npm.taobao.org/tweetnacl/download/tweetnacl-0.14.5.tgz", 906 | "integrity": "sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q=", 907 | "optional": true 908 | }, 909 | "uri-js": { 910 | "version": "4.4.1", 911 | "resolved": "https://registry.npm.taobao.org/uri-js/download/uri-js-4.4.1.tgz?cache=0&sync_timestamp=1610237517218&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Furi-js%2Fdownload%2Furi-js-4.4.1.tgz", 912 | "integrity": "sha1-mxpSWVIlhZ5V9mnZKPiMbFfyp34=", 913 | "optional": true, 914 | "requires": { 915 | "punycode": "^2.1.0" 916 | } 917 | }, 918 | "util-deprecate": { 919 | "version": "1.0.2", 920 | "resolved": "https://registry.npm.taobao.org/util-deprecate/download/util-deprecate-1.0.2.tgz", 921 | "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=" 922 | }, 923 | "uuid": { 924 | "version": "3.4.0", 925 | "resolved": "https://registry.npm.taobao.org/uuid/download/uuid-3.4.0.tgz?cache=0&sync_timestamp=1607458532020&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fuuid%2Fdownload%2Fuuid-3.4.0.tgz", 926 | "integrity": "sha1-sj5DWK+oogL+ehAK8fX4g/AgB+4=", 927 | "optional": true 928 | }, 929 | "verror": { 930 | "version": "1.10.0", 931 | "resolved": "https://registry.npm.taobao.org/verror/download/verror-1.10.0.tgz", 932 | "integrity": "sha1-OhBcoXBTr1XW4nDB+CiGguGNpAA=", 933 | "optional": true, 934 | "requires": { 935 | "assert-plus": "^1.0.0", 936 | "core-util-is": "1.0.2", 937 | "extsprintf": "^1.2.0" 938 | } 939 | }, 940 | "which": { 941 | "version": "1.3.1", 942 | "resolved": "https://registry.npm.taobao.org/which/download/which-1.3.1.tgz", 943 | "integrity": "sha1-pFBD1U9YBTFtqNYvn1CRjT2nCwo=", 944 | "optional": true, 945 | "requires": { 946 | "isexe": "^2.0.0" 947 | } 948 | }, 949 | "wide-align": { 950 | "version": "1.1.3", 951 | "resolved": "https://registry.npm.taobao.org/wide-align/download/wide-align-1.1.3.tgz", 952 | "integrity": "sha1-rgdOa9wMFKQx6ATmJFScYzsABFc=", 953 | "requires": { 954 | "string-width": "^1.0.2 || 2" 955 | } 956 | }, 957 | "wrappy": { 958 | "version": "1.0.2", 959 | "resolved": "https://registry.npm.taobao.org/wrappy/download/wrappy-1.0.2.tgz", 960 | "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=" 961 | }, 962 | "ws": { 963 | "version": "7.4.3", 964 | "resolved": "https://registry.npm.taobao.org/ws/download/ws-7.4.3.tgz", 965 | "integrity": "sha1-H5ZD3jSlQ7jtsSS9y8RXrlWm5c0=" 966 | }, 967 | "yallist": { 968 | "version": "3.1.1", 969 | "resolved": "https://registry.npm.taobao.org/yallist/download/yallist-3.1.1.tgz", 970 | "integrity": "sha1-27fa+b/YusmrRev2ArjLrQ1dCP0=" 971 | } 972 | } 973 | } 974 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "bilibot", 3 | "version": "1.0.0", 4 | "description": "bilibili bot", 5 | "main": "main.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1" 8 | }, 9 | "repository": { 10 | "type": "git", 11 | "url": "git+https://github.com/wenwed/biliBot.git" 12 | }, 13 | "keywords": [ 14 | "bilibili", 15 | "bot" 16 | ], 17 | "author": "wenwd", 18 | "license": "ISC", 19 | "bugs": { 20 | "url": "https://github.com/wenwed/biliBot/issues" 21 | }, 22 | "homepage": "https://github.com/wenwed/biliBot#readme", 23 | "dependencies": { 24 | "axios": "^0.21.1", 25 | "node-mirai-sdk": "^0.2.3", 26 | "sqlite3": "^5.0.0" 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /scripts/middleWare.js: -------------------------------------------------------------------------------- 1 | const sql = require("./sql.js"); 2 | const axios = require("axios"); 3 | 4 | //生成群组订阅列表 5 | exports.createGroupSubList = async (values) => { 6 | let repairWord = ""; 7 | let index = 0; 8 | await sql.selectGroupAllSubInfoByType(values).then(rows => { 9 | rows.forEach(row => { 10 | index++; 11 | repairWord = repairWord + "\n" + index + " " + row.UID + " " + row.Name 12 | }); 13 | }) 14 | if (values[1] === 1) 15 | repairWord = `该群订阅了${index}位up主` + repairWord; 16 | else if (values[1] === 2) 17 | repairWord = `该群直播订阅了${index}位up主` + repairWord; 18 | else if (values[1] === 3) 19 | repairWord = `该群动态订阅了${index}位up主` + repairWord; 20 | return repairWord; 21 | } 22 | 23 | //为群组订阅一位UP主 24 | exports.subGroup = async (groupID, type, UID) => { 25 | // 判断用户输入的UID是不是数字 26 | if (isNaN(UID)) 27 | return "UID应为数字"; 28 | 29 | let repairWord = ""; 30 | let UPName = ""; 31 | let infoData = null; 32 | //判断该群组是否正在关注此UP主 33 | let values = [UID, groupID]; 34 | await sql.selectGroupOneSub(values).then(rows => { 35 | if (rows.length === 1) { 36 | UPName = rows[0].Name; 37 | if (rows[0].Sub_Type === type) { 38 | repairWord = `该群已订阅${UPName}`; 39 | throw new Error("STOP"); 40 | } 41 | else { 42 | values = [type, UID, groupID]; 43 | sql.updateGroupSubType(values); 44 | repairWord = `已更新${UPName}的订阅类型`; 45 | throw new Error("STOP"); 46 | } 47 | } else { 48 | values = [UID]; 49 | return sql.selectUP(values); 50 | } 51 | }).then(rows => { 52 | if (rows.length === 1) { 53 | UPName = rows[0].Name; 54 | values = [UID, groupID, type] 55 | sql.addGroupSub(values); 56 | repairWord = `关注${UPName}成功`; 57 | throw new Error("STOP"); 58 | } else { 59 | let infoURL = `https://api.bilibili.com/x/space/acc/info?mid=${UID}&jsonp=jsonp`; 60 | return axios.get(infoURL, { 61 | headers: { 62 | 'accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8', 63 | 'user-agent': 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/68.0.3440.106 Safari/537.36' 64 | } 65 | }) 66 | } 67 | }).then((res) => { 68 | infoData = res.data; 69 | if (infoData.code !== 0) { 70 | repairWord = "爬取信息出错,请检查UID是否正确"; 71 | throw new Error("STOP"); 72 | } else { 73 | // 向数据库中新增UP主信息 74 | infoData = infoData.data; 75 | let Name = infoData.name; 76 | let AID = null; 77 | if (infoData.live_room.roomStatus === 1) 78 | AID = infoData.live_room.roomid; 79 | let liveStatus = infoData.live_room.liveStatus; 80 | let liveStartTime = Math.round(new Date().getTime() / 1000); 81 | let lastNoticeTime = Math.round(new Date().getTime() / 1000); 82 | values = [UID, Name, AID, liveStatus, liveStartTime, lastNoticeTime] 83 | sql.addUP(values); 84 | 85 | // 向数据库中新增关注 86 | values = [UID, groupID, type]; 87 | sql.addGroupSub(values); 88 | repairWord = `订阅${Name}成功` 89 | } 90 | }).catch(() => { 91 | // 之前throw的"STOP" error会直接跳转到这里 92 | if (repairWord === "") 93 | repairWord = "未知错误"; 94 | }) 95 | return repairWord; 96 | } 97 | 98 | // 删除某个群组对某个UP主的订阅 99 | exports.deleteGroupSub = async (groupID, UID) => { 100 | // 判断用户输入的UID是不是数字 101 | if (isNaN(UID)) 102 | return "UID应为数字"; 103 | 104 | let repairWord = ""; 105 | let UPName = ""; 106 | let values = [UID, groupID]; 107 | let subNum = 0; 108 | 109 | // 先判断是否订阅 110 | await sql.selectGroupOneSub(values).then(rows => { 111 | if (rows.length === 0) { 112 | repairWord = `该群未订阅此UP主`; 113 | throw new Error("STOP"); 114 | } else { 115 | UPName = rows[0].Name; 116 | return sql.deleteGroupSub(values); 117 | } 118 | }).then(() => { 119 | // 查找个人关注的数量 120 | values = [UID]; 121 | return sql.selectPersonSubByUP(values); 122 | }).then(rows => { 123 | // 查找群组关注的数量 124 | subNum += rows.length; 125 | return sql.selectGroupSubByUP(values); 126 | }).then(rows => { 127 | subNum += rows.length; 128 | if (subNum !== 0) { 129 | repairWord = `取消订阅${UPName}成功`; 130 | throw new Error("STOP"); 131 | } else { 132 | return sql.deleteUP(values); 133 | } 134 | }).then(() => { 135 | repairWord = `取消订阅${UPName}成功`; 136 | }).catch(err => { 137 | // 之前throw的"STOP" error会直接跳转到这里 138 | if (repairWord === "") 139 | repairWord = "未知错误"; 140 | }) 141 | return repairWord; 142 | } 143 | 144 | //生成个人订阅列表 145 | exports.createPersonSubList = async (values) => { 146 | let repairWord = ""; 147 | let index = 0; 148 | await sql.selectPersonAllSubInfoByType(values).then(rows => { 149 | rows.forEach(row => { 150 | index++; 151 | repairWord = repairWord + "\n" + index + " " + row.UID + " " + row.Name 152 | }); 153 | }) 154 | if (values[1] === 1) 155 | repairWord = `你订阅了${index}位up主` + repairWord; 156 | else if (values[1] === 2) 157 | repairWord = `你直播订阅了${index}位up主` + repairWord; 158 | else if (values[1] === 3) 159 | repairWord = `你动态订阅了${index}位up主` + repairWord; 160 | return repairWord; 161 | } 162 | 163 | // 开启复读 164 | exports.startRepeat = async (values) => { 165 | let repairWord = ""; 166 | await sql.selectGroupBanRepeat(values).then((rows) => { 167 | if (rows.length === 0) { 168 | repairWord = `该群组已开启复读功能`; 169 | throw new Error("STOP"); 170 | } else { 171 | return sql.deleteGroupBanRepeat(values); 172 | } 173 | }).then(() => { 174 | repairWord = `开启复读功能`; 175 | }).catch(() => { 176 | if (repairWord === "") { 177 | repairWord = `未知错误`; 178 | } 179 | }) 180 | return repairWord; 181 | } 182 | 183 | // 关闭复读 184 | exports.stopRepeat = async (values) => { 185 | let repairWord = ""; 186 | await sql.selectGroupBanRepeat(values).then((rows) => { 187 | if (rows.length === 1) { 188 | repairWord = `该群组已关闭复读功能`; 189 | throw new Error("STOP"); 190 | } else { 191 | return sql.addGroupBanRepeat(values); 192 | } 193 | }).then(() => { 194 | repairWord = `关闭复读功能`; 195 | }).catch(() => { 196 | if (repairWord === "") { 197 | repairWord = `未知错误`; 198 | } 199 | }) 200 | return repairWord; 201 | } 202 | 203 | // 生成关键词列表 204 | exports.createGroupKeyWordsList = async (values) => { 205 | let repairWord = ""; 206 | let index = 0; 207 | await sql.selectKeyWords(values).then(rows => { 208 | rows.forEach(row => { 209 | index++; 210 | repairWord = `${repairWord}\n${index} ${row.Key_Word}`; 211 | }); 212 | }) 213 | if (values[1] === 1) { 214 | repairWord = "该群添加了如下精确关键词:" + repairWord; 215 | } else { 216 | repairWord = "该群添加了如下模糊关键词:" + repairWord; 217 | } 218 | return repairWord; 219 | } 220 | 221 | // 添加关键词 222 | exports.addGroupKeyWords = async (groupID, keyWord, type, replyWord) => { 223 | let values = [groupID, keyWord]; 224 | let repairWord = ""; 225 | await sql.selectOneKeyWords(values).then(rows => { 226 | if (rows.length !== 0) { 227 | repairWord = "该群已添加此关键词"; 228 | throw new Error("STOP"); 229 | } else { 230 | values = [groupID, keyWord, replyWord, type]; 231 | return sql.addKeyWords(values); 232 | } 233 | }).then(() => { 234 | repairWord = "添加成功"; 235 | }).catch(err => { 236 | if (repairWord === "") { 237 | repairWord = "未知错误"; 238 | } 239 | }) 240 | return repairWord; 241 | } 242 | 243 | // 删除关键词 244 | exports.deleteGroupKeyWords = async (values) => { 245 | let repairword = ""; 246 | await sql.selectOneKeyWords(values).then(rows => { 247 | if (rows.length === 0) { 248 | repairword = "该群未添加此关键词"; 249 | throw new Error("STOP"); 250 | } else { 251 | return sql.deleteKeyWords(values); 252 | } 253 | }).then(() => { 254 | repairword = "删除关键词成功"; 255 | }).catch(err => { 256 | if (repairword === "") { 257 | repairword = "未知错误"; 258 | } 259 | }) 260 | return repairword; 261 | } 262 | 263 | //为个人订阅一位UP主 264 | exports.subPerson = async (personID, type, UID) => { 265 | // 判断用户输入的UID是不是数字 266 | if (isNaN(UID)) 267 | return "UID应为数字"; 268 | 269 | let repairWord = ""; 270 | let UPName = ""; 271 | let infoData = null; 272 | //判断该群组是否正在关注此UP主 273 | let values = [UID, personID]; 274 | await sql.selectPersonOneSub(values).then(rows => { 275 | if (rows.length === 1) { 276 | UPName = rows[0].Name; 277 | if (rows[0].Sub_Type === type) { 278 | repairWord = `你已订阅${UPName}`; 279 | throw new Error("STOP"); 280 | } 281 | else { 282 | values = [type, UID, personID]; 283 | sql.updatePersonSubType(values); 284 | repairWord = `已更新${UPName}的关注类型`; 285 | throw new Error("STOP"); 286 | } 287 | } else { 288 | values = [UID]; 289 | return sql.selectUP(values); 290 | } 291 | }).then(rows => { 292 | if (rows.length === 1) { 293 | UPName = rows[0].Name; 294 | values = [UID, personID, type] 295 | sql.addPersonSub(values); 296 | repairWord = `订阅${UPName}成功`; 297 | throw new Error("STOP"); 298 | } else { 299 | let infoURL = `https://api.bilibili.com/x/space/acc/info?mid=${UID}&jsonp=jsonp`; 300 | return axios.get(infoURL, { 301 | headers: { 302 | 'accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8', 303 | 'user-agent': 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/68.0.3440.106 Safari/537.36' 304 | } 305 | }) 306 | } 307 | }).then((res) => { 308 | infoData = res.data; 309 | if (infoData.code !== 0) { 310 | repairWord = "爬取信息出错,请检查UID是否正确"; 311 | throw new Error("STOP"); 312 | } else { 313 | // 向数据库中新增UP主信息 314 | infoData = infoData.data; 315 | let Name = infoData.name; 316 | let AID = null; 317 | if (infoData.live_room.roomStatus === 1) 318 | AID = infoData.live_room.roomid; 319 | let liveStatus = infoData.live_room.liveStatus; 320 | let liveStartTime = Math.round(new Date().getTime() / 1000); 321 | let lastNoticeTime = Math.round(new Date().getTime() / 1000); 322 | values = [UID, Name, AID, liveStatus, liveStartTime, lastNoticeTime] 323 | sql.addUP(values); 324 | 325 | // 向数据库中新增关注 326 | values = [UID, personID, type]; 327 | sql.addPersonSub(values); 328 | repairWord = `订阅${Name}成功` 329 | } 330 | }).catch((err) => { 331 | // 之前throw的"STOP" error会直接跳转到这里 332 | if (repairWord === "") 333 | repairWord = "未知错误"; 334 | }) 335 | return repairWord; 336 | } 337 | 338 | // 删除某个个人对某个UP主的订阅 339 | exports.deletePersonSub = async (personID, UID) => { 340 | // 判断用户输入的UID是不是数字 341 | if (isNaN(UID)) 342 | return "UID应为数字"; 343 | 344 | let repairWord = ""; 345 | let UPName = ""; 346 | let values = [UID, personID]; 347 | let subNum = 0; 348 | 349 | // 先判断是否订阅 350 | await sql.selectPersonOneSub(values).then(rows => { 351 | if (rows.length === 0) { 352 | repairWord = `你未订阅此UP主`; 353 | throw new Error("STOP"); 354 | } else { 355 | UPName = rows[0].Name; 356 | return sql.deletePersonSub(values); 357 | } 358 | }).then(() => { 359 | // 查找个人关注的数量 360 | values = [UID]; 361 | return sql.selectPersonSubByUP(values); 362 | }).then(rows => { 363 | // 查找群组关注的数量 364 | subNum += rows.length; 365 | return sql.selectGroupSubByUP(values); 366 | }).then(rows => { 367 | subNum += rows.length; 368 | if (subNum !== 0) { 369 | repairWord = `取消订阅${UPName}成功`; 370 | throw new Error("STOP"); 371 | } else { 372 | return sql.deleteUP(values); 373 | } 374 | }).then(() => { 375 | repairWord = `取消订阅${UPName}成功`; 376 | }).catch(err => { 377 | // 之前throw的"STOP" error会直接跳转到这里 378 | if (repairWord === "") 379 | repairWord = "未知错误"; 380 | }) 381 | return repairWord; 382 | } 383 | 384 | // 勋章查询(API已失效) 385 | exports.searchBiliMedal = async (UID) => { 386 | // 判断UID是否为数字 387 | if (isNaN(UID)) { 388 | return "UID应为数字"; 389 | } 390 | 391 | let infoURL = `http://101.201.64.44/breeze/user.t?uid=${UID}`; 392 | await axios.get(infoURL, { 393 | headers: { 394 | 'accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8', 395 | 'user-agent': 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/68.0.3440.106 Safari/537.36' 396 | } 397 | }).then((res) => { 398 | console.log(res); 399 | }) 400 | } 401 | 402 | // 添加todo 403 | exports.createTodo = async (todoText, groupID) => { 404 | if (!todoText) { 405 | return "请输入todo内容"; 406 | } 407 | let repairWord = ""; 408 | let values = [todoText, groupID, new Date().getTime()]; 409 | await sql.addTodo(values).then((res) => { 410 | repairWord = `添加todo:${todoText} 成功`; 411 | }) 412 | return repairWord; 413 | } 414 | 415 | // 获取todo列表 416 | exports.selectGroupTodo = async (groupID) => { 417 | let values = [groupID]; 418 | let repairWord = ""; 419 | await sql.selectTodo(values).then((res) => { 420 | repairWord = `当前有${res.length}个todo事项`; 421 | for (let i = 0; i < res.length; i++) { 422 | repairWord = `${repairWord}\n${res[i].todoID} ${res[i].todo_text}`; 423 | } 424 | }) 425 | return repairWord; 426 | } 427 | 428 | // 完成todo 429 | exports.completeTodo = async (groupID, ID) => { 430 | // 判断用户输入的UID是不是数字 431 | if (isNaN(ID)) 432 | return "todo的id应为数字"; 433 | 434 | let values = [ID]; 435 | let repairWord = "未知错误"; 436 | await sql.selectOneTodo(values).then((res) => { 437 | if (res.length === 0) { 438 | repairWord = `没有此项todo或已完成`; 439 | throw new Error("STOP"); 440 | } else if (res[0].Group_Number != groupID) { 441 | repairWord = `此项todo不属于该群组`; 442 | throw new Error("STOP"); 443 | } else { 444 | return sql.deleteTodo(values) 445 | } 446 | }).then((result) => { 447 | repairWord = `已完成todo事项:${res[0].todo_text}`; 448 | }).catch((err) => { 449 | }) 450 | return repairWord; 451 | } 452 | 453 | // 完成某个群组所有的todo 454 | exports.completeAllTodo = async (groupID) => { 455 | let values = [groupID]; 456 | let repairWord = ""; 457 | await sql.deleteAllTodo(values).then((res) => { 458 | repairWord = `已完成该群组所有的todo事项`; 459 | }) 460 | return repairWord; 461 | } -------------------------------------------------------------------------------- /scripts/repair.js: -------------------------------------------------------------------------------- 1 | const sql = require("./sql.js"); 2 | const middleWare = require("./middleWare.js"); 3 | const spider = require("./spider.js"); 4 | const Mirai = require('node-mirai-sdk'); 5 | const { Plain, At } = Mirai.MessageComponent; 6 | 7 | // 开始运行bilibili爬虫 8 | exports.startBiliSpider = async (bot) => { 9 | function sleep(time) { 10 | return new Promise((resolve) => setTimeout(resolve, time)); 11 | } 12 | //更新UP主的动态时间 13 | spider.resetDynamicTime(); 14 | // 五分钟运行一次爬虫 15 | while (true) { 16 | await sleep(300000).then(() => { 17 | spider.startLivingSpider(bot); 18 | spider.startDynamicSpider(bot); 19 | }) 20 | } 21 | } 22 | 23 | // 回复群组消息 24 | exports.repairGroup = async (bot, message, sender, messageChain, reply, quoteReply, recall) => { 25 | // 从 messageChain 中提取文字内容 26 | let msg = ''; 27 | messageChain.forEach(chain => { 28 | if (chain.type === 'Plain') 29 | msg += Plain.value(chain); 30 | }); 31 | 32 | // 判断是否为bot指令 33 | if (msg.indexOf("!") === 0) { 34 | manageGroup(message, sender, messageChain, reply, quoteReply, recall, msg); 35 | return; 36 | } 37 | 38 | manageTodo(sender, reply, msg); 39 | 40 | let target = 0; 41 | messageChain.forEach(chain => { 42 | if (chain.type === 'At') { 43 | target = chain.target; 44 | } 45 | }); 46 | 47 | // 群组聊天@了bot 48 | if (target === bot.qq) { 49 | if (msg === " " || msg === "") { 50 | sql.selectAllAtWords().then((rows) => { 51 | let len = rows.length; 52 | let ran = Math.floor(Math.random() * len); 53 | reply(rows[ran]["At_Word"]); 54 | return; 55 | }) 56 | } else if (msg === "老婆" || msg === " 老婆") { 57 | bot.sendImageMessage("./images/feizhai.jpg", message); 58 | return; 59 | } else { 60 | bot.sendImageMessage("./images/ybb.jpg", message); 61 | return; 62 | } 63 | } 64 | 65 | // else if (msg.includes('引用我')) 66 | // quoteReply([At(sender.id), Plain('好的')]); // 或者: bot.quoteReply(messageChain, message) 67 | 68 | // 判断精确关键词 69 | let values = [sender.group.id, 1] 70 | sql.selectKeyWords(values).then(rows => { 71 | rows.forEach(element => { 72 | if (element.Key_Word === msg) { 73 | reply(element.Repair_Word); 74 | flag = true; 75 | return; 76 | } 77 | }); 78 | }) 79 | 80 | // 判断模糊关键词 81 | values = [sender.group.id, 2] 82 | sql.selectKeyWords(values).then(rows => { 83 | for (let i = 0; i < rows.length; i++) { 84 | if (msg.includes(rows[i].Key_Word)) { 85 | reply(rows[i].Repair_Word); 86 | return; 87 | } 88 | } 89 | }) 90 | 91 | // 复读 92 | values = [sender.group.id] 93 | sql.selectGroupBanRepeat(values).then((rows) => { 94 | if (rows.length === 0) { 95 | // 复读模块 96 | let ran = Math.floor(Math.random() * 80); 97 | if (ran === 1) { 98 | let repeatWord = msg.replace(/你/g, "他").replace(/我/g, "你").replace(/bot/g, "我"); 99 | reply(repeatWord); 100 | return; 101 | } 102 | } 103 | }) 104 | } 105 | 106 | // 回复个人消息 107 | exports.repairPerson = (bot, message, sender, messageChain, reply, quoteReply, recall) => { 108 | let msg = ''; 109 | messageChain.forEach(chain => { 110 | if (chain.type === 'Plain') 111 | msg += Plain.value(chain); // 从 messageChain 中提取文字内容 112 | }); 113 | 114 | // 判断是否为bot指令 115 | if (msg.indexOf("!") === 0) { 116 | managePerson(message, sender, messageChain, reply, quoteReply, recall, msg); 117 | return; 118 | } 119 | } 120 | 121 | //处理bot的群组指令 122 | function manageGroup(message, sender, messageChain, reply, quoteReply, recall, msg) { 123 | // 使用空格切割字符串 124 | let instruct = msg.split(" ", 2); 125 | let length = 0; 126 | let repairWord = ""; 127 | 128 | // 消息来源群组 129 | let groupID = sender.group.id; 130 | // 发送者的权限信息 OWNER,MEMBER,ADMINISTRATOR 131 | let permission = sender.permission; 132 | 133 | let values = []; 134 | let type = 0; 135 | let UID = ""; 136 | 137 | switch (instruct[0]) { 138 | case "!help": 139 | repairWord = `!订阅 uid\n!订阅列表\n!直播订阅 uid\n!直播订阅列表 140 | !动态订阅 uid\n!动态订阅列表\n!取消订阅 uid 141 | todo 内容\ntodolist\ndeltodo id\ndelalltodo 142 | 需要管理员权限:\n!添加精确关键词 关键词 回复词\n!添加模糊关键词 关键词 回复词\n!删除关键词 关键词 143 | !精确关键词列表\n!模糊关键词列表\n!开启复读\n!关闭复读 144 | 当前版本:3.0.0\ngithub地址:https://github.com/wenwed/biliBot`; 145 | reply(repairWord); 146 | return; 147 | 148 | case "!订阅列表": 149 | values = [groupID, 1]; 150 | middleWare.createGroupSubList(values).then(repairWord => { 151 | reply(repairWord); 152 | }); 153 | return; 154 | 155 | case "!直播订阅列表": 156 | values = [groupID, 2]; 157 | middleWare.createGroupSubList(values).then(repairWord => { 158 | reply(repairWord); 159 | }); 160 | return; 161 | 162 | case "!动态订阅列表": 163 | values = [groupID, 3]; 164 | middleWare.createGroupSubList(values).then(repairWord => { 165 | reply(repairWord); 166 | }); 167 | return; 168 | 169 | case "!订阅": 170 | type = 1; 171 | UID = instruct[1]; 172 | middleWare.subGroup(groupID, type, UID).then(repairWord => { 173 | reply(repairWord); 174 | }) 175 | return; 176 | 177 | case "!直播订阅": 178 | type = 2; 179 | UID = instruct[1]; 180 | middleWare.subGroup(groupID, type, UID).then(repairWord => { 181 | reply(repairWord); 182 | }) 183 | return; 184 | 185 | case "!动态订阅": 186 | type = 3; 187 | UID = instruct[1]; 188 | middleWare.subGroup(groupID, type, UID).then(repairWord => { 189 | reply(repairWord); 190 | }) 191 | return; 192 | 193 | case "!取消订阅": 194 | UID = instruct[1]; 195 | middleWare.deleteGroupSub(groupID, UID).then(repairWord => { 196 | reply(repairWord); 197 | }) 198 | return; 199 | 200 | case "!精确关键词列表": 201 | if (permission !== "ADMINISTRATOR" && permission !== "OWNER") { 202 | reply("权限等级不足"); 203 | return; 204 | } 205 | values = [groupID, 1]; 206 | middleWare.createGroupKeyWordsList(values).then(repairWord => { 207 | reply(repairWord); 208 | }) 209 | return; 210 | 211 | case "!模糊关键词列表": 212 | if (permission !== "ADMINISTRATOR" && permission !== "OWNER") { 213 | reply("权限等级不足"); 214 | return; 215 | } 216 | values = [groupID, 2]; 217 | middleWare.createGroupKeyWordsList(values).then(repairWord => { 218 | reply(repairWord); 219 | }) 220 | return; 221 | 222 | case "!添加精确关键词": 223 | if (permission !== "ADMINISTRATOR" && permission !== "OWNER") { 224 | reply("权限等级不足"); 225 | return; 226 | } else if (instruct.lenth === 1) { 227 | reply("请输入关键词"); 228 | return; 229 | } else { 230 | // 判断前两个字符串加空格的长度,方便截取第三段 231 | length = instruct[0].length + instruct[1].length + 2; 232 | if (msg.substr(length) === "") { 233 | reply("请输入回复词"); 234 | return; 235 | } 236 | } 237 | middleWare.addGroupKeyWords(groupID, instruct[1], 1, msg.substr(length)).then(repairWord => { 238 | reply(repairWord); 239 | }) 240 | return; 241 | 242 | case "!添加模糊关键词": 243 | if (permission !== "ADMINISTRATOR" && permission !== "OWNER") { 244 | reply("权限等级不足"); 245 | return; 246 | } else if (instruct.lenth === 1) { 247 | reply("请输入关键词"); 248 | return; 249 | } else { 250 | // 判断前两个字符串加空格的长度,方便截取第三段 251 | length = instruct[0].length + instruct[1].length + 2; 252 | if (msg.substr(length) === "") { 253 | reply("请输入回复词"); 254 | return; 255 | } 256 | } 257 | middleWare.addGroupKeyWords(groupID, instruct[1], 2, msg.substr(length)).then(repairWord => { 258 | reply(repairWord); 259 | }) 260 | return; 261 | 262 | case "!删除关键词": 263 | if (permission !== "ADMINISTRATOR" && permission !== "OWNER") { 264 | reply("权限等级不足"); 265 | return; 266 | } else if (instruct.lenth === 1) { 267 | reply("请输入关键词"); 268 | return; 269 | } 270 | values = [groupID, instruct[1]]; 271 | middleWare.deleteGroupKeyWords(values).then(repairWord => { 272 | reply(repairWord); 273 | }) 274 | return; 275 | 276 | case "!开启复读": 277 | if (permission !== "ADMINISTRATOR" && permission !== "OWNER") { 278 | reply("权限等级不足"); 279 | return; 280 | } 281 | values = [groupID]; 282 | middleWare.startRepeat(values).then(repairWord => { 283 | reply(repairWord); 284 | }) 285 | return; 286 | 287 | case "!关闭复读": 288 | if (permission !== "ADMINISTRATOR" && permission !== "OWNER") { 289 | reply("权限等级不足"); 290 | return; 291 | } 292 | values = [groupID]; 293 | middleWare.stopRepeat(values).then(repairWord => { 294 | reply(repairWord); 295 | }) 296 | return; 297 | } 298 | } 299 | 300 | //处理bot的个人指令 301 | function managePerson(message, sender, messageChain, reply, quoteReply, recall, msg) { 302 | // 使用空格切割字符串 303 | let instruct = msg.split(" ", 2); 304 | 305 | let repairWord = ""; 306 | let personID = sender.id; 307 | 308 | let values = []; 309 | let type = 0; 310 | let UID = ""; 311 | 312 | switch (instruct[0]) { 313 | case "!help": 314 | repairWord = `!订阅 uid\n!订阅列表\n!直播订阅 uid\n!直播订阅列表\n 315 | !动态订阅 uid\n!动态订阅列表\n!取消订阅 uid\n!勋章查询 uid 316 | 当前版本:3.0.0\ngithub地址:https://github.com/wenwed/biliBot`; 317 | reply(repairWord); 318 | return; 319 | 320 | case "!订阅列表": 321 | values = [personID, 1]; 322 | middleWare.createPersonSubList(values).then(repairWord => { 323 | reply(repairWord); 324 | }) 325 | return; 326 | 327 | case "!直播订阅列表": 328 | values = [personID, 2]; 329 | middleWare.createPersonSubList(values).then(repairWord => { 330 | reply(repairWord); 331 | }) 332 | return; 333 | 334 | case "!动态订阅列表": 335 | values = [personID, 3]; 336 | middleWare.createPersonSubList(values).then(repairWord => { 337 | reply(repairWord); 338 | }) 339 | return; 340 | 341 | case "!订阅": 342 | type = 1; 343 | UID = instruct[1]; 344 | middleWare.subPerson(personID, type, UID).then(repairWord => { 345 | reply(repairWord); 346 | }) 347 | return; 348 | 349 | case "!直播订阅": 350 | type = 2; 351 | UID = instruct[1]; 352 | middleWare.subPerson(personID, type, UID).then(repairWord => { 353 | reply(repairWord); 354 | }) 355 | return; 356 | 357 | case "!动态订阅": 358 | type = 3; 359 | UID = instruct[1]; 360 | middleWare.subPerson(personID, type, UID).then(repairWord => { 361 | reply(repairWord); 362 | }) 363 | return; 364 | 365 | case "!取消订阅": 366 | UID = instruct[1]; 367 | middleWare.deletePersonSub(personID, UID).then(repairWord => { 368 | reply(repairWord); 369 | }) 370 | return; 371 | 372 | case "!勋章查询": 373 | reply("API已失效"); 374 | // UID = instruct[1]; 375 | // middleWare.searchBiliMedal(UID).then(repairWord => { 376 | // reply(repairWord); 377 | // }) 378 | return; 379 | } 380 | } 381 | 382 | function manageTodo(sender, reply, msg) { 383 | // 使用空格切割字符串 384 | let instruct = msg.split(" ", 2); 385 | let order = instruct[0].toLowerCase(); 386 | // 消息来源群组 387 | let groupID = sender.group.id; 388 | let permission = sender.permission; 389 | 390 | switch (order) { 391 | case "todo": { 392 | middleWare.createTodo(msg.substring(instruct[0].length + 1), groupID).then((repairWord) => { 393 | reply(repairWord); 394 | }) 395 | return; 396 | } 397 | case "deltodo": { 398 | middleWare.completeTodo(groupID, instruct[1]).then((repairWord) => { 399 | reply(repairWord); 400 | }) 401 | return; 402 | } 403 | case "todolist": { 404 | middleWare.selectGroupTodo(groupID).then((repairWord) => { 405 | reply(repairWord); 406 | }) 407 | return; 408 | } 409 | case "delalltodo": { 410 | if (permission !== "ADMINISTRATOR" && permission !== "OWNER") { 411 | reply("权限等级不足"); 412 | return; 413 | } 414 | middleWare.completeAllTodo(groupID).then((repairWord) => { 415 | reply(repairWord); 416 | }) 417 | return; 418 | } 419 | } 420 | } -------------------------------------------------------------------------------- /scripts/spider.js: -------------------------------------------------------------------------------- 1 | const sql = require("./sql.js"); 2 | const axios = require("axios"); 3 | 4 | function sleep(time) { 5 | return new Promise((resolve) => setTimeout(resolve, time)); 6 | } 7 | 8 | // 直播间爬虫模块 9 | //启动前重置动态爬取时间防止刷屏 10 | exports.resetDynamicTime = () => { 11 | let values = [Math.round(new Date().getTime() / 1000)]; 12 | sql.updateAllUPNoticeTime(values); 13 | } 14 | 15 | // 开始运行直播爬虫 16 | exports.startLivingSpider = async (bot) => { 17 | let rooms = {}; 18 | 19 | //查询群组的全部订阅房间 20 | let values = [1]; 21 | await sql.selectGroupRoomTospider(values).then(rows => { 22 | rows.forEach(row => { 23 | rooms[row.AID] = row.Live_Start_Time; 24 | }); 25 | }) 26 | //查询群组的直播订阅房间 27 | values = [2]; 28 | await sql.selectGroupRoomTospider(values).then(rows => { 29 | rows.forEach(row => { 30 | rooms[row.AID] = row.Live_Start_Time; 31 | }); 32 | }) 33 | //查询个人的全部订阅房间 34 | values = [1]; 35 | await sql.selectPersonRoomTospider(values).then(rows => { 36 | rows.forEach(row => { 37 | rooms[row.AID] = row.Live_Start_Time; 38 | }); 39 | }) 40 | //查询个人的直播订阅房间 41 | values = [2]; 42 | await sql.selectPersonRoomTospider(values).then(rows => { 43 | rows.forEach(row => { 44 | rooms[row.AID] = row.Live_Start_Time; 45 | }); 46 | }) 47 | 48 | //开始爬取房间 49 | searchLivingRooms(bot, rooms); 50 | } 51 | 52 | async function searchLivingRooms(bot, rooms) { 53 | for (let AID in rooms) { 54 | // 每隔三秒爬取一次防止被限制 55 | await sleep(3000).then(() => { 56 | searchLivingRoom(bot, AID, rooms[AID]); 57 | }) 58 | }; 59 | } 60 | 61 | // 爬取直播间状态 62 | async function searchLivingRoom(bot, AID, lastStartTime) { 63 | let data = null; 64 | url = `https://api.live.bilibili.com/xlive/web-room/v1/index/getInfoByRoom?room_id=${AID}`; 65 | await axios.get(url, { 66 | headers: { 67 | 'accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8', 68 | 'user-agent': 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/68.0.3440.106 Safari/537.36' 69 | } 70 | }).then(res => { 71 | data = res.data; 72 | }) 73 | // 房间号错误直接返回 74 | if (data.code === -400) return; 75 | 76 | data = data.data; 77 | let live_status = data.room_info.live_status; 78 | let start_time = data.room_info.live_start_time; 79 | //正在直播且之前未查询过 80 | if (live_status === 1 && start_time !== lastStartTime) { 81 | let values = [start_time, AID]; 82 | // 更新直播开始时间 83 | sql.updateUPLiveTime(values); 84 | // 根据不同的订阅类型发送消息 85 | values = [AID, 1]; 86 | sql.selectGroupByAID(values).then(rows => { 87 | rows.forEach(row => { 88 | handleGroupLiving(bot, data, row.Group_Number); 89 | }); 90 | }) 91 | values = [AID, 2]; 92 | sql.selectGroupByAID(values).then(rows => { 93 | rows.forEach(row => { 94 | handleGroupLiving(bot, data, row.Group_Number); 95 | }); 96 | }) 97 | values = [AID, 1]; 98 | sql.selectPersonByAID(values).then(rows => { 99 | rows.forEach(row => { 100 | handlePersonLiving(bot, data, row.Person_Number); 101 | }); 102 | }) 103 | values = [AID, 2]; 104 | sql.selectPersonByAID(values).then(rows => { 105 | rows.forEach(row => { 106 | handlePersonLiving(bot, data, row.Person_Number); 107 | }); 108 | }) 109 | } 110 | } 111 | 112 | // 发送群组消息 113 | function handleGroupLiving(bot, data, groupID) { 114 | try { 115 | let room = data.room_info; 116 | let UP = data.anchor_info.base_info.uname; 117 | let msg = `你关注的${UP}开播啦!${room.title},地址:https://live.bilibili.com/${room.room_id}`; 118 | bot.sendGroupMessage(msg, groupID); 119 | } catch (error) { 120 | } 121 | } 122 | 123 | //发送个人消息 124 | function handlePersonLiving(bot, data, PersonID) { 125 | try { 126 | let room = data.room_info; 127 | let UP = data.anchor_info.base_info.uname; 128 | let msg = `你关注的${UP}开播啦!${room.title},地址:https://live.bilibili.com/${room.room_id}`; 129 | bot.sendFriendMessage(msg, PersonID); 130 | } catch (error) { 131 | } 132 | } 133 | 134 | // 动态爬虫模块 135 | // 开始运行动态爬虫 136 | exports.startDynamicSpider = async (bot) => { 137 | let UPS = {}; 138 | 139 | //查询群组的全部订阅 140 | let values = [1]; 141 | await sql.selectGroupDynamicTospider(values).then(rows => { 142 | rows.forEach(row => { 143 | UPS[row.UID] = row.Last_Notice_Time; 144 | }); 145 | }) 146 | //查询群组的订阅动态 147 | values = [3]; 148 | await sql.selectGroupDynamicTospider(values).then(rows => { 149 | rows.forEach(row => { 150 | UPS[row.UID] = row.Last_Notice_Time; 151 | }); 152 | }) 153 | //查询个人的全部订阅 154 | values = [1]; 155 | await sql.selectPersonDynamicTospider(values).then(rows => { 156 | rows.forEach(row => { 157 | UPS[row.UID] = row.Last_Notice_Time; 158 | }); 159 | }) 160 | //查询个人的动态订阅 161 | values = [3]; 162 | await sql.selectPersonDynamicTospider(values).then(rows => { 163 | rows.forEach(row => { 164 | UPS[row.UID] = row.Last_Notice_Time; 165 | }); 166 | }) 167 | 168 | //开始爬取动态 169 | searchNewDynamics(bot, UPS); 170 | } 171 | 172 | async function searchNewDynamics(bot, UPS) { 173 | for (let UID in UPS) { 174 | await sleep(3000).then(() => { 175 | searchNewDynamic(bot, UID, UPS[UID]); 176 | }) 177 | }; 178 | } 179 | 180 | // 爬取动态 181 | async function searchNewDynamic(bot, UID, lastNociceTime) { 182 | let data = null; 183 | url = `https://api.vc.bilibili.com/dynamic_svr/v1/dynamic_svr/space_history?host_uid=${UID}`; 184 | await axios.get(url, { 185 | headers: { 186 | 'accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8', 187 | 'user-agent': 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/68.0.3440.106 Safari/537.36' 188 | } 189 | }).then(res => { 190 | data = res.data.data; 191 | }) 192 | 193 | // 如果有cards属性的话 194 | if (data.cards) { 195 | for (var i = 0; i < data.cards.length; i++) { 196 | let desc = data.cards[i].desc; 197 | let card = data.cards[i].card; 198 | let dynamicTime = desc.timestamp; 199 | if (dynamicTime > lastNociceTime) { 200 | let msg = processDynamic(desc, card); 201 | handleDynamicMessage(bot, msg, UID); 202 | 203 | // 更新动态查看时间 204 | let values = [Math.round(new Date().getTime() / 1000), UID]; 205 | sql.updateUPNoticeTime(values); 206 | } else { 207 | break; 208 | } 209 | } 210 | } 211 | } 212 | 213 | // 根据动态的代码处理动态 214 | function processDynamic(desc, card) { 215 | // exports.processDynamic = (desc, card) => { 216 | card = JSON.parse(card); 217 | let dyamic_id = desc.dynamic_id_str; 218 | let type = desc.type; 219 | let uname = desc.user_profile.info.uname; 220 | let content = null; 221 | let res = ""; 222 | 223 | // 转发动态 224 | if (type == 1) { 225 | let pre_dy_id = desc.pre_dy_id_str; 226 | let orig_type = desc.orig_type; 227 | content = card.item.content; 228 | // 转发带有图片的原创动态 229 | if (orig_type == 2) { 230 | res = `${uname}转发了动态:\nURL:https://t.bilibili.com/${dyamic_id}\n${content}`; 231 | let origin = JSON.parse(card.origin); 232 | let description = origin.item.description; 233 | let origin_name = origin.user.name; 234 | res = `${res}\n${origin_name}:\n${description}\nURL:https://t.bilibili.com/${pre_dy_id}`; 235 | } 236 | // 转发原创纯文字动态 237 | else if (orig_type == 4) { 238 | res = `${uname}转发了动态:\nURL:https://t.bilibili.com/${dyamic_id}\n${content}`; 239 | let origin = JSON.parse(card.origin); 240 | let origin_name = origin.user.uname; 241 | let origin_content = origin.item.content; 242 | res = `${res}\n${origin_name}:\n${origin_content}\nURL:https://t.bilibili.com/${pre_dy_id}`; 243 | } 244 | // 转发视频 245 | else if (orig_type == 8) { 246 | res = `${uname}转发了视频:\nURL:https://t.bilibili.com/${dyamic_id}\n${content}`; 247 | let origin = JSON.parse(card.origin); 248 | let aid = origin.aid; 249 | let title = origin.title; 250 | res = `${res}\n${title}\nURL:https://www.bilibili.com/video/av${aid}`; 251 | } 252 | // 转发直播间 253 | else if (orig_type == 4200) { 254 | res = `${uname}转发了直播间:\nURL:https://t.bilibili.com/${dyamic_id}\n${content}`; 255 | let origin = JSON.parse(card.origin); 256 | let rid = origin.roomid; 257 | let title = origin.title; 258 | res = `${res}\n${title} URL:https://live.bilibili.com/${rid}`; 259 | } 260 | // 转发专栏 261 | else if (orig_type == 64) { 262 | res = `${uname} 转发了专栏:\nURL:https://t.bilibili.com/${dyamic_id}\n${content}`; 263 | let origin = JSON.parse(card.origin); 264 | let rid = origin.id; 265 | let title = origin.title; 266 | res = `${res}\n${title}\nURL:https://www.bilibili.com/read/cv${rid}`; 267 | } 268 | // 转发收藏夹 269 | else if (orig_type == 4300) { 270 | res = `${uname}转发了收藏夹:\nURL:https://t.bilibili.com/${dyamic_id}\n${content}`; 271 | } 272 | // 转发发表使用挂件的动态 273 | else if (orig_type == 2048) { 274 | res = `${uname}转发了动态:\nURL:https://t.bilibili.com/${dyamic_id}\n${content}`; 275 | let origin = JSON.parse(card.origin); 276 | let origin_content = origin.vest.content; 277 | res = `${res}\n${origin_content}\nURL:https://t.bilibili.com/${pre_dy_id}`; 278 | } 279 | // 转发原动态已失效 280 | else if (orig_type == 1024) { 281 | res = `${uname}转发了动态:\nURL:https://t.bilibili.com/${dyamic_id}\n${content}`; 282 | let tips = card.item.tips; 283 | res = `${res}\nURL:https://t.bilibili.com/${dyamic_id}\n${tips}`; 284 | } 285 | } 286 | // 原创图片动态 287 | else if (type == 2) { 288 | description = card.item.description; 289 | res = `${uname}发表了新动态:\n${description}\nURL:https://t.bilibili.com/${dyamic_id}`; 290 | } 291 | // 原创文字动态 292 | else if (type == 4) { 293 | console.log(typeof card.item); 294 | content = card.item.content; 295 | res = `${uname}发表了新动态:\n${content}\nURL:https://t.bilibili.com/${dyamic_id}`; 296 | } 297 | // 发表视频 298 | else if (type == 8) { 299 | BVID = desc.bvid; 300 | title = card.title; 301 | res = `${uname}发表了新视频:\n${title}\nURL:https://www.bilibili.com/video/${BVID}`; 302 | } 303 | // 发表使用挂件的动态 304 | else if (type == 2048) { 305 | content = card.vest.content; 306 | res = `${uname}发表了新动态:\n${content}\nURL:https://t.bilibili.com/${dyamic_id}`; 307 | } 308 | // 发表专栏 309 | else if (type == 64) { 310 | title = card.title; 311 | rid = card.id; 312 | res = `${uname}发表了新的专栏:\n${title}\nURL:https://www.bilibili.com/read/cv${rid}`; 313 | } 314 | return res; 315 | } 316 | 317 | // 发送新动态消息 318 | function handleDynamicMessage(bot, msg, UID) { 319 | let values = [UID, 1]; 320 | sql.selectGroupByUID(values).then(rows => { 321 | rows.forEach(row => { 322 | bot.sendGroupMessage(msg, row.Group_Number); 323 | }); 324 | }) 325 | values = [UID, 3]; 326 | sql.selectGroupByUID(values).then(rows => { 327 | rows.forEach(row => { 328 | bot.sendGroupMessage(msg, row.Group_Number); 329 | }); 330 | }) 331 | values = [UID, 1]; 332 | sql.selectPersonByUID(values).then(rows => { 333 | rows.forEach(row => { 334 | bot.sendFriendMessage(msg, row.Person_Number); 335 | }); 336 | }) 337 | values = [UID, 3]; 338 | sql.selectPersonByUID(values).then(rows => { 339 | rows.forEach(row => { 340 | bot.sendFriendMessage(msg, row.Person_Number); 341 | }); 342 | }) 343 | } -------------------------------------------------------------------------------- /scripts/sql.js: -------------------------------------------------------------------------------- 1 | const sqlite3 = require("sqlite3").verbose(); 2 | console.log("Opened database successfully") 3 | 4 | // 创建一个执行sql语句的promise函数 5 | let query = (sql, values) => { 6 | return new Promise((resolve, reject) => { 7 | let db = new sqlite3.Database('./database/robot.db'); 8 | var stmt = db.prepare(sql); 9 | stmt.all(values, (err, rows) => { 10 | if (err) 11 | reject(err); 12 | else { 13 | resolve(rows); 14 | } 15 | }); 16 | stmt.finalize(); 17 | db.close(); 18 | }) 19 | } 20 | 21 | // 创建up主表 22 | let UP = `CREATE TABLE IF NOT EXISTS UP 23 | (UID TEXT PRIMARY KEY NOT NULL, 24 | Name TEXT NOT NULL, 25 | AID TEXT, 26 | Live_Status TEXT NOT NULL, 27 | Last_Notice_Time INTEGER, 28 | Live_Start_Time INTEGER NOT NULL);`; 29 | 30 | // 创建群关注up主表 31 | // Sub_Type:1为直播&动态订阅,2为直播订阅,3为动态订阅 32 | let subGroup = `CREATE TABLE IF NOT EXISTS subGroup 33 | (UID TEXT NOT NULL, 34 | Group_Number TEXT NOT NULL, 35 | Sub_Type INTEGER, 36 | PRIMARY KEY(UID,Group_Number));`; 37 | 38 | // 创建个人关注up主表 39 | let subPerson = `CREATE TABLE IF NOT EXISTS subPerson 40 | (UID TEXT NOT NULL, 41 | Person_Number TEXT NOT NULL, 42 | Sub_Type INTEGER, 43 | PRIMARY KEY(UID,Person_Number));` 44 | 45 | // 创建关键词回复表 46 | let keyWords = `CREATE TABLE IF NOT EXISTS keyWords 47 | (Group_Number TEXT NOT NULL, 48 | Key_Word TEXT NOT NULL, 49 | Repair_Word TEXT NOT NULL, 50 | Key_Type INTEGER NOT NULL, 51 | PRIMARY KEY(Key_Word,Group_Number));`; 52 | 53 | // 创建群组@回复词表 54 | let atWords = `CREATE TABLE IF NOT EXISTS atWords 55 | (atWordID INTEGER PRIMARY KEY AUTOINCREMENT, 56 | At_Word TEXT NOT NULL);`; 57 | 58 | // 创建ban复读群组表 59 | let repeatBan = `CREATE TABLE IF NOT EXISTS repeatBan 60 | (Group_Number INTEGER PRIMARY KEY);`; 61 | 62 | // 创建todolist表 63 | let todos = `CREATE TABLE IF NOT EXISTS todos 64 | (todoID INTEGER PRIMARY KEY AUTOINCREMENT, 65 | todo_text TEXT NOT NULL, 66 | Group_Number TEXT NOT NULL, 67 | todo_time INTEGER);`; 68 | 69 | // 创建表 70 | let createTable = (sql) => { 71 | return query(sql, []); 72 | }; 73 | 74 | createTable(UP); 75 | createTable(subGroup); 76 | createTable(subPerson); 77 | createTable(keyWords); 78 | createTable(atWords); 79 | createTable(repeatBan); 80 | createTable(todos); 81 | 82 | // 关键词模块 83 | // 给某个群添加关键词 84 | exports.addKeyWords = (values) => { 85 | let _sql = `INSERT INTO keyWords (Group_Number,Key_Word,Repair_Word,Key_Type) VALUES (?,?,?,?)`; 86 | return query(_sql, values); 87 | } 88 | 89 | // 查询某个群是否有某个关键词 90 | exports.selectOneKeyWords = (values) => { 91 | let _sql = `SELECT * FROM keyWords WHERE Group_Number=? AND Key_Word=?;`; 92 | return query(_sql, values); 93 | } 94 | 95 | // 查询一个群全部的精确或模糊关键词 96 | exports.selectKeyWords = (values) => { 97 | let _sql = `SELECT Key_Word, Repair_Word FROM keyWords WHERE Group_Number=? AND Key_Type=?;`; 98 | return query(_sql, values); 99 | } 100 | 101 | // 更新某个群的某个关键词的类型 102 | exports.updateKeyWords = (values) => { 103 | let _sql = `UPDATE keyWords SET Key_Type=? WHERE Group_Number=? AND Key_Word=?;`; 104 | return query(_sql, values); 105 | } 106 | 107 | // 删除某个群的某个关键词 108 | exports.deleteKeyWords = (values) => { 109 | let _sql = `DELETE FROM keyWords WHERE Group_Number=? AND Key_Word=?;`; 110 | return query(_sql, values); 111 | } 112 | 113 | 114 | // UP模块 115 | // 添加一个UP主 116 | exports.addUP = (values) => { 117 | let _sql = `INSERT INTO UP (UID,Name,AID,Live_Status,Live_Start_Time,Last_Notice_Time) VALUES (?,?,?,?,?,?);`; 118 | return query(_sql, values); 119 | } 120 | 121 | // 根据ID查询某个UP主的信息 122 | exports.selectUP = (values) => { 123 | let _sql = `SELECT * FROM UP WHERE UID=?;`; 124 | return query(_sql, values); 125 | } 126 | 127 | // 根据ID修改某个UP主的全部信息 128 | exports.updateUP = (values) => { 129 | let _sql = `UPDATE UP SET Name=?,AID=?,Live_Status=?,Dynamic_ID_Str=?,Live_Start_Time=?,Last_Notice_Time=? WHERE UID=?;`; 130 | return query(_sql, values); 131 | } 132 | 133 | // 根据ID修改上一次爬取某个UP主动态的时间 134 | exports.updateUPNoticeTime = (values) => { 135 | let _sql = `UPDATE UP SET Last_Notice_Time=? WHERE UID=?;`; 136 | return query(_sql, values); 137 | } 138 | 139 | // 重置所有UP主的爬取动态时间 140 | exports.updateAllUPNoticeTime = (values) => { 141 | let _sql = `UPDATE UP SET Last_Notice_Time=?;`; 142 | return query(_sql, values); 143 | } 144 | 145 | // 根据AID修改上一次某个UP主开始直播的时间 146 | exports.updateUPLiveTime = (values) => { 147 | let _sql = `UPDATE UP SET Live_Start_Time=? WHERE AID=?;`; 148 | return query(_sql, values); 149 | } 150 | 151 | //删除某个UP主 152 | exports.deleteUP = (values) => { 153 | let _sql = `DELETE FROM UP WHERE UID=?;`; 154 | return query(_sql, values); 155 | } 156 | 157 | 158 | // 个人关注模块 159 | // 添加个人关注 160 | exports.addPersonSub = (values) => { 161 | let _sql = `INSERT INTO subPerson (UID, Person_Number,Sub_Type) VALUES (?,?,?);`; 162 | return query(_sql, values); 163 | } 164 | 165 | // 查询某个个人对某个UP主的关注 166 | exports.selectPersonOneSub = (values) => { 167 | let _sql = `SELECT subPerson.Sub_Type,UP.Name FROM subPerson,UP 168 | WHERE subPerson.UID=? AND subPerson.UID=UP.UID AND Person_Number=?;`; 169 | return query(_sql, values); 170 | } 171 | 172 | // 查询某个人的全部关注 173 | exports.selectPersonAllSub = (values) => { 174 | let _sql = `SELECT * FROM subPerson WHERE UID=? AND Person_Number=?;`; 175 | return query(_sql, values); 176 | } 177 | 178 | // 查询某个群组的全部关注并获取UP主信息 179 | exports.selectPersonAllSubInfoByType = (values) => { 180 | let _sql = `SELECT UP.UID,UP.Name FROM subPerson,UP 181 | WHERE subPerson.Person_Number=? AND subPerson.UID=UP.UID AND Sub_Type=?;`; 182 | return query(_sql, values); 183 | } 184 | 185 | // 查询某个群组的全部直播或动态的关注 186 | exports.selectPersonSubByType = (values) => { 187 | let _sql = `SELECT * FROM subPerson WHERE UID=? AND Person_Number=? AND Sub_Type=?;`; 188 | return query(_sql, values); 189 | } 190 | 191 | // 查询某个人的全部直播或动态的关注 192 | exports.selectPersonSubByType = (values) => { 193 | let _sql = `SELECT * FROM subPerson WHERE UID=? AND Person_Number=? AND Sub_Type=?;`; 194 | return query(_sql, values); 195 | } 196 | 197 | // 修改某个人对某个UP的关注种类 198 | exports.updatePersonSubType = (values) => { 199 | let _sql = `UPDATE subPerson SET Sub_Type=? WHERE UID=? AND Person_Number=?;`; 200 | return query(_sql, values); 201 | } 202 | 203 | // 删除某个人对某个UP的关注 204 | exports.deletePersonSub = (values) => { 205 | let _sql = `DELETE FROM subPerson WHERE UID=? AND Person_Number=?;`; 206 | return query(_sql, values); 207 | } 208 | 209 | 210 | // 群组关注模块 211 | // 添加群组关注 212 | exports.addGroupSub = (values) => { 213 | let _sql = `INSERT INTO subGroup (UID, Group_Number,Sub_Type) VALUES (?,?,?);`; 214 | return query(_sql, values); 215 | } 216 | 217 | // 查询某个群组对某个UP主的关注 218 | exports.selectGroupOneSub = (values) => { 219 | let _sql = `SELECT subGroup.Sub_Type,UP.Name FROM subGroup,UP 220 | WHERE subGroup.UID=? AND subGroup.UID=UP.UID AND Group_Number=?;`; 221 | return query(_sql, values); 222 | } 223 | 224 | // 查询某个群组的全部关注 225 | exports.selectGroupAllSub = (values) => { 226 | let _sql = `SELECT * FROM subGroup WHERE Group_Number=?;`; 227 | return query(_sql, values); 228 | } 229 | 230 | // 查询某个群组的全部关注并获取UP主信息 231 | exports.selectGroupAllSubInfoByType = (values) => { 232 | let _sql = `SELECT UP.UID,UP.Name FROM subGroup,UP 233 | WHERE subGroup.Group_Number=? AND subGroup.UID=UP.UID AND Sub_Type=?;`; 234 | return query(_sql, values); 235 | } 236 | 237 | // 查询某个群组的全部直播或动态的关注 238 | exports.selectGroupSubByType = (values) => { 239 | let _sql = `SELECT * FROM subGroup WHERE UID=? AND Group_Number=? AND Sub_Type=?;`; 240 | return query(_sql, values); 241 | } 242 | 243 | // 修改某个群组对某个UP的关注种类 244 | exports.updateGroupSubType = (values) => { 245 | let _sql = `UPDATE subGroup SET Sub_Type=? WHERE UID=? AND Group_Number=?;`; 246 | return query(_sql, values); 247 | } 248 | 249 | // 删除某个群组对某个UP的关注 250 | exports.deleteGroupSub = (values) => { 251 | let _sql = `DELETE FROM subGroup WHERE UID=? AND Group_Number=?;`; 252 | return query(_sql, values); 253 | } 254 | 255 | 256 | // bilbili爬虫模块 257 | // 查询群组关注中需要爬取的房间 258 | exports.selectGroupRoomTospider = (values) => { 259 | let _sql = "SELECT AID,Live_Start_Time FROM UP,subGroup WHERE subGroup.UID=UP.UID AND subGroup.Sub_Type=?;"; 260 | return query(_sql, values); 261 | } 262 | 263 | // 查询个人关注中需要爬取的房间 264 | exports.selectPersonRoomTospider = (values) => { 265 | let _sql = "SELECT AID,Live_Start_Time FROM UP,subPerson WHERE subPerson.UID=UP.UID AND subPerson.Sub_Type=?;"; 266 | return query(_sql, values); 267 | } 268 | 269 | // 根据房间号和类型查找订阅的群组 270 | exports.selectGroupByAID = (values) => { 271 | let _sql = "SELECT Group_Number FROM subGroup,UP WHERE UP.UID=subGroup.UID AND UP.AID=? AND subGroup.Sub_Type=?;"; 272 | return query(_sql, values); 273 | } 274 | 275 | // 根据房间号和类型查找订阅的个人 276 | exports.selectPersonByAID = (values) => { 277 | let _sql = "SELECT Person_Number FROM subPerson,UP WHERE UP.UID=subPerson.UID AND UP.AID=? AND subPerson.Sub_Type=?;"; 278 | return query(_sql, values); 279 | } 280 | 281 | // 查询群组关注中需要爬取动态的UP主 282 | exports.selectGroupDynamicTospider = (values) => { 283 | let _sql = "SELECT UP.UID,Last_Notice_Time FROM UP,subGroup WHERE subGroup.UID=UP.UID AND subGroup.Sub_Type=?;"; 284 | return query(_sql, values); 285 | } 286 | 287 | // 查询个人关注中需要爬取动态的UP主 288 | exports.selectPersonDynamicTospider = (values) => { 289 | let _sql = "SELECT UP.UID,Last_Notice_Time FROM UP,subPerson WHERE subPerson.UID=UP.UID AND subPerson.Sub_Type=?;"; 290 | return query(_sql, values); 291 | } 292 | 293 | // 根据UID和类型查找订阅的群组 294 | exports.selectGroupByUID = (values) => { 295 | let _sql = "SELECT Group_Number FROM subGroup,UP WHERE UP.UID=subGroup.UID AND UP.UID=? AND subGroup.Sub_Type=?;"; 296 | return query(_sql, values); 297 | } 298 | 299 | // 根据房间号和类型查找订阅的个人 300 | exports.selectPersonByUID = (values) => { 301 | let _sql = "SELECT Person_Number FROM subPerson,UP WHERE UP.UID=subPerson.UID AND UP.UID=? AND subPerson.Sub_Type=?;"; 302 | return query(_sql, values); 303 | } 304 | 305 | 306 | // @bot回复词模块 307 | // 添加@bot后的回复词 308 | exports.addAtWords = (values) => { 309 | let _sql = `INSERT INTO atWords (At_Word) VALUES (?);`; 310 | return query(_sql, values); 311 | } 312 | 313 | // 查询全部的@bot回复词 314 | exports.selectAllAtWords = (values) => { 315 | let _sql = `SELECT * FROM atWords;`; 316 | return query(_sql, values); 317 | } 318 | 319 | 320 | // 复读模块 321 | // 添加群组复读 322 | exports.addGroupBanRepeat = (values) => { 323 | let _sql = `INSERT INTO repeatBan (Group_Number) VALUES (?);`; 324 | return query(_sql, values); 325 | } 326 | 327 | // 查询某个群组是否关闭复读 328 | exports.selectGroupBanRepeat = (values) => { 329 | let _sql = `SELECT * FROM repeatBan WHERE Group_Number=?;`; 330 | return query(_sql, values); 331 | } 332 | 333 | // 删除群组复读 334 | exports.deleteGroupBanRepeat = (values) => { 335 | let _sql = `DELETE FROM repeatBan WHERE Group_Number=?;`; 336 | return query(_sql, values); 337 | } 338 | 339 | 340 | // 其它模块 341 | // 查询某个UP主是否有关注的人 342 | exports.selectPersonSubByUP = (values) => { 343 | let _sql = `select * FROM subPerson WHERE UID=?;`; 344 | return query(_sql, values); 345 | } 346 | 347 | // 查询某个UP主是否有关注的群组 348 | exports.selectGroupSubByUP = (values) => { 349 | let _sql = `select * FROM subGroup WHERE UID=?;`; 350 | return query(_sql, values); 351 | } 352 | 353 | // todo模块 354 | // 添加todo 355 | exports.addTodo = (values) => { 356 | const _sql = `INSERT INTO todos (todo_text, Group_Number, todo_time) VALUES (?,?,?)`; 357 | return query(_sql, values); 358 | } 359 | 360 | // 查询某个todo 361 | exports.selectOneTodo = (values) => { 362 | const _sql = `SELECT * FROM todos WHERE todoID=?;`; 363 | return query(_sql, values) 364 | } 365 | 366 | // 查询todo 367 | exports.selectTodo = (values) => { 368 | const _sql = `SELECT * FROM todos WHERE Group_Number=? ORDER BY todo_time;`; 369 | return query(_sql, values); 370 | } 371 | 372 | // 分页查询todo 373 | exports.selectLimitTodo = (values) => { 374 | const _sql = `SELECT * FROM todos WHERE Group_Number=? ORDER BY todo_time LIMIT ?, ?;`; 375 | return query(_sql, values); 376 | } 377 | 378 | // 完成todo 379 | exports.deleteTodo = (values) => { 380 | const _sql = `DELETE FROM todos WHERE todoID=?;`; 381 | return query(_sql, values); 382 | } 383 | 384 | // 完成所有的todo 385 | exports.deleteAllTodo = (values) => { 386 | const _sql = `DELETE FROM todos WHERE Group_Number=?;`; 387 | return query(_sql, values); 388 | } -------------------------------------------------------------------------------- /test.js: -------------------------------------------------------------------------------- 1 | const sql = require("./scripts/sql.js"); 2 | const middleWare = require("./scripts/middleWare.js"); 3 | 4 | // let values = ["测试15", "114514", 1623700613591]; 5 | // // console.log(values); 6 | // sql.addTodo(values).then((res) => { 7 | // console.log(res); 8 | // }) 9 | 10 | // let values = ["114514"]; 11 | // sql.selectTodo(values).then((res) => { 12 | // console.log(res); 13 | // }) 14 | 15 | // let values = [1]; 16 | // sql.deleteTodo(values).then((res) => { 17 | // console.log(res); 18 | // }) 19 | 20 | // middleWare.createTodo("测试45", "114514").then((res) => { 21 | // console.log(res); 22 | // }) 23 | 24 | // middleWare.selectGroupTodo("114514").then((res) => { 25 | // console.log(res); 26 | // }) 27 | 28 | // middleWare.completeTodo(4).then((res) => { 29 | // console.log(res); 30 | // }) 31 | 32 | // let msg = "todo ceshi ceshi"; 33 | // let instruct = msg.split(" ", 2); 34 | // console.log(msg.substring(instruct[0].length + 1)); 35 | 36 | // let values = [2] 37 | // sql.selectOneTodo(values).then((res) => { 38 | // console.log(res); 39 | // }) 40 | --------------------------------------------------------------------------------