From 161846afc42cb9acd61c12c5cf04e53d6216ae3a Mon Sep 17 00:00:00 2001 From: Issam Hakimi aka Killix Date: Fri, 14 Apr 2017 20:36:34 -0400 Subject: [PATCH 1/4] Move the licence to Apache --- LICENCE.md | 668 +-------------------------------------------------- package.json | 15 +- 2 files changed, 22 insertions(+), 661 deletions(-) diff --git a/LICENCE.md b/LICENCE.md index 7aab016..661eb24 100644 --- a/LICENCE.md +++ b/LICENCE.md @@ -1,660 +1,16 @@ -### GNU AFFERO GENERAL PUBLIC LICENSE +This software is licensed under the Apache 2 license, quoted below. -Version 3, 19 November 2007 +Copyright 2009 Twitter, Inc. +Copyright 2009 Robey Pointer -Copyright (C) 2007 Free Software Foundation, Inc. - +Licensed under the Apache License, Version 2.0 (the "License"); you may not +use this file except in compliance with the License. You may obtain a copy of +the License at -Everyone is permitted to copy and distribute verbatim copies of this -license document, but changing it is not allowed. + http://www.apache.org/licenses/LICENSE-2.0 -### Preamble - -The GNU Affero General Public License is a free, copyleft license for -software and other kinds of works, specifically designed to ensure -cooperation with the community in the case of network server software. - -The licenses for most software and other practical works are designed -to take away your freedom to share and change the works. By contrast, -our General Public Licenses are intended to guarantee your freedom to -share and change all versions of a program--to make sure it remains -free software for all its users. - -When we speak of free software, we are referring to freedom, not -price. Our General Public Licenses are designed to make sure that you -have the freedom to distribute copies of free software (and charge for -them if you wish), that you receive source code or can get it if you -want it, that you can change the software or use pieces of it in new -free programs, and that you know you can do these things. - -Developers that use our General Public Licenses protect your rights -with two steps: (1) assert copyright on the software, and (2) offer -you this License which gives you legal permission to copy, distribute -and/or modify the software. - -A secondary benefit of defending all users' freedom is that -improvements made in alternate versions of the program, if they -receive widespread use, become available for other developers to -incorporate. Many developers of free software are heartened and -encouraged by the resulting cooperation. However, in the case of -software used on network servers, this result may fail to come about. -The GNU General Public License permits making a modified version and -letting the public access it on a server without ever releasing its -source code to the public. - -The GNU Affero General Public License is designed specifically to -ensure that, in such cases, the modified source code becomes available -to the community. It requires the operator of a network server to -provide the source code of the modified version running there to the -users of that server. Therefore, public use of a modified version, on -a publicly accessible server, gives the public access to the source -code of the modified version. - -An older license, called the Affero General Public License and -published by Affero, was designed to accomplish similar goals. This is -a different license, not a version of the Affero GPL, but Affero has -released a new version of the Affero GPL which permits relicensing -under this license. - -The precise terms and conditions for copying, distribution and -modification follow. - -### TERMS AND CONDITIONS - -#### 0. Definitions. - -"This License" refers to version 3 of the GNU Affero General Public -License. - -"Copyright" also means copyright-like laws that apply to other kinds -of works, such as semiconductor masks. - -"The Program" refers to any copyrightable work licensed under this -License. Each licensee is addressed as "you". "Licensees" and -"recipients" may be individuals or organizations. - -To "modify" a work means to copy from or adapt all or part of the work -in a fashion requiring copyright permission, other than the making of -an exact copy. The resulting work is called a "modified version" of -the earlier work or a work "based on" the earlier work. - -A "covered work" means either the unmodified Program or a work based -on the Program. - -To "propagate" a work means to do anything with it that, without -permission, would make you directly or secondarily liable for -infringement under applicable copyright law, except executing it on a -computer or modifying a private copy. Propagation includes copying, -distribution (with or without modification), making available to the -public, and in some countries other activities as well. - -To "convey" a work means any kind of propagation that enables other -parties to make or receive copies. Mere interaction with a user -through a computer network, with no transfer of a copy, is not -conveying. - -An interactive user interface displays "Appropriate Legal Notices" to -the extent that it includes a convenient and prominently visible -feature that (1) displays an appropriate copyright notice, and (2) -tells the user that there is no warranty for the work (except to the -extent that warranties are provided), that licensees may convey the -work under this License, and how to view a copy of this License. If -the interface presents a list of user commands or options, such as a -menu, a prominent item in the list meets this criterion. - -#### 1. Source Code. - -The "source code" for a work means the preferred form of the work for -making modifications to it. "Object code" means any non-source form of -a work. - -A "Standard Interface" means an interface that either is an official -standard defined by a recognized standards body, or, in the case of -interfaces specified for a particular programming language, one that -is widely used among developers working in that language. - -The "System Libraries" of an executable work include anything, other -than the work as a whole, that (a) is included in the normal form of -packaging a Major Component, but which is not part of that Major -Component, and (b) serves only to enable use of the work with that -Major Component, or to implement a Standard Interface for which an -implementation is available to the public in source code form. A -"Major Component", in this context, means a major essential component -(kernel, window system, and so on) of the specific operating system -(if any) on which the executable work runs, or a compiler used to -produce the work, or an object code interpreter used to run it. - -The "Corresponding Source" for a work in object code form means all -the source code needed to generate, install, and (for an executable -work) run the object code and to modify the work, including scripts to -control those activities. However, it does not include the work's -System Libraries, or general-purpose tools or generally available free -programs which are used unmodified in performing those activities but -which are not part of the work. For example, Corresponding Source -includes interface definition files associated with source files for -the work, and the source code for shared libraries and dynamically -linked subprograms that the work is specifically designed to require, -such as by intimate data communication or control flow between those -subprograms and other parts of the work. - -The Corresponding Source need not include anything that users can -regenerate automatically from other parts of the Corresponding Source. - -The Corresponding Source for a work in source code form is that same -work. - -#### 2. Basic Permissions. - -All rights granted under this License are granted for the term of -copyright on the Program, and are irrevocable provided the stated -conditions are met. This License explicitly affirms your unlimited -permission to run the unmodified Program. The output from running a -covered work is covered by this License only if the output, given its -content, constitutes a covered work. This License acknowledges your -rights of fair use or other equivalent, as provided by copyright law. - -You may make, run and propagate covered works that you do not convey, -without conditions so long as your license otherwise remains in force. -You may convey covered works to others for the sole purpose of having -them make modifications exclusively for you, or provide you with -facilities for running those works, provided that you comply with the -terms of this License in conveying all material for which you do not -control copyright. Those thus making or running the covered works for -you must do so exclusively on your behalf, under your direction and -control, on terms that prohibit them from making any copies of your -copyrighted material outside their relationship with you. - -Conveying under any other circumstances is permitted solely under the -conditions stated below. Sublicensing is not allowed; section 10 makes -it unnecessary. - -#### 3. Protecting Users' Legal Rights From Anti-Circumvention Law. - -No covered work shall be deemed part of an effective technological -measure under any applicable law fulfilling obligations under article -11 of the WIPO copyright treaty adopted on 20 December 1996, or -similar laws prohibiting or restricting circumvention of such -measures. - -When you convey a covered work, you waive any legal power to forbid -circumvention of technological measures to the extent such -circumvention is effected by exercising rights under this License with -respect to the covered work, and you disclaim any intention to limit -operation or modification of the work as a means of enforcing, against -the work's users, your or third parties' legal rights to forbid -circumvention of technological measures. - -#### 4. Conveying Verbatim Copies. - -You may convey verbatim copies of the Program's source code as you -receive it, in any medium, provided that you conspicuously and -appropriately publish on each copy an appropriate copyright notice; -keep intact all notices stating that this License and any -non-permissive terms added in accord with section 7 apply to the code; -keep intact all notices of the absence of any warranty; and give all -recipients a copy of this License along with the Program. - -You may charge any price or no price for each copy that you convey, -and you may offer support or warranty protection for a fee. - -#### 5. Conveying Modified Source Versions. - -You may convey a work based on the Program, or the modifications to -produce it from the Program, in the form of source code under the -terms of section 4, provided that you also meet all of these -conditions: - -- a) The work must carry prominent notices stating that you modified - it, and giving a relevant date. -- b) The work must carry prominent notices stating that it is - released under this License and any conditions added under - section 7. This requirement modifies the requirement in section 4 - to "keep intact all notices". -- c) You must license the entire work, as a whole, under this - License to anyone who comes into possession of a copy. This - License will therefore apply, along with any applicable section 7 - additional terms, to the whole of the work, and all its parts, - regardless of how they are packaged. This License gives no - permission to license the work in any other way, but it does not - invalidate such permission if you have separately received it. -- d) If the work has interactive user interfaces, each must display - Appropriate Legal Notices; however, if the Program has interactive - interfaces that do not display Appropriate Legal Notices, your - work need not make them do so. - -A compilation of a covered work with other separate and independent -works, which are not by their nature extensions of the covered work, -and which are not combined with it such as to form a larger program, -in or on a volume of a storage or distribution medium, is called an -"aggregate" if the compilation and its resulting copyright are not -used to limit the access or legal rights of the compilation's users -beyond what the individual works permit. Inclusion of a covered work -in an aggregate does not cause this License to apply to the other -parts of the aggregate. - -#### 6. Conveying Non-Source Forms. - -You may convey a covered work in object code form under the terms of -sections 4 and 5, provided that you also convey the machine-readable -Corresponding Source under the terms of this License, in one of these -ways: - -- a) Convey the object code in, or embodied in, a physical product - (including a physical distribution medium), accompanied by the - Corresponding Source fixed on a durable physical medium - customarily used for software interchange. -- b) Convey the object code in, or embodied in, a physical product - (including a physical distribution medium), accompanied by a - written offer, valid for at least three years and valid for as - long as you offer spare parts or customer support for that product - model, to give anyone who possesses the object code either (1) a - copy of the Corresponding Source for all the software in the - product that is covered by this License, on a durable physical - medium customarily used for software interchange, for a price no - more than your reasonable cost of physically performing this - conveying of source, or (2) access to copy the Corresponding - Source from a network server at no charge. -- c) Convey individual copies of the object code with a copy of the - written offer to provide the Corresponding Source. This - alternative is allowed only occasionally and noncommercially, and - only if you received the object code with such an offer, in accord - with subsection 6b. -- d) Convey the object code by offering access from a designated - place (gratis or for a charge), and offer equivalent access to the - Corresponding Source in the same way through the same place at no - further charge. You need not require recipients to copy the - Corresponding Source along with the object code. If the place to - copy the object code is a network server, the Corresponding Source - may be on a different server (operated by you or a third party) - that supports equivalent copying facilities, provided you maintain - clear directions next to the object code saying where to find the - Corresponding Source. Regardless of what server hosts the - Corresponding Source, you remain obligated to ensure that it is - available for as long as needed to satisfy these requirements. -- e) Convey the object code using peer-to-peer transmission, - provided you inform other peers where the object code and - Corresponding Source of the work are being offered to the general - public at no charge under subsection 6d. - -A separable portion of the object code, whose source code is excluded -from the Corresponding Source as a System Library, need not be -included in conveying the object code work. - -A "User Product" is either (1) a "consumer product", which means any -tangible personal property which is normally used for personal, -family, or household purposes, or (2) anything designed or sold for -incorporation into a dwelling. In determining whether a product is a -consumer product, doubtful cases shall be resolved in favor of -coverage. For a particular product received by a particular user, -"normally used" refers to a typical or common use of that class of -product, regardless of the status of the particular user or of the way -in which the particular user actually uses, or expects or is expected -to use, the product. A product is a consumer product regardless of -whether the product has substantial commercial, industrial or -non-consumer uses, unless such uses represent the only significant -mode of use of the product. - -"Installation Information" for a User Product means any methods, -procedures, authorization keys, or other information required to -install and execute modified versions of a covered work in that User -Product from a modified version of its Corresponding Source. The -information must suffice to ensure that the continued functioning of -the modified object code is in no case prevented or interfered with -solely because modification has been made. - -If you convey an object code work under this section in, or with, or -specifically for use in, a User Product, and the conveying occurs as -part of a transaction in which the right of possession and use of the -User Product is transferred to the recipient in perpetuity or for a -fixed term (regardless of how the transaction is characterized), the -Corresponding Source conveyed under this section must be accompanied -by the Installation Information. But this requirement does not apply -if neither you nor any third party retains the ability to install -modified object code on the User Product (for example, the work has -been installed in ROM). - -The requirement to provide Installation Information does not include a -requirement to continue to provide support service, warranty, or -updates for a work that has been modified or installed by the -recipient, or for the User Product in which it has been modified or -installed. Access to a network may be denied when the modification -itself materially and adversely affects the operation of the network -or violates the rules and protocols for communication across the -network. - -Corresponding Source conveyed, and Installation Information provided, -in accord with this section must be in a format that is publicly -documented (and with an implementation available to the public in -source code form), and must require no special password or key for -unpacking, reading or copying. - -#### 7. Additional Terms. - -"Additional permissions" are terms that supplement the terms of this -License by making exceptions from one or more of its conditions. -Additional permissions that are applicable to the entire Program shall -be treated as though they were included in this License, to the extent -that they are valid under applicable law. If additional permissions -apply only to part of the Program, that part may be used separately -under those permissions, but the entire Program remains governed by -this License without regard to the additional permissions. - -When you convey a copy of a covered work, you may at your option -remove any additional permissions from that copy, or from any part of -it. (Additional permissions may be written to require their own -removal in certain cases when you modify the work.) You may place -additional permissions on material, added by you to a covered work, -for which you have or can give appropriate copyright permission. - -Notwithstanding any other provision of this License, for material you -add to a covered work, you may (if authorized by the copyright holders -of that material) supplement the terms of this License with terms: - -- a) Disclaiming warranty or limiting liability differently from the - terms of sections 15 and 16 of this License; or -- b) Requiring preservation of specified reasonable legal notices or - author attributions in that material or in the Appropriate Legal - Notices displayed by works containing it; or -- c) Prohibiting misrepresentation of the origin of that material, - or requiring that modified versions of such material be marked in - reasonable ways as different from the original version; or -- d) Limiting the use for publicity purposes of names of licensors - or authors of the material; or -- e) Declining to grant rights under trademark law for use of some - trade names, trademarks, or service marks; or -- f) Requiring indemnification of licensors and authors of that - material by anyone who conveys the material (or modified versions - of it) with contractual assumptions of liability to the recipient, - for any liability that these contractual assumptions directly - impose on those licensors and authors. - -All other non-permissive additional terms are considered "further -restrictions" within the meaning of section 10. If the Program as you -received it, or any part of it, contains a notice stating that it is -governed by this License along with a term that is a further -restriction, you may remove that term. If a license document contains -a further restriction but permits relicensing or conveying under this -License, you may add to a covered work material governed by the terms -of that license document, provided that the further restriction does -not survive such relicensing or conveying. - -If you add terms to a covered work in accord with this section, you -must place, in the relevant source files, a statement of the -additional terms that apply to those files, or a notice indicating -where to find the applicable terms. - -Additional terms, permissive or non-permissive, may be stated in the -form of a separately written license, or stated as exceptions; the -above requirements apply either way. - -#### 8. Termination. - -You may not propagate or modify a covered work except as expressly -provided under this License. Any attempt otherwise to propagate or -modify it is void, and will automatically terminate your rights under -this License (including any patent licenses granted under the third -paragraph of section 11). - -However, if you cease all violation of this License, then your license -from a particular copyright holder is reinstated (a) provisionally, -unless and until the copyright holder explicitly and finally -terminates your license, and (b) permanently, if the copyright holder -fails to notify you of the violation by some reasonable means prior to -60 days after the cessation. - -Moreover, your license from a particular copyright holder is -reinstated permanently if the copyright holder notifies you of the -violation by some reasonable means, this is the first time you have -received notice of violation of this License (for any work) from that -copyright holder, and you cure the violation prior to 30 days after -your receipt of the notice. - -Termination of your rights under this section does not terminate the -licenses of parties who have received copies or rights from you under -this License. If your rights have been terminated and not permanently -reinstated, you do not qualify to receive new licenses for the same -material under section 10. - -#### 9. Acceptance Not Required for Having Copies. - -You are not required to accept this License in order to receive or run -a copy of the Program. Ancillary propagation of a covered work -occurring solely as a consequence of using peer-to-peer transmission -to receive a copy likewise does not require acceptance. However, -nothing other than this License grants you permission to propagate or -modify any covered work. These actions infringe copyright if you do -not accept this License. Therefore, by modifying or propagating a -covered work, you indicate your acceptance of this License to do so. - -#### 10. Automatic Licensing of Downstream Recipients. - -Each time you convey a covered work, the recipient automatically -receives a license from the original licensors, to run, modify and -propagate that work, subject to this License. You are not responsible -for enforcing compliance by third parties with this License. - -An "entity transaction" is a transaction transferring control of an -organization, or substantially all assets of one, or subdividing an -organization, or merging organizations. If propagation of a covered -work results from an entity transaction, each party to that -transaction who receives a copy of the work also receives whatever -licenses to the work the party's predecessor in interest had or could -give under the previous paragraph, plus a right to possession of the -Corresponding Source of the work from the predecessor in interest, if -the predecessor has it or can get it with reasonable efforts. - -You may not impose any further restrictions on the exercise of the -rights granted or affirmed under this License. For example, you may -not impose a license fee, royalty, or other charge for exercise of -rights granted under this License, and you may not initiate litigation -(including a cross-claim or counterclaim in a lawsuit) alleging that -any patent claim is infringed by making, using, selling, offering for -sale, or importing the Program or any portion of it. - -#### 11. Patents. - -A "contributor" is a copyright holder who authorizes use under this -License of the Program or a work on which the Program is based. The -work thus licensed is called the contributor's "contributor version". - -A contributor's "essential patent claims" are all patent claims owned -or controlled by the contributor, whether already acquired or -hereafter acquired, that would be infringed by some manner, permitted -by this License, of making, using, or selling its contributor version, -but do not include claims that would be infringed only as a -consequence of further modification of the contributor version. For -purposes of this definition, "control" includes the right to grant -patent sublicenses in a manner consistent with the requirements of -this License. - -Each contributor grants you a non-exclusive, worldwide, royalty-free -patent license under the contributor's essential patent claims, to -make, use, sell, offer for sale, import and otherwise run, modify and -propagate the contents of its contributor version. - -In the following three paragraphs, a "patent license" is any express -agreement or commitment, however denominated, not to enforce a patent -(such as an express permission to practice a patent or covenant not to -sue for patent infringement). To "grant" such a patent license to a -party means to make such an agreement or commitment not to enforce a -patent against the party. - -If you convey a covered work, knowingly relying on a patent license, -and the Corresponding Source of the work is not available for anyone -to copy, free of charge and under the terms of this License, through a -publicly available network server or other readily accessible means, -then you must either (1) cause the Corresponding Source to be so -available, or (2) arrange to deprive yourself of the benefit of the -patent license for this particular work, or (3) arrange, in a manner -consistent with the requirements of this License, to extend the patent -license to downstream recipients. "Knowingly relying" means you have -actual knowledge that, but for the patent license, your conveying the -covered work in a country, or your recipient's use of the covered work -in a country, would infringe one or more identifiable patents in that -country that you have reason to believe are valid. - -If, pursuant to or in connection with a single transaction or -arrangement, you convey, or propagate by procuring conveyance of, a -covered work, and grant a patent license to some of the parties -receiving the covered work authorizing them to use, propagate, modify -or convey a specific copy of the covered work, then the patent license -you grant is automatically extended to all recipients of the covered -work and works based on it. - -A patent license is "discriminatory" if it does not include within the -scope of its coverage, prohibits the exercise of, or is conditioned on -the non-exercise of one or more of the rights that are specifically -granted under this License. You may not convey a covered work if you -are a party to an arrangement with a third party that is in the -business of distributing software, under which you make payment to the -third party based on the extent of your activity of conveying the -work, and under which the third party grants, to any of the parties -who would receive the covered work from you, a discriminatory patent -license (a) in connection with copies of the covered work conveyed by -you (or copies made from those copies), or (b) primarily for and in -connection with specific products or compilations that contain the -covered work, unless you entered into that arrangement, or that patent -license was granted, prior to 28 March 2007. - -Nothing in this License shall be construed as excluding or limiting -any implied license or other defenses to infringement that may -otherwise be available to you under applicable patent law. - -#### 12. No Surrender of Others' Freedom. - -If conditions are imposed on you (whether by court order, agreement or -otherwise) that contradict the conditions of this License, they do not -excuse you from the conditions of this License. If you cannot convey a -covered work so as to satisfy simultaneously your obligations under -this License and any other pertinent obligations, then as a -consequence you may not convey it at all. For example, if you agree to -terms that obligate you to collect a royalty for further conveying -from those to whom you convey the Program, the only way you could -satisfy both those terms and this License would be to refrain entirely -from conveying the Program. - -#### 13. Remote Network Interaction; Use with the GNU General Public License. - -Notwithstanding any other provision of this License, if you modify the -Program, your modified version must prominently offer all users -interacting with it remotely through a computer network (if your -version supports such interaction) an opportunity to receive the -Corresponding Source of your version by providing access to the -Corresponding Source from a network server at no charge, through some -standard or customary means of facilitating copying of software. This -Corresponding Source shall include the Corresponding Source for any -work covered by version 3 of the GNU General Public License that is -incorporated pursuant to the following paragraph. - -Notwithstanding any other provision of this License, you have -permission to link or combine any covered work with a work licensed -under version 3 of the GNU General Public License into a single -combined work, and to convey the resulting work. The terms of this -License will continue to apply to the part which is the covered work, -but the work with which it is combined will remain governed by version -3 of the GNU General Public License. - -#### 14. Revised Versions of this License. - -The Free Software Foundation may publish revised and/or new versions -of the GNU Affero General Public License from time to time. Such new -versions will be similar in spirit to the present version, but may -differ in detail to address new problems or concerns. - -Each version is given a distinguishing version number. If the Program -specifies that a certain numbered version of the GNU Affero General -Public License "or any later version" applies to it, you have the -option of following the terms and conditions either of that numbered -version or of any later version published by the Free Software -Foundation. If the Program does not specify a version number of the -GNU Affero General Public License, you may choose any version ever -published by the Free Software Foundation. - -If the Program specifies that a proxy can decide which future versions -of the GNU Affero General Public License can be used, that proxy's -public statement of acceptance of a version permanently authorizes you -to choose that version for the Program. - -Later license versions may give you additional or different -permissions. However, no additional obligations are imposed on any -author or copyright holder as a result of your choosing to follow a -later version. - -#### 15. Disclaimer of Warranty. - -THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY -APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT -HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT -WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT -LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND -PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE -DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR -CORRECTION. - -#### 16. Limitation of Liability. - -IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING -WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR -CONVEYS THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, -INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES -ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT -NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR -LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM -TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER -PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. - -#### 17. Interpretation of Sections 15 and 16. - -If the disclaimer of warranty and limitation of liability provided -above cannot be given local legal effect according to their terms, -reviewing courts shall apply local law that most closely approximates -an absolute waiver of all civil liability in connection with the -Program, unless a warranty or assumption of liability accompanies a -copy of the Program in return for a fee. - -END OF TERMS AND CONDITIONS - -### How to Apply These Terms to Your New Programs - -If you develop a new program, and you want it to be of the greatest -possible use to the public, the best way to achieve this is to make it -free software which everyone can redistribute and change under these -terms. - -To do so, attach the following notices to the program. It is safest to -attach them to the start of each source file to most effectively state -the exclusion of warranty; and each file should have at least the -"copyright" line and a pointer to where the full notice is found. - - - Copyright (C) - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU Affero General Public License as - published by the Free Software Foundation, either version 3 of the - License, or (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Affero General Public License for more details. - - You should have received a copy of the GNU Affero General Public License - along with this program. If not, see . - -Also add information on how to contact you by electronic and paper -mail. - -If your software can interact with users remotely through a computer -network, you should also make sure that it provides a way for users to -get its source. For example, if your program is a web application, its -interface could display a "Source" link that leads users to an archive -of the code. There are many ways you could offer source, and different -solutions will be better for different programs; see section 13 for -the specific requirements. - -You should also get your employer (if you work as a programmer) or -school, if any, to sign a "copyright disclaimer" for the program, if -necessary. For more information on this, and how to apply and follow -the GNU AGPL, see . +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +License for the specific language governing permissions and limitations under +the License. diff --git a/package.json b/package.json index 5c16c66..8809b4a 100644 --- a/package.json +++ b/package.json @@ -2,7 +2,13 @@ "name": "@broid/kit", "version": "0.0.1", "main": "lib/core/index.js", - "license": "AGPL-3.0+", + "license": "Apache-2.0", + "licenses": [ + { + "type": "Apache-2.0", + "url": "http://www.apache.org/licenses/LICENSE-2.0" + } + ], "author": "Broid Team (https://broid.ai)", "description": "Bot framework supported all messaging plateforms and middlewares.", "repository": { @@ -39,8 +45,6 @@ "watch": "concurrently --kill-others \"npm run lint:watch\" \"npm run tsc:watch\"" }, "devDependencies": { - "@types/bluebird": "^3.0.37", - "@types/bluebird-global": "^3.0.1", "@types/node": "^7.0.5", "@types/ramda": "0.0.3", "ava": "^0.18.1", @@ -51,14 +55,15 @@ "sinon": "^1.17.7", "tslint": "^4.3.1", "tslint-eslint-rules": "^4.0.0", + "tslint-microsoft-contrib": "^4.0.1", "typescript": "~2.2.2", - "watch": "^1.0.1", - "tslint-microsoft-contrib": "^4.0.1" + "watch": "^1.0.1" }, "dependencies": { "@broid/schemas": "^1.0.0", "@broid/utils": "^1.1.0", "bluebird": "^3.5.0", + "body-parser": "^1.17.1", "express": "^4.15.2", "ramda": "^0.23.0", "rxjs": "^5.2.0" From c6d339ab73f63be1be2ef2a66d5d62af7fccd36b Mon Sep 17 00:00:00 2001 From: Issam Hakimi aka Killix Date: Fri, 14 Apr 2017 20:36:50 -0400 Subject: [PATCH 2/4] Version 0.1.0 done --- README.md | 17 ++-- lib/core/bot.js | 149 ++++++++++++++++++++++++++----- package.json | 2 +- src/core/bot.ts | 193 ++++++++++++++++++++++++++++++++++------- src/core/interfaces.ts | 5 +- yarn.lock | 63 +++++++++----- 6 files changed, 344 insertions(+), 85 deletions(-) diff --git a/README.md b/README.md index 407bd49..12c1b53 100644 --- a/README.md +++ b/README.md @@ -108,13 +108,13 @@ bot.hears(["keyword", "hello.*"], "Group") ## Node callback is supported ```javascript -bot.hear("hello.*", "Group", (message, error) => { +bot.hear("hello.*", "Group", (data, error) => { console.log("Data:", JSON.stringify(data, null, 2)); }); ``` ```javascript -bot.hears(["keyword", "hello.*"], "Group", (message, error) => { +bot.hears(["keyword", "hello.*"], "Group", (data, error) => { console.log("Data:", JSON.stringify(data, null, 2)); }); ``` @@ -124,17 +124,17 @@ bot.hears(["keyword", "hello.*"], "Group", (message, error) => { ### A simple message ```javascript -bot.sendText("Hello world.", data.raw); +bot.sendText("Hello world.", data.message); ``` ### A Video or Image message ```javascript -bot.sendImage("http://url-of-media", data.raw, optionalMeta); +bot.sendImage("http://url-of-media", data.message, optionalMeta); // OR -bot.sendVideo("http://url-of-media", data.raw, optionalMeta); +bot.sendVideo("http://url-of-media", data.message, optionalMeta); ``` `optionalMeta` is an object of optional information for the media. @@ -161,11 +161,14 @@ class FakeMiddleware { return "FakeMiddleware"; } - receive(bot, message) { + incoming(bot, message) { + // the return value can be an Promise, Observable or null return "hello world"; } - send(bot, message) { + outgoing(bot, message) { + // the return value can be an Promise, Observable or null + // The object.content field will be use to update the text of the message sent. return "Good buy world"; } } diff --git a/lib/core/bot.js b/lib/core/bot.js index 56fbdb2..7d72211 100644 --- a/lib/core/bot.js +++ b/lib/core/bot.js @@ -2,15 +2,19 @@ Object.defineProperty(exports, "__esModule", { value: true }); const utils_1 = require("@broid/utils"); const Promise = require("bluebird"); +const bodyParser = require("body-parser"); const express = require("express"); const R = require("ramda"); const Rx_1 = require("rxjs/Rx"); +const isObservable = (obs) => obs && typeof obs.subscribe === 'function'; +const isPromise = (obj) => obj && (typeof obj == 'object') + && ('tap' in obj) && ('then' in obj) && (typeof obj.then == 'function'); class Bot { constructor(obj) { this.logLevel = obj && obj.logLevel || 'info'; this.integrations = []; - this.receiveMiddlewares = []; - this.sendMiddlewares = []; + this.incomingMiddlewares = []; + this.outgoingMiddlewares = []; const httpOptions = { host: '0.0.0.0', port: 8080 }; this.httpOptions = obj && obj.http || httpOptions; this.httpEndpoints = []; @@ -20,21 +24,29 @@ class Bot { getHTTPEndpoints() { return this.httpEndpoints; } - use(instance) { + use(instance, filter) { if (instance.listen) { this.logger.info({ method: 'use', message: `Integration: ${instance.serviceName()}` }); this.addIntegration(instance); } - else if (instance.receive || instance.send) { - if (instance.receive) { + else if (instance.incoming || instance.outgoing) { + if (instance.incoming) { this.logger - .info({ method: 'use', message: `Receive middleware: ${instance.serviceName()}` }); - this.receiveMiddlewares.push(instance.receive); + .info({ method: 'use', message: `incoming middleware: ${instance.serviceName()}` }); + this.incomingMiddlewares.push({ + name: `${instance.serviceName()}.incoming`, + middleware: instance, + filter: filter || null, + }); } - if (instance.send) { + if (instance.outgoing) { this.logger - .info({ method: 'use', message: `Send middleware: ${instance.serviceName()}` }); - this.sendMiddlewares.push(instance.send); + .info({ method: 'use', message: `outgoing middleware: ${instance.serviceName()}` }); + this.outgoingMiddlewares.push({ + name: `${instance.serviceName()}.outgoing`, + middleware: instance, + filter: filter || null, + }); } } return; @@ -51,8 +63,9 @@ class Bot { } const listener = Rx_1.Observable .merge(...R.flatten(R.map((integration) => [integration.connect(), integration.listen()], this.integrations))) - .mergeMap((message) => this.testIncoming(message, patternRegex, messageTypesArr) - ? this.processIncomingMessage(message) : Rx_1.Observable.empty()); + .mergeMap((message) => this.processIncomingMessage(message)) + .mergeMap((messageUpdated) => this.testIncoming(messageUpdated.message, patternRegex, messageTypesArr) + ? Promise.resolve(messageUpdated) : Rx_1.Observable.empty()); return this.processListener(listener, R.prop('callback', args)); } hears(patterns, messageTypes, cb) { @@ -61,9 +74,10 @@ class Bot { const patternRegexes = R.map((pattern) => new RegExp(pattern, 'ig'), patterns); const listener = Rx_1.Observable.merge(...R.map((integration) => integration.listen(), this.integrations)) .mergeMap((message) => { - const matches = R.pipe(R.map((patternRegex) => this.testIncoming(message, patternRegex, messageTypesArr)), R.reject(R.equals(false))); + const messageUpdated = this.processIncomingMessage(message); + const matches = R.pipe(R.map((patternRegex) => this.testIncoming(messageUpdated.message, patternRegex, messageTypesArr)), R.reject(R.equals(false))); if (!R.isEmpty(matches(patternRegexes))) { - return this.processIncomingMessage(message); + return Promise.resolve(messageUpdated); } return Rx_1.Observable.empty(); }); @@ -73,8 +87,9 @@ class Bot { return this.hear(true, messageTypes, cb); } sendText(text, message) { - return this.processOutcomingMessage(text, message) - .then((textUpdated) => { + return this.processOutgoingContent(text, message) + .then((updated) => { + const content = updated.content || text; let data = { '@context': 'https://www.w3.org/ns/activitystreams', 'generator': { @@ -83,7 +98,7 @@ class Bot { type: 'Service', }, 'object': { - content: textUpdated, + content: content, type: 'Note', }, 'to': { @@ -102,6 +117,17 @@ class Bot { sendImage(url, message, meta) { return this.sendMedia(url, 'Image', message, meta); } + processOutgoingContent(content, message) { + return this.processOutgoingMessage(content, message) + .toPromise(Promise) + .then((updated) => { + const contents = R.reject(R.isNil)(R.map((o) => o.content, updated.data)); + if (!R.isEmpty(contents)) { + updated.content = R.join(' ', contents); + } + return updated; + }); + } messageTypes2Arr(messageTypes) { let messageTypesArr = []; if (messageTypes) { @@ -131,7 +157,7 @@ class Bot { testIncoming(message, patternRegex, messageTypesArr) { const messageContext = R.prop('@context', message); if (!messageContext) { - this.logger.debug('Message received should follow Broid schema.', message); + this.logger.debug('Message incoming should follow Broid schema.', message); return false; } const content = R.path(['object', 'content'], message); @@ -165,7 +191,7 @@ class Bot { return Promise.reject('Message should follow broid-schemas.'); } sendMedia(url, mediaType, message, meta) { - return this.processOutcomingMessage(url, message) + return this.processOutgoingContent(url, message) .then((urlUpdated) => { let data = { '@context': 'https://www.w3.org/ns/activitystreams', @@ -196,6 +222,8 @@ class Bot { if (router) { if (!this.express) { this.express = express(); + this.express.use(bodyParser.json()); + this.express.use(bodyParser.urlencoded({ extended: false })); } const httpPath = `/webhook/${integration.serviceName()}`; this.httpEndpoints.push(httpPath); @@ -203,12 +231,87 @@ class Bot { } return; } + chain(input, filters) { + let seq = Rx_1.Observable.from(filters); + return seq.reduce((chain, filter, index) => { + return chain.concatMap((data) => { + return filter(data) + .map((filterResult) => { + return R.flatten(R.concat(data, [R.assoc('order', index, filterResult)])); + }); + }); + }, Rx_1.Observable.of(input)) + .concatMap((value) => value); + } processIncomingMessage(message) { - return Promise.reduce(this.receiveMiddlewares, (data, fn) => fn(this, data), message) - .then((data) => ({ message: data, raw: message })); + const middlewares = R.map((middleware) => { + return (acc) => { + let resultObservable = Rx_1.Observable.empty(); + let patternRegexes = []; + if (middleware.filter) { + const patterns = R.is(Array, middleware.filter) ? middleware.filter : [middleware.filter]; + patternRegexes = R.map((pattern) => new RegExp(pattern, 'ig'), patterns); + } + const matches = R.pipe(R.map((patternRegex) => this.testIncoming(message, patternRegex, [])), R.reject(R.equals(false))); + if (R.isEmpty(patternRegexes) || !R.isEmpty(matches(patternRegexes))) { + const fn = middleware.middleware.incoming; + const result = fn(this, message, acc); + if (isObservable(result)) { + resultObservable = result; + } + else if (isPromise(result)) { + resultObservable = Rx_1.Observable.fromPromise(result); + } + else { + resultObservable = Rx_1.Observable.of(result); + } + } + return resultObservable.map((data) => ({ middleware: middleware.name, data })); + }; + }, this.incomingMiddlewares); + const intialAcc = []; + return this.chain(intialAcc, middlewares) + .take(1) + .map((data) => ({ data, message })); } - processOutcomingMessage(messageText, message) { - return Promise.reduce(this.sendMiddlewares, (text, fn) => fn(this, text, message), messageText); + processOutgoingMessage(content, message) { + const middlewares = R.map((middleware) => { + return (acc) => { + let resultObservable = Rx_1.Observable.empty(); + let patternRegexes = []; + if (middleware.filter) { + const patterns = R.is(Array, middleware.filter) ? middleware.filter : [middleware.filter]; + patternRegexes = R.map((pattern) => new RegExp(pattern, 'ig'), patterns); + } + const matches = R.pipe(R.map((patternRegex) => this.testIncoming(message, patternRegex, [])), R.reject(R.equals(false))); + if (R.isEmpty(patternRegexes) || !R.isEmpty(matches(patternRegexes))) { + const fn = middleware.middleware.outgoing; + const result = fn(this, content, message, acc); + if (isObservable(result)) { + resultObservable = result; + } + else if (isPromise(result)) { + resultObservable = Rx_1.Observable.fromPromise(result); + } + else { + resultObservable = Rx_1.Observable.of(result); + } + } + return resultObservable.map((data_) => { + let data = data_; + if (typeof data === 'string') { + data = { + content: data + }; + } + return { middleware: middleware.name, data, content: data.content }; + }); + }; + }, this.outgoingMiddlewares); + const intialAcc = []; + return this.chain(intialAcc, middlewares) + .take(1) + .map((data) => ({ data, message })); } startHttpServer() { if (this.express && !this.httpServer) { diff --git a/package.json b/package.json index 8809b4a..9044263 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@broid/kit", - "version": "0.0.1", + "version": "0.1.0", "main": "lib/core/index.js", "license": "Apache-2.0", "licenses": [ diff --git a/src/core/bot.ts b/src/core/bot.ts index c247219..32b8081 100644 --- a/src/core/bot.ts +++ b/src/core/bot.ts @@ -5,6 +5,7 @@ import { import { Logger } from '@broid/utils'; import * as Promise from 'bluebird'; +import * as bodyParser from 'body-parser'; import * as express from 'express'; import * as http from 'http'; import * as R from 'ramda'; @@ -16,10 +17,15 @@ import { IListenerArgs, IMetaMediaSend, IOptions, - middlewareReceiveType, - middlewareSendType, + middlewareIncomingType, + middlewareOutgoingType, } from './interfaces'; +const isObservable = (obs:any): boolean => obs && typeof obs.subscribe === 'function'; +const isPromise = (obj:any): boolean => + obj && (typeof obj=='object') + && ('tap' in obj) && ('then' in obj) && (typeof obj.then == 'function'); + export class Bot { public httpEndpoints: string[]; public httpServer: null | http.Server; @@ -29,15 +35,15 @@ export class Bot { private integrations: any; private logLevel: string; private logger: Logger; - private sendMiddlewares: any; - private receiveMiddlewares: any; + private outgoingMiddlewares: any; + private incomingMiddlewares: any; constructor(obj?: IOptions) { this.logLevel = obj && obj.logLevel || 'info'; this.integrations = []; - this.receiveMiddlewares = []; - this.sendMiddlewares = []; + this.incomingMiddlewares = []; + this.outgoingMiddlewares = []; const httpOptions: IHTTPOptions = { host: '0.0.0.0', port: 8080 }; this.httpOptions = obj && obj.http || httpOptions; @@ -51,22 +57,30 @@ export class Bot { return this.httpEndpoints; } - public use(instance: any): void { + public use(instance: any, filter?: string | string[]): void { // it's an integration if (instance.listen) { this.logger.info({ method: 'use', message: `Integration: ${instance.serviceName()}` }); this.addIntegration(instance); - } else if (instance.receive || instance.send) { // Middleware - if (instance.receive) { + } else if (instance.incoming || instance.outgoing) { // Middleware + if (instance.incoming) { this.logger - .info({ method: 'use', message: `Receive middleware: ${instance.serviceName()}` }); - this.receiveMiddlewares.push(instance.receive); + .info({ method: 'use', message: `incoming middleware: ${instance.serviceName()}` }); + this.incomingMiddlewares.push({ + name: `${instance.serviceName()}.incoming`, + middleware: instance, + filter: filter || null, + }); } - if (instance.send) { + if (instance.outgoing) { this.logger - .info({ method: 'use', message: `Send middleware: ${instance.serviceName()}` }); - this.sendMiddlewares.push(instance.send); + .info({ method: 'use', message: `outgoing middleware: ${instance.serviceName()}` }); + this.outgoingMiddlewares.push({ + name: `${instance.serviceName()}.outgoing`, + middleware: instance, + filter: filter || null, + }); } } return; @@ -89,9 +103,10 @@ export class Bot { const listener: Observable = Observable .merge(...R.flatten(R.map((integration: any) => [integration.connect(), integration.listen()], this.integrations))) - .mergeMap((message: IActivityStream) => - this.testIncoming(message, patternRegex, messageTypesArr) - ? this.processIncomingMessage(message) : Observable.empty()); + .mergeMap((message: IActivityStream) => this.processIncomingMessage(message)) + .mergeMap((messageUpdated: any) => + this.testIncoming(messageUpdated.message, patternRegex, messageTypesArr) + ? Promise.resolve(messageUpdated) : Observable.empty()); return this.processListener(listener, R.prop('callback', args) as callbackType); } @@ -107,12 +122,14 @@ export class Bot { const listener: Observable = Observable.merge(...R.map((integration: any) => integration.listen(), this.integrations)) .mergeMap((message: IActivityStream) => { + const messageUpdated: any = this.processIncomingMessage(message); + const matches = R.pipe(R.map((patternRegex: RegExp) => - this.testIncoming(message, patternRegex, messageTypesArr)), + this.testIncoming(messageUpdated.message, patternRegex, messageTypesArr)), R.reject(R.equals(false))); if (!R.isEmpty(matches(patternRegexes))) { - return this.processIncomingMessage(message); + return Promise.resolve(messageUpdated); } return Observable.empty(); @@ -127,8 +144,9 @@ export class Bot { } public sendText(text: string, message: IActivityStream) { - return this.processOutcomingMessage(text, message) - .then((textUpdated) => { + return this.processOutgoingContent(text, message) + .then((updated) => { + const content: string = updated.content || text; let data: ISendParameters = { '@context': 'https://www.w3.org/ns/activitystreams', 'generator': { @@ -137,7 +155,7 @@ export class Bot { type: 'Service', }, 'object': { - content: textUpdated, + content: content, type: 'Note', }, 'to': { @@ -160,6 +178,18 @@ export class Bot { return this.sendMedia(url, 'Image', message, meta); } + private processOutgoingContent(content: string, message: IActivityStream): Promise { + return this.processOutgoingMessage(content, message) + .toPromise(Promise) + .then((updated) => { + const contents = R.reject(R.isNil)(R.map((o: any) => o.content, updated.data)); + if (!R.isEmpty(contents)) { + updated.content = R.join(' ', contents); + } + return updated; + }); + } + private messageTypes2Arr(messageTypes?: string | null): string[] { let messageTypesArr: string[] = []; if (messageTypes) { @@ -199,7 +229,7 @@ export class Bot { messageTypesArr: string[]): boolean { const messageContext = R.prop('@context', message); if (!messageContext) { - this.logger.debug('Message received should follow Broid schema.', message); + this.logger.debug('Message incoming should follow Broid schema.', message); return false; } @@ -247,7 +277,7 @@ export class Bot { private sendMedia(url: string, mediaType: string, message: IActivityStream, meta?: IMetaMediaSend): Promise { - return this.processOutcomingMessage(url, message) + return this.processOutgoingContent(url, message) .then((urlUpdated) => { let data: ISendParameters = { '@context': 'https://www.w3.org/ns/activitystreams', @@ -281,6 +311,8 @@ export class Bot { if (router) { if (!this.express) { this.express = express(); + this.express.use(bodyParser.json()); + this.express.use(bodyParser.urlencoded({ extended: false })); } const httpPath = `/webhook/${integration.serviceName()}`; @@ -291,15 +323,114 @@ export class Bot { return; } - private processIncomingMessage(message: IActivityStream): Promise { - return Promise.reduce(this.receiveMiddlewares, (data: any, fn: middlewareReceiveType) => - fn(this, data), message) - .then((data) => ({ message: data, raw: message })); + /** + * I'd like to identify I way reach the same results dynamically, given an array (or sequence) of filters. + * + * @param input {} A value to be processed by a chain of filters. + * @param filters {Array} An array of filters through which to process the input. + * @returns {Observable} The output after processing `input` through the chained filters. + */ + private chain(input, filters) { + let seq = Observable.from(filters); + + return seq.reduce( + (chain: any, filter: any, index: any) => { + return chain.concatMap((data: any) => { + return filter(data) + .map((filterResult: any) => { + return R.flatten(R.concat(data, [R.assoc('order', index, filterResult)])); + }); + }); + }, + Observable.of(input) + ) + .concatMap((value: any) => value); } - private processOutcomingMessage(messageText: string, message: IActivityStream): Promise { - return Promise.reduce(this.sendMiddlewares, (text: any, fn: middlewareSendType) => - fn(this, text, message), messageText); + private processIncomingMessage(message: IActivityStream): Observable { + const middlewares = R.map((middleware: any) => { + return (acc: any) => { + let resultObservable = Observable.empty(); + + // Filter by regex if it' set + let patternRegexes: boolean[] | RegExp[] = []; + if (middleware.filter) { + const patterns = R.is(Array, middleware.filter) ? middleware.filter : [middleware.filter]; + patternRegexes = R.map((pattern: string) => new RegExp(pattern, 'ig'), patterns); + } + + const matches = R.pipe(R.map((patternRegex: RegExp | boolean) => + this.testIncoming(message, patternRegex, [])), + R.reject(R.equals(false))); + + if (R.isEmpty(patternRegexes) || !R.isEmpty(matches(patternRegexes))) { + const fn: middlewareIncomingType = middleware.middleware.incoming; + const result: any = fn(this, message, acc); + + if (isObservable(result)) { + resultObservable = result; + } else if (isPromise(result)) { + resultObservable = Observable.fromPromise(result); + } else { + resultObservable = Observable.of(result); + } + } + + return resultObservable.map((data) => ({ middleware: middleware.name, data })); + }; + }, this.incomingMiddlewares); + + const intialAcc = []; + return this.chain(intialAcc, middlewares) + .take(1) + .map((data: any) => ({ data, message })); + } + + private processOutgoingMessage(content: string, message: IActivityStream): Observable { + const middlewares = R.map((middleware: any) => { + return (acc: any) => { + let resultObservable = Observable.empty(); + + // Filter by regex if it' set + let patternRegexes: boolean[] | RegExp[] = []; + if (middleware.filter) { + const patterns = R.is(Array, middleware.filter) ? middleware.filter : [middleware.filter]; + patternRegexes = R.map((pattern: string) => new RegExp(pattern, 'ig'), patterns); + } + + const matches = R.pipe(R.map((patternRegex: RegExp | boolean) => + this.testIncoming(message, patternRegex, [])), + R.reject(R.equals(false))); + + if (R.isEmpty(patternRegexes) || !R.isEmpty(matches(patternRegexes))) { + const fn: middlewareOutgoingType = middleware.middleware.outgoing; + const result: any = fn(this, content, message, acc); + + if (isObservable(result)) { + resultObservable = result; + } else if (isPromise(result)) { + resultObservable = Observable.fromPromise(result); + } else { + resultObservable = Observable.of(result); + } + } + + return resultObservable.map((data_: any) => { + let data: any = data_; + if (typeof data === 'string') { + data = { + content: data + }; + } + return { middleware: middleware.name, data, content: data.content }; + }); + }; + }, this.outgoingMiddlewares); + + const intialAcc = []; + return this.chain(intialAcc, middlewares) + .take(1) + .map((data: any) => ({ data, message })); } private startHttpServer(): void { diff --git a/src/core/interfaces.ts b/src/core/interfaces.ts index 7f8d013..703a009 100644 --- a/src/core/interfaces.ts +++ b/src/core/interfaces.ts @@ -1,8 +1,9 @@ +import { Observable } from 'rxjs/Rx'; import { IActivityStream } from '@broid/schemas'; export type callbackType = (message: any, error?: any) => any; -export type middlewareReceiveType = (bot: any, message: any) => Promise; -export type middlewareSendType = (bot: any, text: any, message: IActivityStream) => Promise; +export type middlewareIncomingType = (bot: any, message: any, acc?: any) => Promise | Observable; +export type middlewareOutgoingType = (bot: any, content: string, message: IActivityStream, acc?: any) => Promise | Observable; export interface IHTTPOptions { host: string; diff --git a/yarn.lock b/yarn.lock index f697a6f..e11b69f 100644 --- a/yarn.lock +++ b/yarn.lock @@ -53,16 +53,6 @@ request "^2.81.0" valid-url "^1.0.9" -"@types/bluebird-global@^3.0.1": - version "3.5.1" - resolved "https://registry.yarnpkg.com/@types/bluebird-global/-/bluebird-global-3.5.1.tgz#c63c0e18b861f2c6992e79af1f8e00c69a35805a" - dependencies: - "@types/bluebird" "*" - -"@types/bluebird@*", "@types/bluebird@^3.0.37": - version "3.5.2" - resolved "https://registry.yarnpkg.com/@types/bluebird/-/bluebird-3.5.2.tgz#ecf1104217495e50fe0b588d538146cd6f733b89" - "@types/node@^7.0.5": version "7.0.12" resolved "https://registry.yarnpkg.com/@types/node/-/node-7.0.12.tgz#ae5f67a19c15f752148004db07cbbb372e69efc9" @@ -180,8 +170,8 @@ arr-exclude@^1.0.0: resolved "https://registry.yarnpkg.com/arr-exclude/-/arr-exclude-1.0.0.tgz#dfc7c2e552a270723ccda04cf3128c8cbfe5c631" arr-flatten@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/arr-flatten/-/arr-flatten-1.0.1.tgz#e5ffe54d45e19f32f216e91eb99c8ce892bb604b" + version "1.0.2" + resolved "https://registry.yarnpkg.com/arr-flatten/-/arr-flatten-1.0.2.tgz#1ec1e63439c54f67d6f72bb4299c3d4f73b2d996" array-differ@^1.0.0: version "1.0.0" @@ -658,6 +648,21 @@ bluebird@^3.0.0, bluebird@^3.4.6, bluebird@^3.5.0: version "3.5.0" resolved "https://registry.yarnpkg.com/bluebird/-/bluebird-3.5.0.tgz#791420d7f551eea2897453a8a77653f96606d67c" +body-parser@^1.17.1: + version "1.17.1" + resolved "https://registry.yarnpkg.com/body-parser/-/body-parser-1.17.1.tgz#75b3bc98ddd6e7e0d8ffe750dfaca5c66993fa47" + dependencies: + bytes "2.4.0" + content-type "~1.0.2" + debug "2.6.1" + depd "~1.1.0" + http-errors "~1.6.1" + iconv-lite "0.4.15" + on-finished "~2.3.0" + qs "6.4.0" + raw-body "~2.2.0" + type-is "~1.6.14" + boom@2.x.x: version "2.10.1" resolved "https://registry.yarnpkg.com/boom/-/boom-2.10.1.tgz#39c8918ceff5799f83f9492a848f625add0c766f" @@ -717,6 +722,10 @@ builtin-modules@^1.0.0: version "1.1.1" resolved "https://registry.yarnpkg.com/builtin-modules/-/builtin-modules-1.1.1.tgz#270f076c5a72c02f5b65a47df94c5fe3a278892f" +bytes@2.4.0: + version "2.4.0" + resolved "https://registry.yarnpkg.com/bytes/-/bytes-2.4.0.tgz#7d97196f9d5baf7f6935e25985549edd2a6c2339" + caching-transform@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/caching-transform/-/caching-transform-1.0.1.tgz#6dbdb2f20f8d8fbce79f3e94e9d1742dcdf5c0a1" @@ -1067,8 +1076,8 @@ dashdash@^1.12.0: assert-plus "^1.0.0" date-fns@^1.23.0: - version "1.28.2" - resolved "https://registry.yarnpkg.com/date-fns/-/date-fns-1.28.2.tgz#19e4192d68875c0bf7c9537e3f296a8ec64853ef" + version "1.28.3" + resolved "https://registry.yarnpkg.com/date-fns/-/date-fns-1.28.3.tgz#145d87adc3f5a82c6bda668de97eee1132c97ea1" date-time@^0.1.1: version "0.1.1" @@ -1078,13 +1087,13 @@ debug-log@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/debug-log/-/debug-log-1.0.1.tgz#2307632d4c04382b8df8a32f70b895046d52745f" -debug@2, debug@2.6.3, debug@^2.1.1, debug@^2.1.3, debug@^2.2.0: +debug@2, debug@2.6.3, debug@^2.1.1, debug@^2.1.3: version "2.6.3" resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.3.tgz#0f7eb8c30965ec08c72accfa0130c8b79984141d" dependencies: ms "0.7.2" -debug@2.6.1: +debug@2.6.1, debug@^2.2.0: version "2.6.1" resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.1.tgz#79855090ba2c4e3115cc7d8769491d58f0491351" dependencies: @@ -1687,8 +1696,8 @@ home-or-tmp@^2.0.0: os-tmpdir "^1.0.1" hosted-git-info@^2.1.4: - version "2.4.1" - resolved "https://registry.yarnpkg.com/hosted-git-info/-/hosted-git-info-2.4.1.tgz#4b0445e41c004a8bd1337773a4ff790ca40318c8" + version "2.4.2" + resolved "https://registry.yarnpkg.com/hosted-git-info/-/hosted-git-info-2.4.2.tgz#0076b9f46a270506ddbaaea56496897460612a67" http-errors@~1.6.1: version "1.6.1" @@ -1715,6 +1724,10 @@ https-proxy-agent@^1.0.0: debug "2" extend "3" +iconv-lite@0.4.15: + version "0.4.15" + resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.15.tgz#fe265a218ac6a57cfe854927e9d04c19825eddeb" + ignore-by-default@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/ignore-by-default/-/ignore-by-default-1.0.1.tgz#48ca6d72f6c6a3af00a9ad4ae6876be3889e2b09" @@ -2822,6 +2835,14 @@ range-parser@~1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/range-parser/-/range-parser-1.2.0.tgz#f49be6b487894ddc40dcc94a322f611092e00d5e" +raw-body@~2.2.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/raw-body/-/raw-body-2.2.0.tgz#994976cf6a5096a41162840492f0bdc5d6e7fb96" + dependencies: + bytes "2.4.0" + iconv-lite "0.4.15" + unpipe "1.0.0" + rc@^1.0.1, rc@^1.1.2, rc@^1.1.6, rc@^1.1.7: version "1.2.1" resolved "https://registry.yarnpkg.com/rc/-/rc-1.2.1.tgz#2e03e8e42ee450b8cb3dce65be1bf8974e1dfd95" @@ -3523,7 +3544,7 @@ unique-temp-dir@^1.0.0: os-tmpdir "^1.0.1" uid2 "0.0.3" -unpipe@~1.0.0: +unpipe@1.0.0, unpipe@~1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/unpipe/-/unpipe-1.0.0.tgz#b2bf4ee8514aae6165b4817829d21b2ef49904ec" @@ -3729,8 +3750,8 @@ yargs-parser@^5.0.0: camelcase "^3.0.0" yargs@^7.0.2: - version "7.0.2" - resolved "https://registry.yarnpkg.com/yargs/-/yargs-7.0.2.tgz#115b97df1321823e8b8648e8968c782521221f67" + version "7.1.0" + resolved "https://registry.yarnpkg.com/yargs/-/yargs-7.1.0.tgz#6ba318eb16961727f5d284f8ea003e8d6154d0c8" dependencies: camelcase "^3.0.0" cliui "^3.2.0" From 92f4574a8ce46dfd928642f7f3f06fb1aa1c1f84 Mon Sep 17 00:00:00 2001 From: Issam Hakimi aka Killix Date: Tue, 18 Apr 2017 11:30:05 -0400 Subject: [PATCH 3/4] Update the licence --- LICENCE.md | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/LICENCE.md b/LICENCE.md index 661eb24..b1ab972 100644 --- a/LICENCE.md +++ b/LICENCE.md @@ -1,16 +1,15 @@ This software is licensed under the Apache 2 license, quoted below. -Copyright 2009 Twitter, Inc. -Copyright 2009 Robey Pointer +Copyright 2017 Broid -Licensed under the Apache License, Version 2.0 (the "License"); you may not -use this file except in compliance with the License. You may obtain a copy of -the License at +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -License for the specific language governing permissions and limitations under -the License. +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. From 376bfc3ae1fe4504f2649f65ce993e92ae48d178 Mon Sep 17 00:00:00 2001 From: Issam Hakimi aka Killix Date: Tue, 18 Apr 2017 18:53:58 -0400 Subject: [PATCH 4/4] follow comments --- lib/core/bot.js | 36 +++++++++++++++++------------------- src/core/bot.ts | 36 ++++++++++++++++-------------------- 2 files changed, 33 insertions(+), 39 deletions(-) diff --git a/lib/core/bot.js b/lib/core/bot.js index 7d72211..62adef6 100644 --- a/lib/core/bot.js +++ b/lib/core/bot.js @@ -29,25 +29,23 @@ class Bot { this.logger.info({ method: 'use', message: `Integration: ${instance.serviceName()}` }); this.addIntegration(instance); } - else if (instance.incoming || instance.outgoing) { - if (instance.incoming) { - this.logger - .info({ method: 'use', message: `incoming middleware: ${instance.serviceName()}` }); - this.incomingMiddlewares.push({ - name: `${instance.serviceName()}.incoming`, - middleware: instance, - filter: filter || null, - }); - } - if (instance.outgoing) { - this.logger - .info({ method: 'use', message: `outgoing middleware: ${instance.serviceName()}` }); - this.outgoingMiddlewares.push({ - name: `${instance.serviceName()}.outgoing`, - middleware: instance, - filter: filter || null, - }); - } + else if (instance.incoming) { + this.logger + .info({ method: 'use', message: `incoming middleware: ${instance.serviceName()}` }); + this.incomingMiddlewares.push({ + name: `${instance.serviceName()}.incoming`, + middleware: instance, + filter: filter || null, + }); + } + else if (instance.outgoing) { + this.logger + .info({ method: 'use', message: `outgoing middleware: ${instance.serviceName()}` }); + this.outgoingMiddlewares.push({ + name: `${instance.serviceName()}.outgoing`, + middleware: instance, + filter: filter || null, + }); } return; } diff --git a/src/core/bot.ts b/src/core/bot.ts index 32b8081..01fb127 100644 --- a/src/core/bot.ts +++ b/src/core/bot.ts @@ -62,26 +62,22 @@ export class Bot { if (instance.listen) { this.logger.info({ method: 'use', message: `Integration: ${instance.serviceName()}` }); this.addIntegration(instance); - } else if (instance.incoming || instance.outgoing) { // Middleware - if (instance.incoming) { - this.logger - .info({ method: 'use', message: `incoming middleware: ${instance.serviceName()}` }); - this.incomingMiddlewares.push({ - name: `${instance.serviceName()}.incoming`, - middleware: instance, - filter: filter || null, - }); - } - - if (instance.outgoing) { - this.logger - .info({ method: 'use', message: `outgoing middleware: ${instance.serviceName()}` }); - this.outgoingMiddlewares.push({ - name: `${instance.serviceName()}.outgoing`, - middleware: instance, - filter: filter || null, - }); - } + } else if(instance.incoming) { + this.logger + .info({ method: 'use', message: `incoming middleware: ${instance.serviceName()}` }); + this.incomingMiddlewares.push({ + name: `${instance.serviceName()}.incoming`, + middleware: instance, + filter: filter || null, + }); + } else if (instance.outgoing) { // Middleware + this.logger + .info({ method: 'use', message: `outgoing middleware: ${instance.serviceName()}` }); + this.outgoingMiddlewares.push({ + name: `${instance.serviceName()}.outgoing`, + middleware: instance, + filter: filter || null, + }); } return; }