diff --git a/.gitignore b/.gitignore index 055395e..575e544 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,3 @@ -node_modules/ -.env +node_modules/ +.env package-lock.json \ No newline at end of file diff --git a/.npmignore b/.npmignore index 06db450..482a67f 100644 --- a/.npmignore +++ b/.npmignore @@ -1,4 +1,4 @@ -# npmignore for vyla-sdk in js -.env -test/ -node_modules/ +# npmignore for vyla-sdk in js +.env +test/ +node_modules/ diff --git a/LICENSE b/LICENSE index 12d4ca7..a28c66f 100644 --- a/LICENSE +++ b/LICENSE @@ -1,407 +1,407 @@ -Attribution-NonCommercial 4.0 International - -======================================================================= - -Creative Commons Corporation ("Creative Commons") is not a law firm and -does not provide legal services or legal advice. Distribution of -Creative Commons public licenses does not create a lawyer-client or -other relationship. Creative Commons makes its licenses and related -information available on an "as-is" basis. Creative Commons gives no -warranties regarding its licenses, any material licensed under their -terms and conditions, or any related information. Creative Commons -disclaims all liability for damages resulting from their use to the -fullest extent possible. - -Using Creative Commons Public Licenses - -Creative Commons public licenses provide a standard set of terms and -conditions that creators and other rights holders may use to share -original works of authorship and other material subject to copyright -and certain other rights specified in the public license below. The -following considerations are for informational purposes only, are not -exhaustive, and do not form part of our licenses. - - Considerations for licensors: Our public licenses are - intended for use by those authorized to give the public - permission to use material in ways otherwise restricted by - copyright and certain other rights. Our licenses are - irrevocable. Licensors should read and understand the terms - and conditions of the license they choose before applying it. - Licensors should also secure all rights necessary before - applying our licenses so that the public can reuse the - material as expected. Licensors should clearly mark any - material not subject to the license. This includes other CC- - licensed material, or material used under an exception or - limitation to copyright. More considerations for licensors: - wiki.creativecommons.org/Considerations_for_licensors - - Considerations for the public: By using one of our public - licenses, a licensor grants the public permission to use the - licensed material under specified terms and conditions. If - the licensor's permission is not necessary for any reason--for - example, because of any applicable exception or limitation to - copyright--then that use is not regulated by the license. Our - licenses grant only permissions under copyright and certain - other rights that a licensor has authority to grant. Use of - the licensed material may still be restricted for other - reasons, including because others have copyright or other - rights in the material. A licensor may make special requests, - such as asking that all changes be marked or described. - Although not required by our licenses, you are encouraged to - respect those requests where reasonable. More considerations - for the public: - wiki.creativecommons.org/Considerations_for_licensees - -======================================================================= - -Creative Commons Attribution-NonCommercial 4.0 International Public -License - -By exercising the Licensed Rights (defined below), You accept and agree -to be bound by the terms and conditions of this Creative Commons -Attribution-NonCommercial 4.0 International Public License ("Public -License"). To the extent this Public License may be interpreted as a -contract, You are granted the Licensed Rights in consideration of Your -acceptance of these terms and conditions, and the Licensor grants You -such rights in consideration of benefits the Licensor receives from -making the Licensed Material available under these terms and -conditions. - - -Section 1 -- Definitions. - - a. Adapted Material means material subject to Copyright and Similar - Rights that is derived from or based upon the Licensed Material - and in which the Licensed Material is translated, altered, - arranged, transformed, or otherwise modified in a manner requiring - permission under the Copyright and Similar Rights held by the - Licensor. For purposes of this Public License, where the Licensed - Material is a musical work, performance, or sound recording, - Adapted Material is always produced where the Licensed Material is - synched in timed relation with a moving image. - - b. Adapter's License means the license You apply to Your Copyright - and Similar Rights in Your contributions to Adapted Material in - accordance with the terms and conditions of this Public License. - - c. Copyright and Similar Rights means copyright and/or similar rights - closely related to copyright including, without limitation, - performance, broadcast, sound recording, and Sui Generis Database - Rights, without regard to how the rights are labeled or - categorized. For purposes of this Public License, the rights - specified in Section 2(b)(1)-(2) are not Copyright and Similar - Rights. - d. Effective Technological Measures means those measures that, in the - absence of proper authority, may not be circumvented under laws - fulfilling obligations under Article 11 of the WIPO Copyright - Treaty adopted on December 20, 1996, and/or similar international - agreements. - - e. Exceptions and Limitations means fair use, fair dealing, and/or - any other exception or limitation to Copyright and Similar Rights - that applies to Your use of the Licensed Material. - - f. Licensed Material means the artistic or literary work, database, - or other material to which the Licensor applied this Public - License. - - g. Licensed Rights means the rights granted to You subject to the - terms and conditions of this Public License, which are limited to - all Copyright and Similar Rights that apply to Your use of the - Licensed Material and that the Licensor has authority to license. - - h. Licensor means the individual(s) or entity(ies) granting rights - under this Public License. - - i. NonCommercial means not primarily intended for or directed towards - commercial advantage or monetary compensation. For purposes of - this Public License, the exchange of the Licensed Material for - other material subject to Copyright and Similar Rights by digital - file-sharing or similar means is NonCommercial provided there is - no payment of monetary compensation in connection with the - exchange. - - j. Share means to provide material to the public by any means or - process that requires permission under the Licensed Rights, such - as reproduction, public display, public performance, distribution, - dissemination, communication, or importation, and to make material - available to the public including in ways that members of the - public may access the material from a place and at a time - individually chosen by them. - - k. Sui Generis Database Rights means rights other than copyright - resulting from Directive 96/9/EC of the European Parliament and of - the Council of 11 March 1996 on the legal protection of databases, - as amended and/or succeeded, as well as other essentially - equivalent rights anywhere in the world. - - l. You means the individual or entity exercising the Licensed Rights - under this Public License. Your has a corresponding meaning. - - -Section 2 -- Scope. - - a. License grant. - - 1. Subject to the terms and conditions of this Public License, - the Licensor hereby grants You a worldwide, royalty-free, - non-sublicensable, non-exclusive, irrevocable license to - exercise the Licensed Rights in the Licensed Material to: - - a. reproduce and Share the Licensed Material, in whole or - in part, for NonCommercial purposes only; and - - b. produce, reproduce, and Share Adapted Material for - NonCommercial purposes only. - - 2. Exceptions and Limitations. For the avoidance of doubt, where - Exceptions and Limitations apply to Your use, this Public - License does not apply, and You do not need to comply with - its terms and conditions. - - 3. Term. The term of this Public License is specified in Section - 6(a). - - 4. Media and formats; technical modifications allowed. The - Licensor authorizes You to exercise the Licensed Rights in - all media and formats whether now known or hereafter created, - and to make technical modifications necessary to do so. The - Licensor waives and/or agrees not to assert any right or - authority to forbid You from making technical modifications - necessary to exercise the Licensed Rights, including - technical modifications necessary to circumvent Effective - Technological Measures. For purposes of this Public License, - simply making modifications authorized by this Section 2(a) - (4) never produces Adapted Material. - - 5. Downstream recipients. - - a. Offer from the Licensor -- Licensed Material. Every - recipient of the Licensed Material automatically - receives an offer from the Licensor to exercise the - Licensed Rights under the terms and conditions of this - Public License. - - b. No downstream restrictions. You may not offer or impose - any additional or different terms or conditions on, or - apply any Effective Technological Measures to, the - Licensed Material if doing so restricts exercise of the - Licensed Rights by any recipient of the Licensed - Material. - - 6. No endorsement. Nothing in this Public License constitutes or - may be construed as permission to assert or imply that You - are, or that Your use of the Licensed Material is, connected - with, or sponsored, endorsed, or granted official status by, - the Licensor or others designated to receive attribution as - provided in Section 3(a)(1)(A)(i). - - b. Other rights. - - 1. Moral rights, such as the right of integrity, are not - licensed under this Public License, nor are publicity, - privacy, and/or other similar personality rights; however, to - the extent possible, the Licensor waives and/or agrees not to - assert any such rights held by the Licensor to the limited - extent necessary to allow You to exercise the Licensed - Rights, but not otherwise. - - 2. Patent and trademark rights are not licensed under this - Public License. - - 3. To the extent possible, the Licensor waives any right to - collect royalties from You for the exercise of the Licensed - Rights, whether directly or through a collecting society - under any voluntary or waivable statutory or compulsory - licensing scheme. In all other cases the Licensor expressly - reserves any right to collect such royalties, including when - the Licensed Material is used other than for NonCommercial - purposes. - - -Section 3 -- License Conditions. - -Your exercise of the Licensed Rights is expressly made subject to the -following conditions. - - a. Attribution. - - 1. If You Share the Licensed Material (including in modified - form), You must: - - a. retain the following if it is supplied by the Licensor - with the Licensed Material: - - i. identification of the creator(s) of the Licensed - Material and any others designated to receive - attribution, in any reasonable manner requested by - the Licensor (including by pseudonym if - designated); - - ii. a copyright notice; - - iii. a notice that refers to this Public License; - - iv. a notice that refers to the disclaimer of - warranties; - - v. a URI or hyperlink to the Licensed Material to the - extent reasonably practicable; - - b. indicate if You modified the Licensed Material and - retain an indication of any previous modifications; and - - c. indicate the Licensed Material is licensed under this - Public License, and include the text of, or the URI or - hyperlink to, this Public License. - - 2. You may satisfy the conditions in Section 3(a)(1) in any - reasonable manner based on the medium, means, and context in - which You Share the Licensed Material. For example, it may be - reasonable to satisfy the conditions by providing a URI or - hyperlink to a resource that includes the required - information. - - 3. If requested by the Licensor, You must remove any of the - information required by Section 3(a)(1)(A) to the extent - reasonably practicable. - - 4. If You Share Adapted Material You produce, the Adapter's - License You apply must not prevent recipients of the Adapted - Material from complying with this Public License. - - -Section 4 -- Sui Generis Database Rights. - -Where the Licensed Rights include Sui Generis Database Rights that -apply to Your use of the Licensed Material: - - a. for the avoidance of doubt, Section 2(a)(1) grants You the right - to extract, reuse, reproduce, and Share all or a substantial - portion of the contents of the database for NonCommercial purposes - only; - - b. if You include all or a substantial portion of the database - contents in a database in which You have Sui Generis Database - Rights, then the database in which You have Sui Generis Database - Rights (but not its individual contents) is Adapted Material; and - - c. You must comply with the conditions in Section 3(a) if You Share - all or a substantial portion of the contents of the database. - -For the avoidance of doubt, this Section 4 supplements and does not -replace Your obligations under this Public License where the Licensed -Rights include other Copyright and Similar Rights. - - -Section 5 -- Disclaimer of Warranties and Limitation of Liability. - - a. UNLESS OTHERWISE SEPARATELY UNDERTAKEN BY THE LICENSOR, TO THE - EXTENT POSSIBLE, THE LICENSOR OFFERS THE LICENSED MATERIAL AS-IS - AND AS-AVAILABLE, AND MAKES NO REPRESENTATIONS OR WARRANTIES OF - ANY KIND CONCERNING THE LICENSED MATERIAL, WHETHER EXPRESS, - IMPLIED, STATUTORY, OR OTHER. THIS INCLUDES, WITHOUT LIMITATION, - WARRANTIES OF TITLE, MERCHANTABILITY, FITNESS FOR A PARTICULAR - PURPOSE, NON-INFRINGEMENT, ABSENCE OF LATENT OR OTHER DEFECTS, - ACCURACY, OR THE PRESENCE OR ABSENCE OF ERRORS, WHETHER OR NOT - KNOWN OR DISCOVERABLE. WHERE DISCLAIMERS OF WARRANTIES ARE NOT - ALLOWED IN FULL OR IN PART, THIS DISCLAIMER MAY NOT APPLY TO YOU. - - b. TO THE EXTENT POSSIBLE, IN NO EVENT WILL THE LICENSOR BE LIABLE - TO YOU ON ANY LEGAL THEORY (INCLUDING, WITHOUT LIMITATION, - NEGLIGENCE) OR OTHERWISE FOR ANY DIRECT, SPECIAL, INDIRECT, - INCIDENTAL, CONSEQUENTIAL, PUNITIVE, EXEMPLARY, OR OTHER LOSSES, - COSTS, EXPENSES, OR DAMAGES ARISING OUT OF THIS PUBLIC LICENSE OR - USE OF THE LICENSED MATERIAL, EVEN IF THE LICENSOR HAS BEEN - ADVISED OF THE POSSIBILITY OF SUCH LOSSES, COSTS, EXPENSES, OR - DAMAGES. WHERE A LIMITATION OF LIABILITY IS NOT ALLOWED IN FULL OR - IN PART, THIS LIMITATION MAY NOT APPLY TO YOU. - - c. The disclaimer of warranties and limitation of liability provided - above shall be interpreted in a manner that, to the extent - possible, most closely approximates an absolute disclaimer and - waiver of all liability. - - -Section 6 -- Term and Termination. - - a. This Public License applies for the term of the Copyright and - Similar Rights licensed here. However, if You fail to comply with - this Public License, then Your rights under this Public License - terminate automatically. - - b. Where Your right to use the Licensed Material has terminated under - Section 6(a), it reinstates: - - 1. automatically as of the date the violation is cured, provided - it is cured within 30 days of Your discovery of the - violation; or - - 2. upon express reinstatement by the Licensor. - - For the avoidance of doubt, this Section 6(b) does not affect any - right the Licensor may have to seek remedies for Your violations - of this Public License. - - c. For the avoidance of doubt, the Licensor may also offer the - Licensed Material under separate terms or conditions or stop - distributing the Licensed Material at any time; however, doing so - will not terminate this Public License. - - d. Sections 1, 5, 6, 7, and 8 survive termination of this Public - License. - - -Section 7 -- Other Terms and Conditions. - - a. The Licensor shall not be bound by any additional or different - terms or conditions communicated by You unless expressly agreed. - - b. Any arrangements, understandings, or agreements regarding the - Licensed Material not stated herein are separate from and - independent of the terms and conditions of this Public License. - - -Section 8 -- Interpretation. - - a. For the avoidance of doubt, this Public License does not, and - shall not be interpreted to, reduce, limit, restrict, or impose - conditions on any use of the Licensed Material that could lawfully - be made without permission under this Public License. - - b. To the extent possible, if any provision of this Public License is - deemed unenforceable, it shall be automatically reformed to the - minimum extent necessary to make it enforceable. If the provision - cannot be reformed, it shall be severed from this Public License - without affecting the enforceability of the remaining terms and - conditions. - - c. No term or condition of this Public License will be waived and no - failure to comply consented to unless expressly agreed to by the - Licensor. - - d. Nothing in this Public License constitutes or may be interpreted - as a limitation upon, or waiver of, any privileges and immunities - that apply to the Licensor or You, including from the legal - processes of any jurisdiction or authority. - -======================================================================= - -Creative Commons is not a party to its public -licenses. Notwithstanding, Creative Commons may elect to apply one of -its public licenses to material it publishes and in those instances -will be considered the “Licensor.” The text of the Creative Commons -public licenses is dedicated to the public domain under the CC0 Public -Domain Dedication. Except for the limited purpose of indicating that -material is shared under a Creative Commons public license or as -otherwise permitted by the Creative Commons policies published at -creativecommons.org/policies, Creative Commons does not authorize the -use of the trademark "Creative Commons" or any other trademark or logo -of Creative Commons without its prior written consent including, -without limitation, in connection with any unauthorized modifications -to any of its public licenses or any other arrangements, -understandings, or agreements concerning use of licensed material. For -the avoidance of doubt, this paragraph does not form part of the -public licenses. - +Attribution-NonCommercial 4.0 International + +======================================================================= + +Creative Commons Corporation ("Creative Commons") is not a law firm and +does not provide legal services or legal advice. Distribution of +Creative Commons public licenses does not create a lawyer-client or +other relationship. Creative Commons makes its licenses and related +information available on an "as-is" basis. Creative Commons gives no +warranties regarding its licenses, any material licensed under their +terms and conditions, or any related information. Creative Commons +disclaims all liability for damages resulting from their use to the +fullest extent possible. + +Using Creative Commons Public Licenses + +Creative Commons public licenses provide a standard set of terms and +conditions that creators and other rights holders may use to share +original works of authorship and other material subject to copyright +and certain other rights specified in the public license below. The +following considerations are for informational purposes only, are not +exhaustive, and do not form part of our licenses. + + Considerations for licensors: Our public licenses are + intended for use by those authorized to give the public + permission to use material in ways otherwise restricted by + copyright and certain other rights. Our licenses are + irrevocable. Licensors should read and understand the terms + and conditions of the license they choose before applying it. + Licensors should also secure all rights necessary before + applying our licenses so that the public can reuse the + material as expected. Licensors should clearly mark any + material not subject to the license. This includes other CC- + licensed material, or material used under an exception or + limitation to copyright. More considerations for licensors: + wiki.creativecommons.org/Considerations_for_licensors + + Considerations for the public: By using one of our public + licenses, a licensor grants the public permission to use the + licensed material under specified terms and conditions. If + the licensor's permission is not necessary for any reason--for + example, because of any applicable exception or limitation to + copyright--then that use is not regulated by the license. Our + licenses grant only permissions under copyright and certain + other rights that a licensor has authority to grant. Use of + the licensed material may still be restricted for other + reasons, including because others have copyright or other + rights in the material. A licensor may make special requests, + such as asking that all changes be marked or described. + Although not required by our licenses, you are encouraged to + respect those requests where reasonable. More considerations + for the public: + wiki.creativecommons.org/Considerations_for_licensees + +======================================================================= + +Creative Commons Attribution-NonCommercial 4.0 International Public +License + +By exercising the Licensed Rights (defined below), You accept and agree +to be bound by the terms and conditions of this Creative Commons +Attribution-NonCommercial 4.0 International Public License ("Public +License"). To the extent this Public License may be interpreted as a +contract, You are granted the Licensed Rights in consideration of Your +acceptance of these terms and conditions, and the Licensor grants You +such rights in consideration of benefits the Licensor receives from +making the Licensed Material available under these terms and +conditions. + + +Section 1 -- Definitions. + + a. Adapted Material means material subject to Copyright and Similar + Rights that is derived from or based upon the Licensed Material + and in which the Licensed Material is translated, altered, + arranged, transformed, or otherwise modified in a manner requiring + permission under the Copyright and Similar Rights held by the + Licensor. For purposes of this Public License, where the Licensed + Material is a musical work, performance, or sound recording, + Adapted Material is always produced where the Licensed Material is + synched in timed relation with a moving image. + + b. Adapter's License means the license You apply to Your Copyright + and Similar Rights in Your contributions to Adapted Material in + accordance with the terms and conditions of this Public License. + + c. Copyright and Similar Rights means copyright and/or similar rights + closely related to copyright including, without limitation, + performance, broadcast, sound recording, and Sui Generis Database + Rights, without regard to how the rights are labeled or + categorized. For purposes of this Public License, the rights + specified in Section 2(b)(1)-(2) are not Copyright and Similar + Rights. + d. Effective Technological Measures means those measures that, in the + absence of proper authority, may not be circumvented under laws + fulfilling obligations under Article 11 of the WIPO Copyright + Treaty adopted on December 20, 1996, and/or similar international + agreements. + + e. Exceptions and Limitations means fair use, fair dealing, and/or + any other exception or limitation to Copyright and Similar Rights + that applies to Your use of the Licensed Material. + + f. Licensed Material means the artistic or literary work, database, + or other material to which the Licensor applied this Public + License. + + g. Licensed Rights means the rights granted to You subject to the + terms and conditions of this Public License, which are limited to + all Copyright and Similar Rights that apply to Your use of the + Licensed Material and that the Licensor has authority to license. + + h. Licensor means the individual(s) or entity(ies) granting rights + under this Public License. + + i. NonCommercial means not primarily intended for or directed towards + commercial advantage or monetary compensation. For purposes of + this Public License, the exchange of the Licensed Material for + other material subject to Copyright and Similar Rights by digital + file-sharing or similar means is NonCommercial provided there is + no payment of monetary compensation in connection with the + exchange. + + j. Share means to provide material to the public by any means or + process that requires permission under the Licensed Rights, such + as reproduction, public display, public performance, distribution, + dissemination, communication, or importation, and to make material + available to the public including in ways that members of the + public may access the material from a place and at a time + individually chosen by them. + + k. Sui Generis Database Rights means rights other than copyright + resulting from Directive 96/9/EC of the European Parliament and of + the Council of 11 March 1996 on the legal protection of databases, + as amended and/or succeeded, as well as other essentially + equivalent rights anywhere in the world. + + l. You means the individual or entity exercising the Licensed Rights + under this Public License. Your has a corresponding meaning. + + +Section 2 -- Scope. + + a. License grant. + + 1. Subject to the terms and conditions of this Public License, + the Licensor hereby grants You a worldwide, royalty-free, + non-sublicensable, non-exclusive, irrevocable license to + exercise the Licensed Rights in the Licensed Material to: + + a. reproduce and Share the Licensed Material, in whole or + in part, for NonCommercial purposes only; and + + b. produce, reproduce, and Share Adapted Material for + NonCommercial purposes only. + + 2. Exceptions and Limitations. For the avoidance of doubt, where + Exceptions and Limitations apply to Your use, this Public + License does not apply, and You do not need to comply with + its terms and conditions. + + 3. Term. The term of this Public License is specified in Section + 6(a). + + 4. Media and formats; technical modifications allowed. The + Licensor authorizes You to exercise the Licensed Rights in + all media and formats whether now known or hereafter created, + and to make technical modifications necessary to do so. The + Licensor waives and/or agrees not to assert any right or + authority to forbid You from making technical modifications + necessary to exercise the Licensed Rights, including + technical modifications necessary to circumvent Effective + Technological Measures. For purposes of this Public License, + simply making modifications authorized by this Section 2(a) + (4) never produces Adapted Material. + + 5. Downstream recipients. + + a. Offer from the Licensor -- Licensed Material. Every + recipient of the Licensed Material automatically + receives an offer from the Licensor to exercise the + Licensed Rights under the terms and conditions of this + Public License. + + b. No downstream restrictions. You may not offer or impose + any additional or different terms or conditions on, or + apply any Effective Technological Measures to, the + Licensed Material if doing so restricts exercise of the + Licensed Rights by any recipient of the Licensed + Material. + + 6. No endorsement. Nothing in this Public License constitutes or + may be construed as permission to assert or imply that You + are, or that Your use of the Licensed Material is, connected + with, or sponsored, endorsed, or granted official status by, + the Licensor or others designated to receive attribution as + provided in Section 3(a)(1)(A)(i). + + b. Other rights. + + 1. Moral rights, such as the right of integrity, are not + licensed under this Public License, nor are publicity, + privacy, and/or other similar personality rights; however, to + the extent possible, the Licensor waives and/or agrees not to + assert any such rights held by the Licensor to the limited + extent necessary to allow You to exercise the Licensed + Rights, but not otherwise. + + 2. Patent and trademark rights are not licensed under this + Public License. + + 3. To the extent possible, the Licensor waives any right to + collect royalties from You for the exercise of the Licensed + Rights, whether directly or through a collecting society + under any voluntary or waivable statutory or compulsory + licensing scheme. In all other cases the Licensor expressly + reserves any right to collect such royalties, including when + the Licensed Material is used other than for NonCommercial + purposes. + + +Section 3 -- License Conditions. + +Your exercise of the Licensed Rights is expressly made subject to the +following conditions. + + a. Attribution. + + 1. If You Share the Licensed Material (including in modified + form), You must: + + a. retain the following if it is supplied by the Licensor + with the Licensed Material: + + i. identification of the creator(s) of the Licensed + Material and any others designated to receive + attribution, in any reasonable manner requested by + the Licensor (including by pseudonym if + designated); + + ii. a copyright notice; + + iii. a notice that refers to this Public License; + + iv. a notice that refers to the disclaimer of + warranties; + + v. a URI or hyperlink to the Licensed Material to the + extent reasonably practicable; + + b. indicate if You modified the Licensed Material and + retain an indication of any previous modifications; and + + c. indicate the Licensed Material is licensed under this + Public License, and include the text of, or the URI or + hyperlink to, this Public License. + + 2. You may satisfy the conditions in Section 3(a)(1) in any + reasonable manner based on the medium, means, and context in + which You Share the Licensed Material. For example, it may be + reasonable to satisfy the conditions by providing a URI or + hyperlink to a resource that includes the required + information. + + 3. If requested by the Licensor, You must remove any of the + information required by Section 3(a)(1)(A) to the extent + reasonably practicable. + + 4. If You Share Adapted Material You produce, the Adapter's + License You apply must not prevent recipients of the Adapted + Material from complying with this Public License. + + +Section 4 -- Sui Generis Database Rights. + +Where the Licensed Rights include Sui Generis Database Rights that +apply to Your use of the Licensed Material: + + a. for the avoidance of doubt, Section 2(a)(1) grants You the right + to extract, reuse, reproduce, and Share all or a substantial + portion of the contents of the database for NonCommercial purposes + only; + + b. if You include all or a substantial portion of the database + contents in a database in which You have Sui Generis Database + Rights, then the database in which You have Sui Generis Database + Rights (but not its individual contents) is Adapted Material; and + + c. You must comply with the conditions in Section 3(a) if You Share + all or a substantial portion of the contents of the database. + +For the avoidance of doubt, this Section 4 supplements and does not +replace Your obligations under this Public License where the Licensed +Rights include other Copyright and Similar Rights. + + +Section 5 -- Disclaimer of Warranties and Limitation of Liability. + + a. UNLESS OTHERWISE SEPARATELY UNDERTAKEN BY THE LICENSOR, TO THE + EXTENT POSSIBLE, THE LICENSOR OFFERS THE LICENSED MATERIAL AS-IS + AND AS-AVAILABLE, AND MAKES NO REPRESENTATIONS OR WARRANTIES OF + ANY KIND CONCERNING THE LICENSED MATERIAL, WHETHER EXPRESS, + IMPLIED, STATUTORY, OR OTHER. THIS INCLUDES, WITHOUT LIMITATION, + WARRANTIES OF TITLE, MERCHANTABILITY, FITNESS FOR A PARTICULAR + PURPOSE, NON-INFRINGEMENT, ABSENCE OF LATENT OR OTHER DEFECTS, + ACCURACY, OR THE PRESENCE OR ABSENCE OF ERRORS, WHETHER OR NOT + KNOWN OR DISCOVERABLE. WHERE DISCLAIMERS OF WARRANTIES ARE NOT + ALLOWED IN FULL OR IN PART, THIS DISCLAIMER MAY NOT APPLY TO YOU. + + b. TO THE EXTENT POSSIBLE, IN NO EVENT WILL THE LICENSOR BE LIABLE + TO YOU ON ANY LEGAL THEORY (INCLUDING, WITHOUT LIMITATION, + NEGLIGENCE) OR OTHERWISE FOR ANY DIRECT, SPECIAL, INDIRECT, + INCIDENTAL, CONSEQUENTIAL, PUNITIVE, EXEMPLARY, OR OTHER LOSSES, + COSTS, EXPENSES, OR DAMAGES ARISING OUT OF THIS PUBLIC LICENSE OR + USE OF THE LICENSED MATERIAL, EVEN IF THE LICENSOR HAS BEEN + ADVISED OF THE POSSIBILITY OF SUCH LOSSES, COSTS, EXPENSES, OR + DAMAGES. WHERE A LIMITATION OF LIABILITY IS NOT ALLOWED IN FULL OR + IN PART, THIS LIMITATION MAY NOT APPLY TO YOU. + + c. The disclaimer of warranties and limitation of liability provided + above shall be interpreted in a manner that, to the extent + possible, most closely approximates an absolute disclaimer and + waiver of all liability. + + +Section 6 -- Term and Termination. + + a. This Public License applies for the term of the Copyright and + Similar Rights licensed here. However, if You fail to comply with + this Public License, then Your rights under this Public License + terminate automatically. + + b. Where Your right to use the Licensed Material has terminated under + Section 6(a), it reinstates: + + 1. automatically as of the date the violation is cured, provided + it is cured within 30 days of Your discovery of the + violation; or + + 2. upon express reinstatement by the Licensor. + + For the avoidance of doubt, this Section 6(b) does not affect any + right the Licensor may have to seek remedies for Your violations + of this Public License. + + c. For the avoidance of doubt, the Licensor may also offer the + Licensed Material under separate terms or conditions or stop + distributing the Licensed Material at any time; however, doing so + will not terminate this Public License. + + d. Sections 1, 5, 6, 7, and 8 survive termination of this Public + License. + + +Section 7 -- Other Terms and Conditions. + + a. The Licensor shall not be bound by any additional or different + terms or conditions communicated by You unless expressly agreed. + + b. Any arrangements, understandings, or agreements regarding the + Licensed Material not stated herein are separate from and + independent of the terms and conditions of this Public License. + + +Section 8 -- Interpretation. + + a. For the avoidance of doubt, this Public License does not, and + shall not be interpreted to, reduce, limit, restrict, or impose + conditions on any use of the Licensed Material that could lawfully + be made without permission under this Public License. + + b. To the extent possible, if any provision of this Public License is + deemed unenforceable, it shall be automatically reformed to the + minimum extent necessary to make it enforceable. If the provision + cannot be reformed, it shall be severed from this Public License + without affecting the enforceability of the remaining terms and + conditions. + + c. No term or condition of this Public License will be waived and no + failure to comply consented to unless expressly agreed to by the + Licensor. + + d. Nothing in this Public License constitutes or may be interpreted + as a limitation upon, or waiver of, any privileges and immunities + that apply to the Licensor or You, including from the legal + processes of any jurisdiction or authority. + +======================================================================= + +Creative Commons is not a party to its public +licenses. Notwithstanding, Creative Commons may elect to apply one of +its public licenses to material it publishes and in those instances +will be considered the “Licensor.” The text of the Creative Commons +public licenses is dedicated to the public domain under the CC0 Public +Domain Dedication. Except for the limited purpose of indicating that +material is shared under a Creative Commons public license or as +otherwise permitted by the Creative Commons policies published at +creativecommons.org/policies, Creative Commons does not authorize the +use of the trademark "Creative Commons" or any other trademark or logo +of Creative Commons without its prior written consent including, +without limitation, in connection with any unauthorized modifications +to any of its public licenses or any other arrangements, +understandings, or agreements concerning use of licensed material. For +the avoidance of doubt, this paragraph does not form part of the +public licenses. + Creative Commons may be contacted at creativecommons.org. \ No newline at end of file diff --git a/README.md b/README.md index 3edf372..56dca7c 100644 --- a/README.md +++ b/README.md @@ -1,40 +1,40 @@ -# vyla/sdk -VylaSDK is a javascript base version of [Vyla](https://vyla.mintlify.app/)'s stream & scrape api, allowing developers to access content providers directly without using a REST api. This gives you the power & updates of Vyla without the headaches of api keys & server reliability. - -## Installing -To start, install VylaSDK through npm or pnpm: -```bash -# npm -npm install @vyla-entertainment/sdk - -# pnpm -pnpm install @vyla-entertainment/sdk -``` - -## Usage -Start by creating a VylaSDK element with your TMDB api key. -```js -import VylaSDK from "@vyla-entertainment/sdk"; - -const sdk = new VylaSDK({ - tmdbApiKey: ... -}); -``` - -You can now use this to access Vyla's content. -```js -// Get sources -// Args: excludeDisabled -sdk.getSources(false); - -// Get subtitles -// Args: tmdb id, season?, episode? -await sdk.getSubtitles('0000000', null, null); -> {label, file, type, source}[] - -// Probe & test a source -// Args: source key -await sdk.probeSource('nebula'); -> {ok, ms} - -// Probe & test all sources -await sdk.probeAllSources(); -> {'key': {ok, ms}, ...} +# vyla/sdk +VylaSDK is a javascript base version of [Vyla](https://vyla.mintlify.app/)'s stream & scrape api, allowing developers to access content providers directly without using a REST api. This gives you the power & updates of Vyla without the headaches of api keys & server reliability. + +## Installing +To start, install VylaSDK through npm or pnpm: +```bash +# npm +npm install @vyla-entertainment/sdk + +# pnpm +pnpm install @vyla-entertainment/sdk +``` + +## Usage +Start by creating a VylaSDK element with your TMDB api key. +```js +import VylaSDK from "@vyla-entertainment/sdk"; + +const sdk = new VylaSDK({ + tmdbApiKey: ... +}); +``` + +You can now use this to access Vyla's content. +```js +// Get sources +// Args: excludeDisabled +sdk.getSources(false); + +// Get subtitles +// Args: tmdb id, season?, episode? +await sdk.getSubtitles('0000000', null, null); -> {label, file, type, source}[] + +// Probe & test a source +// Args: source key +await sdk.probeSource('nebula'); -> {ok, ms} + +// Probe & test all sources +await sdk.probeAllSources(); -> {'key': {ok, ms}, ...} ``` \ No newline at end of file diff --git a/src/config.js b/src/config.js index d7f7e30..efd2ddb 100644 --- a/src/config.js +++ b/src/config.js @@ -1,519 +1,519 @@ -export const SOURCES = [ - { - key: '1embed', - label: '1Embed', - sourceFile: '1embed', - proxyParam: '1e', - timeout: 20000, - jitter: 500, - retries: 2, - multiUrl: true, - }, - - { - key: '123anime', - label: '123Anime', - sourceFile: '123anime', - proxyParam: 'a1', - timeout: 25000, - jitter: 500, - retries: 2, - multiUrl: false, - skipProxy: true, - cdnHeaders: [{ - pattern: /hlsx\d+cdn\.|burntburst\d+\.store|echovideo\.ru/i, - headers: { - Referer: 'https://play2.echovideo.ru/', - Origin: 'https://play2.echovideo.ru', - }, - },], - }, - - { - key: 'anihq-sub', - label: 'AniHQ (Sub)', - sourceFile: 'anihq', - proxyParam: 'ahsub', - timeout: 25000, - jitter: 500, - retries: 2, - multiUrl: true, - skipProxy: true - }, - - { - key: 'anihq-dub', - label: 'AniHQ (Dub)', - sourceFile: 'anihq', - proxyParam: 'ahdub', - timeout: 25000, - jitter: 500, - retries: 2, - multiUrl: true, - skipProxy: true - }, - - { - key: 'anineko-sub', - sourceFile: 'anineko', - label: 'AniNeko (Sub)', - proxyParam: 'anksub', - timeout: 25000, - jitter: 500, - retries: 2 - }, - - { - key: 'anineko-dub', - sourceFile: 'anineko', - label: 'AniNeko (Dub)', - proxyParam: 'ankdub', - timeout: 25000, - jitter: 500, - retries: 2 - }, - - { - key: 'anipm-sub', - sourceFile: 'anipm', - label: 'AniPM (Sub)', - proxyParam: 'apsub', - timeout: 25000, - jitter: 500, - retries: 2, - skipProxy: true, - skipVerify: true, - multiUrl: true, - verifyHeaders: { - Referer: 'https://ani.pm/', - Origin: 'https://ani.pm', - }, - }, - - { - key: 'anipm-dub', - sourceFile: 'anipm', - label: 'AniPM (Dub)', - proxyParam: 'apdub', - timeout: 25000, - jitter: 500, - retries: 2, - skipProxy: true, - skipVerify: true, - multiUrl: true, - verifyHeaders: { - Referer: 'https://ani.pm/', - Origin: 'https://ani.pm', - }, - }, - - { - key: 'flaxmovies', - label: 'FlaxMovies', - sourceFile: 'flaxmovies', - proxyParam: 'fx', - timeout: 20000, - jitter: 500, - retries: 2, - multiUrl: true, - disabled: true, // Temporarily disabled because their site is down, all streams are returning 403's - cdnHeaders: [{ - pattern: /flix2watch\.pro/i, - headers: { - Referer: 'https://flaxmovies.xyz/', - Origin: 'https://flaxmovies.xyz', - }, - },], - }, - - { - key: 'fsharetv', - label: 'FShareTV', - sourceFile: 'fsharetv', - proxyParam: 'fs', - timeout: 25000, - jitter: 600, - retries: 2, - multiUrl: false, - verifyHeaders: { - Accept: 'text/html,application/xhtml+xml,application/xml;q=0.9,/;q=0.8', - 'Accept-Language': 'en-US,en;q=0.9', - Referer: 'https://fsharetv.cc', - }, - }, - - { - key: 'goated', - label: 'Goated', - sourceFile: 'goated', - proxyParam: 'gt', - timeout: 25000, - jitter: 500, - retries: 2, - multiUrl: true, - skipProxy: true, - }, - - { - key: 'fsonic', - label: 'Fsonic', - sourceFile: 'fsonic', - proxyParam: 'fn', - timeout: 35000, - jitter: 600, - retries: 1, - multiUrl: true, - }, - - { - key: 'fsonline', - label: 'FSOnline', - sourceFile: 'fsonline', - proxyParam: 'fo', - timeout: 20000, - retries: 1, - jitter: 0, - multiUrl: true, - skipProxy: true, - }, - - { - key: 'hexa', - label: 'Hexa', - sourceFile: 'hexa', - proxyParam: 'hx', - timeout: 20000, - jitter: 500, - retries: 2, - }, - - { - key: 'kisskh', - label: 'KissKH', - sourceFile: 'kisskh', - proxyParam: 'kk', - timeout: 30000, - jitter: 500, - retries: 1, - }, - - { - key: 'lookmovie', - label: 'LookMovie', - sourceFile: 'lookmovie', - proxyParam: 'lm', - timeout: 20000, - jitter: 500, - retries: 2, - multiUrl: true, - verifyHeaders: { - 'Accept-Language': 'en-US,en;q=0.9', - }, - }, - - { - key: 'mapple', - label: 'Mapple', - sourceFile: 'mapple', - proxyParam: 'mp', - timeout: 15000, - retries: 1, - jitter: 0 - }, - - { - key: 'meowtv', - label: 'MeowTV', - sourceFile: 'meowtv', - proxyParam: 'mt', - timeout: 20000, - jitter: 500, - retries: 2, - multiUrl: true, - skipProxy: true - }, - - { - key: 'nebula', - label: 'Nebula', - sourceFile: 'nebula', - proxyParam: 'nb', - timeout: 25000, - jitter: 500, - retries: 1, - multiUrl: true, - skipProxy: true, - }, - - { - key: 'nekowatch-sub', - sourceFile: 'nekowatch', - label: 'NekoWatch (Sub)', - proxyParam: 'nwsub', - timeout: 30000, - jitter: 500, - retries: 2 - }, - - { - key: 'nekowatch-dub', - sourceFile: 'nekowatch', - label: 'NekoWatch (Dub)', - proxyParam: 'nwdub', - timeout: 30000, - jitter: 500, - retries: 2 - }, - - { - key: 'opstream', - label: 'OpStream', - sourceFile: 'opstream', - proxyParam: 'op', - timeout: 35000, - jitter: 500, - retries: 2, - multiUrl: true, - skipProxy: true, - verifyHeaders: { - Referer: 'https://opstream.fun/', - Origin: 'https://opstream.fun', - }, - }, - - { - key: 'peachify', - label: 'Peachify', - sourceFile: 'peachify', - proxyParam: 'pf', - timeout: 30000, - jitter: 500, - retries: 1, - multiUrl: true - }, - - { - key: 'pengu', - label: 'Pengu', - sourceFile: 'pengu', - proxyParam: 'pg', - timeout: 25000, - jitter: 500, - retries: 1, - multiUrl: true, - skipProxy: true, - disabled: true, // Temporarily disabled because they now require google auth - }, - - { - key: 'purstream', - sourceFile: 'purstream', - label: 'Purstream', - proxyParam: 'ps', - timeout: 20000, - jitter: 500, - retries: 2, - }, - - { - key: 'vidapi', - label: 'VidAPI', - sourceFile: 'vidapi', - proxyParam: 'va', - timeout: 25000, - jitter: 500, - retries: 1, - multiUrl: true - }, - - { - key: 'vidcore', - sourceFile: 'vidcore', - label: 'Vidcore', - proxyParam: 'vc', - timeout: 30000, - jitter: 500, - retries: 2, - sourcesTimeout: 10000, - }, - - { - key: 'videasy', - label: 'Videasy', - sourceFile: 'videasy', - proxyParam: 'vy', - timeout: 40000, - sourcesTimeout: 10000, - jitter: 900, - retries: 3, - multiUrl: true, - verifyHeaders: { - Accept: 'application/json, /; q=0.01', - Referer: 'https://player.videasy.net/', - Origin: 'https://player.videasy.net', - }, - }, - - { - key: 'vidfast', - label: 'Vidfast', - sourceFile: 'vidfast', - proxyParam: 'vf', - timeout: 35000, - jitter: 500, - retries: 1, - }, - - { - key: 'vidlink', - label: 'Vidlink', - sourceFile: 'vidlink', - proxyParam: 'vl', - timeout: 20000, - jitter: 500, - retries: 2, - skipProxy: true, - multiUrl: true, - disabled: true, // Temporarily disabled because their site is down, all streams are returning 403's - }, - - { - key: 'vidnest', - label: 'VidNest', - sourceFile: 'vidnest', - proxyParam: 'vdn', - timeout: 20000, - retries: 1, - jitter: 0, - multiUrl: true, - }, - - { - key: 'vidnest-sub', - label: 'VidNest (Sub)', - sourceFile: 'vidnest', - proxyParam: 'vdn', - timeout: 20000, - retries: 1, - jitter: 0, - multiUrl: true, - skipProxy: true, - }, - - { - key: 'vidnest-dub', - label: 'VidNest (Dub)', - sourceFile: 'vidnest', - proxyParam: 'vdn', - timeout: 20000, - retries: 1, - jitter: 0, - multiUrl: true, - skipProxy: true, - }, - - { - key: 'vidrift', - label: 'VidRift', - sourceFile: 'vidrift', - proxyParam: 'vr', - timeout: 20000, - jitter: 500, - retries: 2, - multiUrl: true, - skipProxy: true - }, - - { - key: 'vidrock', - label: 'VidRock', - sourceFile: 'vidrock', - proxyParam: 'vr', - timeout: 20000, - jitter: 800, - retries: 3, - multiUrl: true, - cdnHeaders: [{ - pattern: /./, - headers: { - Accept: '/', - 'Accept-Language': 'en-US,en;q=0.9', - Referer: 'https://vidrock.ru/', - Origin: 'https://vidrock.ru', - }, - },], - }, - - { - key: 'vidsync', - label: 'VidSync', - sourceFile: 'vidsync', - proxyParam: 'vs', - timeout: 20000, - retries: 2, - multiUrl: true, - disabled: true, // Temporarily disabled due to enc dec issues - }, - - { - key: 'vidup', - label: 'VidUp', - sourceFile: 'vidup', - proxyParam: 'vu', - timeout: 35000, - jitter: 500, - retries: 1, - multiUrl: true - }, - - { - key: 'vidzee', - label: 'VidZee', - sourceFile: 'vidzee', - proxyParam: 'vz', - timeout: 20000, - sourcesTimeout: 10000, - jitter: 400, - retries: 3, - disabled: true, // Temporarily disabled because their site is down, all streams are returning 403's - verifyHeaders: { - Accept: '/', - 'Accept-Language': 'en-US,en;q=0.9', - Referer: 'https://player.vidzee.wtf', - Origin: 'https://player.vidzee.wtf', - }, - }, - - { - key: 'vixsrc', - label: 'VixSrc', - sourceFile: 'vixsrc', - proxyParam: 'vx', - timeout: 35000, - jitter: 0, - retries: 2, - multiUrl: false, - skipProxy: true, - verifyHeaders: { - Accept: 'application/json, text/javascript, /; q=0.01', - 'Accept-Language': 'en-US,en;q=0.9', - Referer: 'https://vixsrc.to/', - Origin: 'https://vixsrc.to', - }, - }, - - { - key: 'xpass', - sourceFile: 'xpass', - label: 'XPass', - proxyParam: 'xp', - timeout: 20000, - jitter: 500, - retries: 2, - skipProxy: true, - }, -]; - -export const HEALTH_PROBE_ID = '155'; -export const SOURCE_MAP = Object.fromEntries(SOURCES.map(s => [s.key, s])); +export const SOURCES = [ + { + key: '1embed', + label: '1Embed', + sourceFile: '1embed', + proxyParam: '1e', + timeout: 20000, + jitter: 500, + retries: 2, + multiUrl: true, + }, + + { + key: '123anime', + label: '123Anime', + sourceFile: '123anime', + proxyParam: 'a1', + timeout: 25000, + jitter: 500, + retries: 2, + multiUrl: false, + skipProxy: true, + cdnHeaders: [{ + pattern: /hlsx\d+cdn\.|burntburst\d+\.store|echovideo\.ru/i, + headers: { + Referer: 'https://play2.echovideo.ru/', + Origin: 'https://play2.echovideo.ru', + }, + },], + }, + + { + key: 'anihq-sub', + label: 'AniHQ (Sub)', + sourceFile: 'anihq', + proxyParam: 'ahsub', + timeout: 25000, + jitter: 500, + retries: 2, + multiUrl: true, + skipProxy: true + }, + + { + key: 'anihq-dub', + label: 'AniHQ (Dub)', + sourceFile: 'anihq', + proxyParam: 'ahdub', + timeout: 25000, + jitter: 500, + retries: 2, + multiUrl: true, + skipProxy: true + }, + + { + key: 'anineko-sub', + sourceFile: 'anineko', + label: 'AniNeko (Sub)', + proxyParam: 'anksub', + timeout: 25000, + jitter: 500, + retries: 2 + }, + + { + key: 'anineko-dub', + sourceFile: 'anineko', + label: 'AniNeko (Dub)', + proxyParam: 'ankdub', + timeout: 25000, + jitter: 500, + retries: 2 + }, + + { + key: 'anipm-sub', + sourceFile: 'anipm', + label: 'AniPM (Sub)', + proxyParam: 'apsub', + timeout: 25000, + jitter: 500, + retries: 2, + skipProxy: true, + skipVerify: true, + multiUrl: true, + verifyHeaders: { + Referer: 'https://ani.pm/', + Origin: 'https://ani.pm', + }, + }, + + { + key: 'anipm-dub', + sourceFile: 'anipm', + label: 'AniPM (Dub)', + proxyParam: 'apdub', + timeout: 25000, + jitter: 500, + retries: 2, + skipProxy: true, + skipVerify: true, + multiUrl: true, + verifyHeaders: { + Referer: 'https://ani.pm/', + Origin: 'https://ani.pm', + }, + }, + + { + key: 'flaxmovies', + label: 'FlaxMovies', + sourceFile: 'flaxmovies', + proxyParam: 'fx', + timeout: 20000, + jitter: 500, + retries: 2, + multiUrl: true, + disabled: true, // Temporarily disabled because their site is down, all streams are returning 403's + cdnHeaders: [{ + pattern: /flix2watch\.pro/i, + headers: { + Referer: 'https://flaxmovies.xyz/', + Origin: 'https://flaxmovies.xyz', + }, + },], + }, + + { + key: 'fsharetv', + label: 'FShareTV', + sourceFile: 'fsharetv', + proxyParam: 'fs', + timeout: 25000, + jitter: 600, + retries: 2, + multiUrl: false, + verifyHeaders: { + Accept: 'text/html,application/xhtml+xml,application/xml;q=0.9,/;q=0.8', + 'Accept-Language': 'en-US,en;q=0.9', + Referer: 'https://fsharetv.cc', + }, + }, + + { + key: 'goated', + label: 'Goated', + sourceFile: 'goated', + proxyParam: 'gt', + timeout: 25000, + jitter: 500, + retries: 2, + multiUrl: true, + skipProxy: true, + }, + + { + key: 'fsonic', + label: 'Fsonic', + sourceFile: 'fsonic', + proxyParam: 'fn', + timeout: 35000, + jitter: 600, + retries: 1, + multiUrl: true, + }, + + { + key: 'fsonline', + label: 'FSOnline', + sourceFile: 'fsonline', + proxyParam: 'fo', + timeout: 20000, + retries: 1, + jitter: 0, + multiUrl: true, + skipProxy: true, + }, + + { + key: 'hexa', + label: 'Hexa', + sourceFile: 'hexa', + proxyParam: 'hx', + timeout: 20000, + jitter: 500, + retries: 2, + }, + + { + key: 'kisskh', + label: 'KissKH', + sourceFile: 'kisskh', + proxyParam: 'kk', + timeout: 30000, + jitter: 500, + retries: 1, + }, + + { + key: 'lookmovie', + label: 'LookMovie', + sourceFile: 'lookmovie', + proxyParam: 'lm', + timeout: 20000, + jitter: 500, + retries: 2, + multiUrl: true, + verifyHeaders: { + 'Accept-Language': 'en-US,en;q=0.9', + }, + }, + + { + key: 'mapple', + label: 'Mapple', + sourceFile: 'mapple', + proxyParam: 'mp', + timeout: 15000, + retries: 1, + jitter: 0 + }, + + { + key: 'meowtv', + label: 'MeowTV', + sourceFile: 'meowtv', + proxyParam: 'mt', + timeout: 20000, + jitter: 500, + retries: 2, + multiUrl: true, + skipProxy: true + }, + + { + key: 'nebula', + label: 'Nebula', + sourceFile: 'nebula', + proxyParam: 'nb', + timeout: 25000, + jitter: 500, + retries: 1, + multiUrl: true, + skipProxy: true, + }, + + { + key: 'nekowatch-sub', + sourceFile: 'nekowatch', + label: 'NekoWatch (Sub)', + proxyParam: 'nwsub', + timeout: 30000, + jitter: 500, + retries: 2 + }, + + { + key: 'nekowatch-dub', + sourceFile: 'nekowatch', + label: 'NekoWatch (Dub)', + proxyParam: 'nwdub', + timeout: 30000, + jitter: 500, + retries: 2 + }, + + { + key: 'opstream', + label: 'OpStream', + sourceFile: 'opstream', + proxyParam: 'op', + timeout: 35000, + jitter: 500, + retries: 2, + multiUrl: true, + skipProxy: true, + verifyHeaders: { + Referer: 'https://opstream.fun/', + Origin: 'https://opstream.fun', + }, + }, + + { + key: 'peachify', + label: 'Peachify', + sourceFile: 'peachify', + proxyParam: 'pf', + timeout: 30000, + jitter: 500, + retries: 1, + multiUrl: true + }, + + { + key: 'pengu', + label: 'Pengu', + sourceFile: 'pengu', + proxyParam: 'pg', + timeout: 25000, + jitter: 500, + retries: 1, + multiUrl: true, + skipProxy: true, + disabled: true, // Temporarily disabled because they now require google auth + }, + + { + key: 'purstream', + sourceFile: 'purstream', + label: 'Purstream', + proxyParam: 'ps', + timeout: 20000, + jitter: 500, + retries: 2, + }, + + { + key: 'vidapi', + label: 'VidAPI', + sourceFile: 'vidapi', + proxyParam: 'va', + timeout: 25000, + jitter: 500, + retries: 1, + multiUrl: true + }, + + { + key: 'vidcore', + sourceFile: 'vidcore', + label: 'Vidcore', + proxyParam: 'vc', + timeout: 30000, + jitter: 500, + retries: 2, + sourcesTimeout: 10000, + }, + + { + key: 'videasy', + label: 'Videasy', + sourceFile: 'videasy', + proxyParam: 'vy', + timeout: 40000, + sourcesTimeout: 10000, + jitter: 900, + retries: 3, + multiUrl: true, + verifyHeaders: { + Accept: 'application/json, /; q=0.01', + Referer: 'https://player.videasy.net/', + Origin: 'https://player.videasy.net', + }, + }, + + { + key: 'vidfast', + label: 'Vidfast', + sourceFile: 'vidfast', + proxyParam: 'vf', + timeout: 35000, + jitter: 500, + retries: 1, + }, + + { + key: 'vidlink', + label: 'Vidlink', + sourceFile: 'vidlink', + proxyParam: 'vl', + timeout: 20000, + jitter: 500, + retries: 2, + skipProxy: true, + multiUrl: true, + disabled: true, // Temporarily disabled because their site is down, all streams are returning 403's + }, + + { + key: 'vidnest', + label: 'VidNest', + sourceFile: 'vidnest', + proxyParam: 'vdn', + timeout: 20000, + retries: 1, + jitter: 0, + multiUrl: true, + }, + + { + key: 'vidnest-sub', + label: 'VidNest (Sub)', + sourceFile: 'vidnest', + proxyParam: 'vdn', + timeout: 20000, + retries: 1, + jitter: 0, + multiUrl: true, + skipProxy: true, + }, + + { + key: 'vidnest-dub', + label: 'VidNest (Dub)', + sourceFile: 'vidnest', + proxyParam: 'vdn', + timeout: 20000, + retries: 1, + jitter: 0, + multiUrl: true, + skipProxy: true, + }, + + { + key: 'vidrift', + label: 'VidRift', + sourceFile: 'vidrift', + proxyParam: 'vr', + timeout: 20000, + jitter: 500, + retries: 2, + multiUrl: true, + skipProxy: true + }, + + { + key: 'vidrock', + label: 'VidRock', + sourceFile: 'vidrock', + proxyParam: 'vr', + timeout: 20000, + jitter: 800, + retries: 3, + multiUrl: true, + cdnHeaders: [{ + pattern: /./, + headers: { + Accept: '/', + 'Accept-Language': 'en-US,en;q=0.9', + Referer: 'https://vidrock.ru/', + Origin: 'https://vidrock.ru', + }, + },], + }, + + { + key: 'vidsync', + label: 'VidSync', + sourceFile: 'vidsync', + proxyParam: 'vs', + timeout: 20000, + retries: 2, + multiUrl: true, + disabled: true, // Temporarily disabled due to enc dec issues + }, + + { + key: 'vidup', + label: 'VidUp', + sourceFile: 'vidup', + proxyParam: 'vu', + timeout: 35000, + jitter: 500, + retries: 1, + multiUrl: true + }, + + { + key: 'vidzee', + label: 'VidZee', + sourceFile: 'vidzee', + proxyParam: 'vz', + timeout: 20000, + sourcesTimeout: 10000, + jitter: 400, + retries: 3, + disabled: true, // Temporarily disabled because their site is down, all streams are returning 403's + verifyHeaders: { + Accept: '/', + 'Accept-Language': 'en-US,en;q=0.9', + Referer: 'https://player.vidzee.wtf', + Origin: 'https://player.vidzee.wtf', + }, + }, + + { + key: 'vixsrc', + label: 'VixSrc', + sourceFile: 'vixsrc', + proxyParam: 'vx', + timeout: 35000, + jitter: 0, + retries: 2, + multiUrl: false, + skipProxy: true, + verifyHeaders: { + Accept: 'application/json, text/javascript, /; q=0.01', + 'Accept-Language': 'en-US,en;q=0.9', + Referer: 'https://vixsrc.to/', + Origin: 'https://vixsrc.to', + }, + }, + + { + key: 'xpass', + sourceFile: 'xpass', + label: 'XPass', + proxyParam: 'xp', + timeout: 20000, + jitter: 500, + retries: 2, + skipProxy: true, + }, +]; + +export const HEALTH_PROBE_ID = '155'; +export const SOURCE_MAP = Object.fromEntries(SOURCES.map(s => [s.key, s])); export default SOURCES; \ No newline at end of file diff --git a/src/downloads/downloads.js b/src/downloads/downloads.js index da0d7de..6e512e9 100644 --- a/src/downloads/downloads.js +++ b/src/downloads/downloads.js @@ -1,8 +1,8 @@ -import { getDownloads, getDownloadsTv } from "./sources/trendimovies"; - -export async function fetchDownloads(id, s = null, e = null) { - const res = s != null && e != null - ? await getDownloadsTv(id, s, e) - : await getDownloads(id); - return res; +import { getDownloads, getDownloadsTv } from "./sources/trendimovies"; + +export async function fetchDownloads(id, s = null, e = null) { + const res = s != null && e != null + ? await getDownloadsTv(id, s, e) + : await getDownloads(id); + return res; } \ No newline at end of file diff --git a/src/downloads/sources/trendimovies.js b/src/downloads/sources/trendimovies.js index c796f5f..b9f92d3 100644 --- a/src/downloads/sources/trendimovies.js +++ b/src/downloads/sources/trendimovies.js @@ -1,63 +1,63 @@ -const BASE = "https://trendimovies.com"; - -const HEADERS = { - "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/124.0.0.0 Safari/537.36", - Accept: "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8", - "Accept-Language": "en-US,en;q=0.9", - "Referer": "https://trendimovies.com/", -}; - -async function fetchPage(path) { - const res = await fetch(`${BASE}${path}`, { headers: HEADERS }); - if (!res.ok) throw new Error(`trendimovies ${res.status}`); - return res.text(); -} - -function parseLinks(html) { - const m = html.match(/DownloadSection[^>]*props="([^"]+)"/s) || - html.match(/props="([^"]+)"[^>]*ssr[^>]*client="load"[^>]*opts="[^"]*DownloadSection/s); - if (!m) { - const alt = html.match(/"DownloadSection"/); - if (!alt) return []; - const propsMatch = html.match(/props="({[^"]*DownloadSection[^"]*})"/s); - if (!propsMatch) return []; - return extractLinks(propsMatch[1].replace(/"/g, '"').replace(/'/g, "'")); - } - return extractLinks(m[1].replace(/"/g, '"').replace(/'/g, "'")); -} - -function extractLinks(propsJson) { - try { - const parsed = JSON.parse(propsJson); - const rawLinks = parsed?.links?.[1]; - if (!Array.isArray(rawLinks)) return []; - return rawLinks - .map(item => item?.[1]) - .filter(l => l && typeof l === "object") - .map(l => ({ - url: unwrap(l.url), - quality: unwrap(l.quality) || "HD", - size: unwrap(l.file_size) || null, - type: "mkv", - active: unwrap(l.is_active) !== false, - })) - .filter(l => l.url && l.active); - } catch { - return []; - } -} - -function unwrap(v) { - if (Array.isArray(v) && v.length === 2 && (v[0] === 0 || v[0] === 1)) return v[1]; - return v; -} - -export async function getDownloads(tmdbId) { - const html = await fetchPage(`/movie/${tmdbId}`); - return parseLinks(html); -} - -export async function getDownloadsTv(tmdbId, season, episode) { - const html = await fetchPage(`/tv/${tmdbId}/season/${season}/episode/${episode}`); - return parseLinks(html); +const BASE = "https://trendimovies.com"; + +const HEADERS = { + "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/124.0.0.0 Safari/537.36", + Accept: "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8", + "Accept-Language": "en-US,en;q=0.9", + "Referer": "https://trendimovies.com/", +}; + +async function fetchPage(path) { + const res = await fetch(`${BASE}${path}`, { headers: HEADERS }); + if (!res.ok) throw new Error(`trendimovies ${res.status}`); + return res.text(); +} + +function parseLinks(html) { + const m = html.match(/DownloadSection[^>]*props="([^"]+)"/s) || + html.match(/props="([^"]+)"[^>]*ssr[^>]*client="load"[^>]*opts="[^"]*DownloadSection/s); + if (!m) { + const alt = html.match(/"DownloadSection"/); + if (!alt) return []; + const propsMatch = html.match(/props="({[^"]*DownloadSection[^"]*})"/s); + if (!propsMatch) return []; + return extractLinks(propsMatch[1].replace(/"/g, '"').replace(/'/g, "'")); + } + return extractLinks(m[1].replace(/"/g, '"').replace(/'/g, "'")); +} + +function extractLinks(propsJson) { + try { + const parsed = JSON.parse(propsJson); + const rawLinks = parsed?.links?.[1]; + if (!Array.isArray(rawLinks)) return []; + return rawLinks + .map(item => item?.[1]) + .filter(l => l && typeof l === "object") + .map(l => ({ + url: unwrap(l.url), + quality: unwrap(l.quality) || "HD", + size: unwrap(l.file_size) || null, + type: "mkv", + active: unwrap(l.is_active) !== false, + })) + .filter(l => l.url && l.active); + } catch { + return []; + } +} + +function unwrap(v) { + if (Array.isArray(v) && v.length === 2 && (v[0] === 0 || v[0] === 1)) return v[1]; + return v; +} + +export async function getDownloads(tmdbId) { + const html = await fetchPage(`/movie/${tmdbId}`); + return parseLinks(html); +} + +export async function getDownloadsTv(tmdbId, season, episode) { + const html = await fetchPage(`/tv/${tmdbId}/season/${season}/episode/${episode}`); + return parseLinks(html); } \ No newline at end of file diff --git a/src/health.js b/src/health.js index c9a28e8..d39ae34 100644 --- a/src/health.js +++ b/src/health.js @@ -1,38 +1,38 @@ -import { HEALTH_PROBE_ID } from "./config.js"; - -const withTimeout = (promise, ms) => Promise.race([promise, new Promise(r => setTimeout(() => r(null), ms))]); -async function withRetry(fn, attempts = 2, delay = 300) { - for (let i = 0; i < attempts; i++) { - try { - const result = await fn(); - if (result != null) return result; - } catch (err) { - if (i === attempts - 1) throw err; - await new Promise(r => setTimeout(r, delay + Math.random() * delay * 0.5)); - } - } - return null; -} - -export async function probeSource(tmdbApiKey, cfg, mod) { - const audio = /dub$/.test(cfg.key) ? 'dub' : 'sub'; - const streamArgs = { - id: HEALTH_PROBE_ID, - s: null, - e: null, - clientIP: null, - absoluteBase: null, - audio, - tmdbApiKey, - config: cfg, - }; - - const t = Date.now(); - const result = await withTimeout( - withRetry(() => mod.getStream(streamArgs), cfg.retries, 300), - cfg.timeout - ); - - const firstUrl = result?.url ?? result?.allUrls?.[0]?.url; - return { ok: !!(typeof firstUrl === 'string' && firstUrl.startsWith('http')), ms: Date.now() - t }; +import { HEALTH_PROBE_ID } from "./config.js"; + +const withTimeout = (promise, ms) => Promise.race([promise, new Promise(r => setTimeout(() => r(null), ms))]); +async function withRetry(fn, attempts = 2, delay = 300) { + for (let i = 0; i < attempts; i++) { + try { + const result = await fn(); + if (result != null) return result; + } catch (err) { + if (i === attempts - 1) throw err; + await new Promise(r => setTimeout(r, delay + Math.random() * delay * 0.5)); + } + } + return null; +} + +export async function probeSource(tmdbApiKey, cfg, mod) { + const audio = /dub$/.test(cfg.key) ? 'dub' : 'sub'; + const streamArgs = { + id: HEALTH_PROBE_ID, + s: null, + e: null, + clientIP: null, + absoluteBase: null, + audio, + tmdbApiKey, + config: cfg, + }; + + const t = Date.now(); + const result = await withTimeout( + withRetry(() => mod.getStream(streamArgs), cfg.retries, 300), + cfg.timeout + ); + + const firstUrl = result?.url ?? result?.allUrls?.[0]?.url; + return { ok: !!(typeof firstUrl === 'string' && firstUrl.startsWith('http')), ms: Date.now() - t }; } \ No newline at end of file diff --git a/src/sdk.js b/src/sdk.js index 099e569..015dc5b 100644 --- a/src/sdk.js +++ b/src/sdk.js @@ -1,65 +1,65 @@ -import SOURCES, { SOURCE_MAP } from "./config.js"; -import { fetchDownloads } from "./downloads/downloads.js"; -import { probeSource } from "./health.js"; -import { fetchSubtitles, getSubPathsMovie, getSubPathsTv } from "./subtitles.js"; -import { createStreamArgs } from "./utils/helpers.js"; - -const ALL_SOURCE_MODULES = Object.fromEntries( - await Promise.all(SOURCES.map(async cfg => [cfg.key, await import(`./sources/${cfg.sourceFile}.js`)])) -); - -const SOURCE_MODULES = Object.fromEntries( - Object.entries(ALL_SOURCE_MODULES).filter(([key]) => !SOURCE_MAP[key]?.disabled) -); - -export default class VylaSDK { - constructor({ tmdbApiKey } = {}) { - this.tmdbApiKey = tmdbApiKey; - } - getSources(excludeDisabled = false) { - if (excludeDisabled) { - return SOURCES.filter(cfg => !cfg.disabled); - } - return SOURCES; - } - async probeAllSources() { - const active = SOURCES.filter(cfg => !cfg.disabled); - - const results = await Promise.allSettled( - active.map(async cfg => await probeSource(cfg, SOURCE_MODULES[cfg.key])) - ); - - const sources = Object.fromEntries( - active.map((cfg, i) => [ - cfg.key, - results[i].status === 'fulfilled' ? results[i].value : { ok: false, ms: null }, - ]) - ); - - return sources; - } - async probeSource(key) { - const cfg = SOURCES.find(cfg => cfg.key === key); - if (!cfg) throw new Error(`Source with key "${key}" not found`); - const mod = SOURCE_MODULES[key]; - if (!mod) throw new Error(`Source module for key "${key}" not found`); - return await probeSource(this.tmdbApiKey, cfg, mod); - } - async getStream(key, id, s = null, e = null, clientIP = null) { - const cfg = SOURCES.find(cfg => cfg.key === key); - if (!cfg) throw new Error(`Source with key "${key}" not found`); - const mod = SOURCE_MODULES[key]; - if (!mod) throw new Error(`Source module for key "${key}" not found`); - const streamArgs = await createStreamArgs(cfg, this.tmdbApiKey, id, s, e, clientIP); - return await mod.getStream(streamArgs); - } - async getSubtitles(id, s = null, e = null) { - const paths = s != null && e != null - ? await getSubPathsTv(id, s, e) - : await getSubPathsMovie(id); - return await fetchSubtitles(paths); - } - async getDownloads(id, s = null, e = null) { - return await fetchDownloads(id, s, e); - } +import SOURCES, { SOURCE_MAP } from "./config.js"; +import { fetchDownloads } from "./downloads/downloads.js"; +import { probeSource } from "./health.js"; +import { fetchSubtitles, getSubPathsMovie, getSubPathsTv } from "./subtitles.js"; +import { createStreamArgs } from "./utils/helpers.js"; + +const ALL_SOURCE_MODULES = Object.fromEntries( + await Promise.all(SOURCES.map(async cfg => [cfg.key, await import(`./sources/${cfg.sourceFile}.js`)])) +); + +const SOURCE_MODULES = Object.fromEntries( + Object.entries(ALL_SOURCE_MODULES).filter(([key]) => !SOURCE_MAP[key]?.disabled) +); + +export default class VylaSDK { + constructor({ tmdbApiKey } = {}) { + this.tmdbApiKey = tmdbApiKey; + } + getSources(excludeDisabled = false) { + if (excludeDisabled) { + return SOURCES.filter(cfg => !cfg.disabled); + } + return SOURCES; + } + async probeAllSources() { + const active = SOURCES.filter(cfg => !cfg.disabled); + + const results = await Promise.allSettled( + active.map(async cfg => await probeSource(cfg, SOURCE_MODULES[cfg.key])) + ); + + const sources = Object.fromEntries( + active.map((cfg, i) => [ + cfg.key, + results[i].status === 'fulfilled' ? results[i].value : { ok: false, ms: null }, + ]) + ); + + return sources; + } + async probeSource(key) { + const cfg = SOURCES.find(cfg => cfg.key === key); + if (!cfg) throw new Error(`Source with key "${key}" not found`); + const mod = SOURCE_MODULES[key]; + if (!mod) throw new Error(`Source module for key "${key}" not found`); + return await probeSource(this.tmdbApiKey, cfg, mod); + } + async getStream(key, id, s = null, e = null, clientIP = null) { + const cfg = SOURCES.find(cfg => cfg.key === key); + if (!cfg) throw new Error(`Source with key "${key}" not found`); + const mod = SOURCE_MODULES[key]; + if (!mod) throw new Error(`Source module for key "${key}" not found`); + const streamArgs = await createStreamArgs(cfg, this.tmdbApiKey, id, s, e, clientIP); + return await mod.getStream(streamArgs); + } + async getSubtitles(id, s = null, e = null) { + const paths = s != null && e != null + ? await getSubPathsTv(id, s, e) + : await getSubPathsMovie(id); + return await fetchSubtitles(paths); + } + async getDownloads(id, s = null, e = null) { + return await fetchDownloads(id, s, e); + } } \ No newline at end of file diff --git a/src/sources/123anime.js b/src/sources/123anime.js index a0fa6dd..6bafdb8 100644 --- a/src/sources/123anime.js +++ b/src/sources/123anime.js @@ -1,57 +1,57 @@ -import { getTmdbInfo, fetchJson, USER_AGENT } from '../utils/helpers.js'; - -async function resolveSlug(id, s, e, info) { - const titles = info?.titles || []; - const keywords = []; - for (const title of titles) { - const t = title.toLowerCase().replace(/[^a-z0-9\s]/g, ' ').replace(/\s+/g, ' ').trim(); - if (!keywords.includes(t)) keywords.push(t); - const words = title.split(/[\s:]+/).filter(w => w.length > 2); - if (words.length >= 2) { - const short = words.slice(0, 3).join(' ').toLowerCase(); - if (!keywords.includes(short)) keywords.push(short); - } - } - const slugCandidates = []; - for (const keyword of keywords) { - try { - const data = await fetchJson(`https://123animehub.cc/ajax/film/search?keyword=${encodeURIComponent(keyword)}&_=${Date.now()}`, { headers: { 'X-Requested-With': 'XMLHttpRequest', 'Referer': 'https://123animehub.cc', 'Accept': 'application/json', 'User-Agent': USER_AGENT }, signal: AbortSignal.timeout(8000) }); - let html = data.html || '', idx = 0; - while ((idx = html.indexOf('href="/anime/', idx)) !== -1) { - const start = idx + 13; - const end = html.indexOf('"', start); - const slug = html.slice(start, end); - if (!slugCandidates.includes(slug)) slugCandidates.push(slug); - idx = end; - } - } catch { } - if (slugCandidates.length) break; - } - for (const slug of slugCandidates) { - try { - const data = await fetchJson(`https://123animehub.cc/ajax/episode/info?epr=${encodeURIComponent(s ? `${slug}/${s}/${e}` : `${slug}/1`)}&ts=1&_=${Date.now()}`, { headers: { 'Referer': `https://123animehub.cc/anime/${slug}`, 'X-Requested-With': 'XMLHttpRequest', 'Accept': 'application/json, text/javascript, */*; q=0.01', 'User-Agent': USER_AGENT }, signal: AbortSignal.timeout(10000) }); - if (data?.target) return data.target; - } catch { } - } - return null; -} - -export async function getStream({ id, s, e }) { - if (!s) return null; - const info = await getTmdbInfo(id, 'tv', s); - if (!info.isAnime) return null; - const target = await resolveSlug(id, s, e, info); - if (!target) return null; - const embedMatch = target.match(/\/embed-[^/]+\/([A-Za-z0-9+/=]+)$/); - if (!embedMatch) return null; - const origin = new URL(target).origin; - try { - const embedRes = await fetch(target, { headers: { 'User-Agent': USER_AGENT }, signal: AbortSignal.timeout(10000) }); - if (!embedRes.ok) return null; - const setCookie = embedRes.headers.get('set-cookie'); - const data = await fetchJson(`${origin}/hs/getSources?id=${embedMatch[1]}`, { headers: { 'Referer': target, 'Accept': '*/*', 'User-Agent': USER_AGENT, ...(setCookie ? { 'Cookie': setCookie.split(';')[0].trim() } : {}) }, signal: AbortSignal.timeout(10000) }); - const src = typeof data.sources === 'string' && data.sources.length ? data.sources : (Array.isArray(data.sources) && data.sources.length ? (data.sources[0].file || data.sources[0].src || data.sources[0].url) : null); - if (src) return { url: src, headers: { 'Referer': 'https://play2.echovideo.ru/', 'Origin': 'https://play2.echovideo.ru' } }; - } catch { } - return null; +import { getTmdbInfo, fetchJson, USER_AGENT } from '../utils/helpers.js'; + +async function resolveSlug(id, s, e, info) { + const titles = info?.titles || []; + const keywords = []; + for (const title of titles) { + const t = title.toLowerCase().replace(/[^a-z0-9\s]/g, ' ').replace(/\s+/g, ' ').trim(); + if (!keywords.includes(t)) keywords.push(t); + const words = title.split(/[\s:]+/).filter(w => w.length > 2); + if (words.length >= 2) { + const short = words.slice(0, 3).join(' ').toLowerCase(); + if (!keywords.includes(short)) keywords.push(short); + } + } + const slugCandidates = []; + for (const keyword of keywords) { + try { + const data = await fetchJson(`https://123animehub.cc/ajax/film/search?keyword=${encodeURIComponent(keyword)}&_=${Date.now()}`, { headers: { 'X-Requested-With': 'XMLHttpRequest', 'Referer': 'https://123animehub.cc', 'Accept': 'application/json', 'User-Agent': USER_AGENT }, signal: AbortSignal.timeout(8000) }); + let html = data.html || '', idx = 0; + while ((idx = html.indexOf('href="/anime/', idx)) !== -1) { + const start = idx + 13; + const end = html.indexOf('"', start); + const slug = html.slice(start, end); + if (!slugCandidates.includes(slug)) slugCandidates.push(slug); + idx = end; + } + } catch { } + if (slugCandidates.length) break; + } + for (const slug of slugCandidates) { + try { + const data = await fetchJson(`https://123animehub.cc/ajax/episode/info?epr=${encodeURIComponent(s ? `${slug}/${s}/${e}` : `${slug}/1`)}&ts=1&_=${Date.now()}`, { headers: { 'Referer': `https://123animehub.cc/anime/${slug}`, 'X-Requested-With': 'XMLHttpRequest', 'Accept': 'application/json, text/javascript, */*; q=0.01', 'User-Agent': USER_AGENT }, signal: AbortSignal.timeout(10000) }); + if (data?.target) return data.target; + } catch { } + } + return null; +} + +export async function getStream({ id, s, e }) { + if (!s) return null; + const info = await getTmdbInfo(id, 'tv', s); + if (!info.isAnime) return null; + const target = await resolveSlug(id, s, e, info); + if (!target) return null; + const embedMatch = target.match(/\/embed-[^/]+\/([A-Za-z0-9+/=]+)$/); + if (!embedMatch) return null; + const origin = new URL(target).origin; + try { + const embedRes = await fetch(target, { headers: { 'User-Agent': USER_AGENT }, signal: AbortSignal.timeout(10000) }); + if (!embedRes.ok) return null; + const setCookie = embedRes.headers.get('set-cookie'); + const data = await fetchJson(`${origin}/hs/getSources?id=${embedMatch[1]}`, { headers: { 'Referer': target, 'Accept': '*/*', 'User-Agent': USER_AGENT, ...(setCookie ? { 'Cookie': setCookie.split(';')[0].trim() } : {}) }, signal: AbortSignal.timeout(10000) }); + const src = typeof data.sources === 'string' && data.sources.length ? data.sources : (Array.isArray(data.sources) && data.sources.length ? (data.sources[0].file || data.sources[0].src || data.sources[0].url) : null); + if (src) return { url: src, headers: { 'Referer': 'https://play2.echovideo.ru/', 'Origin': 'https://play2.echovideo.ru' } }; + } catch { } + return null; } \ No newline at end of file diff --git a/src/sources/1embed.js b/src/sources/1embed.js index a467229..ef35f4c 100644 --- a/src/sources/1embed.js +++ b/src/sources/1embed.js @@ -1,92 +1,92 @@ -import { USER_AGENT } from '../utils/helpers.js'; - -const BASE_URL = "https://1embed.cc"; - -const PROVIDERS = [ - { id: "sdev", name: "1Embed - SDev" }, - { id: "xpa", name: "1Embed - XPass" }, - { id: "vnes", name: "1Embed - VidNest" }, - { id: "pro", name: "1Embed - Pro" }, - { id: "pur", name: "1Embed - Purstream" }, - { id: "czo", name: "1Embed - Cinezo" }, - { id: "fas", name: "1Embed - VidFast" } -]; - -let cachedToken = null; -let tokenExpiresAt = 0; - -async function getToken() { - const now = Math.floor(Date.now() / 1000); - if (cachedToken && tokenExpiresAt > now + 10) return cachedToken; - try { - const res = await fetch(`${BASE_URL}/api/token`, { headers: { "Referer": `${BASE_URL}/`, "User-Agent": USER_AGENT, "Accept": "application/json" }, signal: AbortSignal.timeout(10000) }); - if (!res.ok) return null; - const data = await res.json(); - cachedToken = data.token; - tokenExpiresAt = data.expiresAt; - return cachedToken; - } catch { return null; } -} - -async function fetchProviderStream(provider, type, id, s, e, token) { - try { - const referer = type === "movie" ? `${BASE_URL}/embed/movie/${id}` : `${BASE_URL}/embed/tv/${id}/${s}/${e}`; - const payload = { type, id: String(id), provider: provider.id }; - if (type === "tv") { payload.season = Number(s); payload.episode = Number(e); } - const res = await fetch(`${BASE_URL}/api/sources`, { - method: "POST", - headers: { "User-Agent": USER_AGENT, "Referer": referer, "Origin": BASE_URL, "Accept": "application/json", "Content-Type": "application/json", "x-bcine-key": token, "X-Requested-With": "XMLHttpRequest" }, - body: JSON.stringify(payload), - signal: AbortSignal.timeout(15000) - }); - if (!res.ok) return null; - const data = await res.json(); - - let rawSources = []; - if (Array.isArray(data.servers)) rawSources.push(...data.servers); - if (data.providerResults?.[provider.id]?.sources) rawSources.push(...data.providerResults[provider.id].sources); - if (data.providerResults?.[provider.id] && Array.isArray(data.providerResults[provider.id])) rawSources.push(...data.providerResults[provider.id]); - - if (!rawSources.length) return null; - const results = []; - for (const src of rawSources) { - if (typeof src !== 'object' || !src) continue; - let streamUrl = src.url || src.file || src.link; - if (typeof streamUrl !== 'string') continue; - if (streamUrl.startsWith('/')) streamUrl = `${BASE_URL}${streamUrl}`; - const isWorker = streamUrl.includes('omena-puu') || streamUrl.includes('nocach') || streamUrl.includes('?p='); - const isHls = src.type === 'hls' || streamUrl.includes('m3u8') || isWorker; - if (isHls && !streamUrl.includes('m3u8')) streamUrl += streamUrl.includes('?') ? '&format=.m3u8' : '?format=.m3u8'; - const srcHeaders = (src.headers && typeof src.headers === 'object') ? src.headers : {}; - results.push({ - url: streamUrl, - server: provider.name, - quality: src.quality || src.label || src.title || "Auto", - type: isHls ? "hls" : "mp4", - headers: { "User-Agent": USER_AGENT, "Referer": referer, "Origin": BASE_URL, ...srcHeaders }, - }); - } - return results; - } catch { - return null; - } -} - -export async function getStream(args) { - const { id, s, e, server } = args; - const type = s != null && e != null ? "tv" : "movie"; - const token = await getToken(); - if (!token) return null; - let targets = PROVIDERS; - if (server && server !== 'all') { - const cleanName = server.replace('1Embed - ', '').toLowerCase(); - targets = PROVIDERS.filter(p => p.id === cleanName || p.name.toLowerCase().includes(cleanName)); - if (!targets.length) targets = PROVIDERS; - } - const settled = await Promise.allSettled(targets.map(p => fetchProviderStream(p, type, id, s, e, token))); - const allUrls = []; - for (const r of settled) if (r.status === 'fulfilled' && r.value) allUrls.push(...r.value); - return allUrls.length ? { allUrls } : null; -} - +import { USER_AGENT } from '../utils/helpers.js'; + +const BASE_URL = "https://1embed.cc"; + +const PROVIDERS = [ + { id: "sdev", name: "1Embed - SDev" }, + { id: "xpa", name: "1Embed - XPass" }, + { id: "vnes", name: "1Embed - VidNest" }, + { id: "pro", name: "1Embed - Pro" }, + { id: "pur", name: "1Embed - Purstream" }, + { id: "czo", name: "1Embed - Cinezo" }, + { id: "fas", name: "1Embed - VidFast" } +]; + +let cachedToken = null; +let tokenExpiresAt = 0; + +async function getToken() { + const now = Math.floor(Date.now() / 1000); + if (cachedToken && tokenExpiresAt > now + 10) return cachedToken; + try { + const res = await fetch(`${BASE_URL}/api/token`, { headers: { "Referer": `${BASE_URL}/`, "User-Agent": USER_AGENT, "Accept": "application/json" }, signal: AbortSignal.timeout(10000) }); + if (!res.ok) return null; + const data = await res.json(); + cachedToken = data.token; + tokenExpiresAt = data.expiresAt; + return cachedToken; + } catch { return null; } +} + +async function fetchProviderStream(provider, type, id, s, e, token) { + try { + const referer = type === "movie" ? `${BASE_URL}/embed/movie/${id}` : `${BASE_URL}/embed/tv/${id}/${s}/${e}`; + const payload = { type, id: String(id), provider: provider.id }; + if (type === "tv") { payload.season = Number(s); payload.episode = Number(e); } + const res = await fetch(`${BASE_URL}/api/sources`, { + method: "POST", + headers: { "User-Agent": USER_AGENT, "Referer": referer, "Origin": BASE_URL, "Accept": "application/json", "Content-Type": "application/json", "x-bcine-key": token, "X-Requested-With": "XMLHttpRequest" }, + body: JSON.stringify(payload), + signal: AbortSignal.timeout(15000) + }); + if (!res.ok) return null; + const data = await res.json(); + + let rawSources = []; + if (Array.isArray(data.servers)) rawSources.push(...data.servers); + if (data.providerResults?.[provider.id]?.sources) rawSources.push(...data.providerResults[provider.id].sources); + if (data.providerResults?.[provider.id] && Array.isArray(data.providerResults[provider.id])) rawSources.push(...data.providerResults[provider.id]); + + if (!rawSources.length) return null; + const results = []; + for (const src of rawSources) { + if (typeof src !== 'object' || !src) continue; + let streamUrl = src.url || src.file || src.link; + if (typeof streamUrl !== 'string') continue; + if (streamUrl.startsWith('/')) streamUrl = `${BASE_URL}${streamUrl}`; + const isWorker = streamUrl.includes('omena-puu') || streamUrl.includes('nocach') || streamUrl.includes('?p='); + const isHls = src.type === 'hls' || streamUrl.includes('m3u8') || isWorker; + if (isHls && !streamUrl.includes('m3u8')) streamUrl += streamUrl.includes('?') ? '&format=.m3u8' : '?format=.m3u8'; + const srcHeaders = (src.headers && typeof src.headers === 'object') ? src.headers : {}; + results.push({ + url: streamUrl, + server: provider.name, + quality: src.quality || src.label || src.title || "Auto", + type: isHls ? "hls" : "mp4", + headers: { "User-Agent": USER_AGENT, "Referer": referer, "Origin": BASE_URL, ...srcHeaders }, + }); + } + return results; + } catch { + return null; + } +} + +export async function getStream(args) { + const { id, s, e, server } = args; + const type = s != null && e != null ? "tv" : "movie"; + const token = await getToken(); + if (!token) return null; + let targets = PROVIDERS; + if (server && server !== 'all') { + const cleanName = server.replace('1Embed - ', '').toLowerCase(); + targets = PROVIDERS.filter(p => p.id === cleanName || p.name.toLowerCase().includes(cleanName)); + if (!targets.length) targets = PROVIDERS; + } + const settled = await Promise.allSettled(targets.map(p => fetchProviderStream(p, type, id, s, e, token))); + const allUrls = []; + for (const r of settled) if (r.status === 'fulfilled' && r.value) allUrls.push(...r.value); + return allUrls.length ? { allUrls } : null; +} + export async function getSources() { return PROVIDERS.map(p => p.name); } \ No newline at end of file diff --git a/src/sources/anihq.js b/src/sources/anihq.js index 45a69f3..e2c148b 100644 --- a/src/sources/anihq.js +++ b/src/sources/anihq.js @@ -1,112 +1,112 @@ -import { getTmdbInfo, USER_AGENT } from '../utils/helpers.js'; - -async function extractVoe(voeUrl) { - try { - const res = await fetch(voeUrl, { - headers: { - 'User-Agent': USER_AGENT, - 'Referer': 'https://anihq.cc/' - } - }); - - const mirrorUrl = res.url; - const html = await res.text(); - - const scriptMatch = html.match(/