pax_global_header00006660000000000000000000000064126334646360014527gustar00rootroot0000000000000052 comment=a59ac410c057e8042c528e9f73e9f3eaada6e79e yowsup-2.4.48/000077500000000000000000000000001263346463600131745ustar00rootroot00000000000000yowsup-2.4.48/.gitignore000066400000000000000000000000701263346463600151610ustar00rootroot00000000000000*.pyc *.class todo *.egg-info tp tests dist build .idea yowsup-2.4.48/.travis.yml000066400000000000000000000003741263346463600153110ustar00rootroot00000000000000language: python python: - "2.6" - "2.7" - "3.2" - "3.3" - "3.4" # command to install dependencies install: - python setup.py install # command to run tests script: nosetests branches: only: - master - develop - uniform_xml yowsup-2.4.48/LICENSE000066400000000000000000001044621263346463600142100ustar00rootroot00000000000000GNU GENERAL PUBLIC LICENSE Version 3, 29 June 2007 Copyright (C) 2007 Free Software Foundation, Inc. Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. Preamble The GNU General Public License is a free, copyleft license for software and other kinds of works. The licenses for most software and other practical works are designed to take away your freedom to share and change the works. By contrast, the GNU General Public License is 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. We, the Free Software Foundation, use the GNU General Public License for most of our software; it applies also to any other work released this way by its authors. You can apply it to your programs, too. 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. To protect your rights, we need to prevent others from denying you these rights or asking you to surrender the rights. Therefore, you have certain responsibilities if you distribute copies of the software, or if you modify it: responsibilities to respect the freedom of others. For example, if you distribute copies of such a program, whether gratis or for a fee, you must pass on to the recipients the same freedoms that you received. You must make sure that they, too, receive or can get the source code. And you must show them these terms so they know their rights. Developers that use the GNU GPL protect your rights with two steps: (1) assert copyright on the software, and (2) offer you this License giving you legal permission to copy, distribute and/or modify it. For the developers' and authors' protection, the GPL clearly explains that there is no warranty for this free software. For both users' and authors' sake, the GPL requires that modified versions be marked as changed, so that their problems will not be attributed erroneously to authors of previous versions. Some devices are designed to deny users access to install or run modified versions of the software inside them, although the manufacturer can do so. This is fundamentally incompatible with the aim of protecting users' freedom to change the software. The systematic pattern of such abuse occurs in the area of products for individuals to use, which is precisely where it is most unacceptable. Therefore, we have designed this version of the GPL to prohibit the practice for those products. If such problems arise substantially in other domains, we stand ready to extend this provision to those domains in future versions of the GPL, as needed to protect the freedom of users. Finally, every program is threatened constantly by software patents. States should not allow patents to restrict development and use of software on general-purpose computers, but in those that do, we wish to avoid the special danger that patents applied to a free program could make it effectively proprietary. To prevent this, the GPL assures that patents cannot be used to render the program non-free. 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 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. Use with the GNU Affero General Public License. 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 Affero 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 special requirements of the GNU Affero General Public License, section 13, concerning interaction through a network will apply to the combination as such. 14. Revised Versions of this License. The Free Software Foundation may publish revised and/or new versions of the GNU 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 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 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 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. {one line to give the program's name and a brief idea of what it does.} Copyright (C) {year} {name of author} This program is free software: you can redistribute it and/or modify it under the terms of the GNU 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 General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . Also add information on how to contact you by electronic and paper mail. If the program does terminal interaction, make it output a short notice like this when it starts in an interactive mode: {project} Copyright (C) {year} {fullname} This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. This is free software, and you are welcome to redistribute it under certain conditions; type `show c' for details. The hypothetical commands `show w' and `show c' should show the appropriate parts of the General Public License. Of course, your program's commands might be different; for a GUI interface, you would use an "about box". 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 GPL, see . The GNU General Public License does not permit incorporating your program into proprietary programs. If your program is a subroutine library, you may consider it more useful to permit linking proprietary applications with the library. If this is what you want to do, use the GNU Lesser General Public License instead of this License. But first, please read . yowsup-2.4.48/README.md000066400000000000000000000072301263346463600144550ustar00rootroot00000000000000# Yowsup 2 [![Build Status](https://travis-ci.org/tgalal/yowsup.svg?branch=master)](https://travis-ci.org/tgalal/yowsup) ## Updates (December 14, 2015) Yowsup v2.4.48 is out, See [release notes](https://github.com/tgalal/yowsup/releases/tag/v2.4.48) ========================================================== ## Yowsup opened WhatsApp service under platforms! Yowsup is a python library that enables you build application which use WhatsApp service. Yowsup has been used to create an unofficial WhatsApp client Nokia N9 through the Wazapp project which was in use by 200K + users as well as another fully featured unofficial client for Blackberry 10 ## Quickstart * **[yowsup's architecture](https://github.com/tgalal/yowsup/wiki/Architecture)** * **[Create a sample app](https://github.com/tgalal/yowsup/wiki/Sample-Application)** * **[yowsup-cli](https://github.com/tgalal/yowsup/wiki/yowsup-cli-2.0)** * **[Yowsup development, debugging, maintainance and sanity](https://github.com/tgalal/yowsup/wiki/Yowsup-development,-debugging,-maintainance-and-sanity)** ## Installation - Requires python2.6+, or python3.0 + - Required python packages: python-dateutil, - Required python packages for end-to-end encryption: protobuf, pycrypto, python-axolotl-curve25519 - Required python packages for yowsup-cli: argparse, readline (or pyreadline for windows), pillow (for sending images) Install using setup.py to pull all python dependencies, or using pip: ``` pip install yowsup2 ``` ### Linux You need to have installed python headers (from probably python-dev package) and ncurses-dev, then run ``` python setup.py install ``` Because of a bug with python-dateutil package you might get permission error for some dateutil file called requires.txt when you use yowsup (see [this bug report](https://bugs.launchpad.net/dateutil/+bug/1243202)) to fix you'll need to chmod 644 that file. ### Mac ``` python setup.py install ``` Administrators privileges might be required, if so then run with 'sudo' ### Windows - Install [mingw](http://www.mingw.org/) compiler - Add mingw to your PATH - In PYTHONPATH\Lib\distutils create a file called distutils.cfg and add these lines: ``` [build] compiler=mingw32 ``` - Install gcc: ```mingw-get.exe install gcc``` - Install [zlib](http://www.zlib.net/) - ```python setup.py install``` If pycrypto fails to install with some "chmod error". You can install it separately using something like ```easy_install http://www.voidspace.org.uk/downloads/pycrypto26/pycrypto-2.6.win32-py2.7.exe``` or for python3 from: > [https://github.com/axper/python3-pycrypto-windows-installer](https://github.com/axper/python3-pycrypto-windows-installer) and then rerun the install command again # Special thanks Special thanks to: - [CODeRUS](https://github.com/CODeRUS) - [mgp25](https://github.com/mgp25) - [SikiFn](https://github.com/SikiFn) - [0xTryCatch](https://github.com/0xTryCatch) - [shirioko](https://github.com/shirioko) and everyone else on the [WhatsAPI](https://github.com/mgp25/WhatsAPI-Official) project for their contributions to yowsup and the amazing effort they put into WhatsAPI, the PHP WhatsApp library Special thanks goes to all other people who use and contribute to the library as well. Please **[read this](https://github.com/tgalal/yowsup/wiki/Yowsup-development,-debugging,-maintainance-and-sanity)** if you'd like to contribute to yowsup 2.0 Thanks! # License: As of January 1, 2015 yowsup is licensed under the GPLv3+: http://www.gnu.org/licenses/gpl-3.0.html. yowsup-2.4.48/setup.py000077500000000000000000000025431263346463600147150ustar00rootroot00000000000000#!/usr/bin/env python from __future__ import print_function from setuptools import setup, find_packages import yowsup import platform deps = ['python-dateutil', 'argparse', 'python-axolotl>=0.1.7', 'pillow'] if platform.system().lower() == "windows": deps.append('pyreadline') else: try: import readline except ImportError: deps.append('readline') setup( name='yowsup2', version=yowsup.__version__, url='http://github.com/tgalal/yowsup/', license='GPL-3+', author='Tarek Galal', tests_require=[], install_requires = deps, scripts = ['yowsup-cli'], #cmdclass={'test': PyTest}, author_email='tare2.galal@gmail.com', description='A WhatsApp python library', #long_description=long_description, packages= find_packages(), include_package_data=True, platforms='any', #test_suite='', classifiers = [ 'Programming Language :: Python', 'Development Status :: 4 - Beta', 'Natural Language :: English', #'Environment :: Web Environment', 'Intended Audience :: Developers', 'License :: OSI Approved :: GNU General Public License v3 or later (GPLv3+)', 'Operating System :: OS Independent', 'Topic :: Software Development :: Libraries :: Python Modules' ], #extras_require={ # 'testing': ['pytest'], #} ) yowsup-2.4.48/yowsup-cli000077500000000000000000000316161263346463600152440ustar00rootroot00000000000000#!/usr/bin/env python __version__ = "2.0.13" __author__ = "Tarek Galal" import sys, argparse, yowsup, logging HELP_CONFIG = """ ############# Yowsup Configuration Sample ########### # # ==================== # The file contains info about your WhatsApp account. This is used during registration and login. # You can define or override all fields in the command line args as well. # # Country code. See http://www.ipipi.com/help/telephone-country-codes.htm. This is now required. cc=49 # # Your full phone number including the country code you defined in 'cc', without preceding '+' or '00' phone=491234567890 # # You obtain this password when you register using Yowsup. password=NDkxNTIyNTI1NjAyMkBzLndoYXRzYXBwLm5ldA== ####################################################### """ logger = logging.getLogger("yowsup-cli") class YowArgParser(argparse.ArgumentParser): def __init__(self, *args, **kwargs): super(YowArgParser, self).__init__(*args, **kwargs) self.add_argument("-v", "--version", action = "store_true", help = "Print version info and exit" ) self.add_argument("-d", "--debug", action = "store_true", help = "Show debug messages" ) self.add_argument("--help-config", help = "Prints a config file sample", action = "store_true") self.args = {} def getArgs(self): return self.parse_args() def getConfig(self, config): try: f = open(config) out = {} for l in f: line = l.strip() if len(line) and line[0] not in ('#',';'): prep = line.split('#', 1)[0].split(';', 1)[0].split('=', 1) varname = prep[0].strip() val = prep[1].strip() out[varname.replace('-', '_')] = val return out except IOError: print("Invalid config path: %s" % config) sys.exit(1) def process(self): self.args = vars(self.parse_args()) if self.args["version"]: print("yowsup-cli v%s\nUsing yowsup v%s" % (__version__, yowsup.__version__)) sys.exit(0) if self.args["help_config"]: print(HELP_CONFIG) sys.exit(0) if self.args["debug"]: logging.basicConfig(level = logging.DEBUG) else: logging.basicConfig(level = logging.INFO) class RegistrationArgParser(YowArgParser): def __init__(self, *args, **kwargs): super(RegistrationArgParser, self).__init__(*args, **kwargs) self.description = "WhatsApp Registration options" configGroup = self.add_argument_group("Configuration options", description = "Config file is optional. Other configuration arguments have higher priority if given, and will override those specified in the config file") configGroup.add_argument("-c", '--config', action = "store", help = 'Path to config file. If this is not set then you must set at least --phone and --cc arguments') configGroup.add_argument("-m", '--mcc', action = "store", help = "Mobile Country Code. Check your mcc here: https://en.wikipedia.org/wiki/Mobile_country_code") configGroup.add_argument("-n", '--mnc', action = "store", help = "Mobile Network Code. Check your mnc from https://en.wikipedia.org/wiki/Mobile_country_code") # configGroup.add_argument("-M", '--sim-mcc', # action = "store", # help = "Mobile Country Code. Check your mcc here: https://en.wikipedia.org/wiki/Mobile_country_code" # ) # configGroup.add_argument("-N", '--sim-mnc', # action= "store", # help = "SIM MNC" # ) configGroup.add_argument("-p", '--phone', action= "store", help = " Your full phone number including the country code you defined in 'cc', without preceeding '+' or '00'") configGroup.add_argument("-C", '--cc', action = "store", help = "Country code. See http://www.ipipi.com/help/telephone-country-codes.htm. This is now required") # configGroup.add_argument("-i", '--id', # action="store", # help = "Identity" # ) regSteps = self.add_argument_group("Modes") regSteps = regSteps.add_mutually_exclusive_group() regSteps.add_argument("-r", '--requestcode', help='Request the digit registration code from Whatsapp.', action="store", required=False, metavar="(sms|voice)") regSteps.add_argument("-R", '--register', help='Register account on Whatsapp using the code you previously received', action="store", required=False, metavar="code") def process(self): super(RegistrationArgParser, self).process() config = self.getConfig(self.args["config"]) if self.args["config"] else {} if self.args["mcc"] : config["mcc"] = self.args["mcc"] if self.args["mnc"] : config["mnc"] = self.args["mnc"] if self.args["phone"] : config["phone"] = self.args["phone"] if self.args["cc" ] : config["cc"] = self.args["cc"] #if self.args["sim_mnc"] : config["sim_mnc"] = self.args["sim_mnc"] #if self.args["sim_mcc"] : config["sim_mcc"] = self.args["sim_mcc"] if not "mcc" in config: config["mcc"] = "000" if not "mnc" in config: config["mnc"] = "000" if not "sim_mcc" in config: config["sim_mcc"] = "000" if not "sim_mnc" in config: config["sim_mnc"] = "000" try: assert self.args["requestcode"] or self.args["register"], "Must specify one of the modes -r/-R" assert "cc" in config, "Must specify cc (country code)" assert "phone" in config, "Must specify phone number" except AssertionError as e: print(e) print("\n") return False if not config["phone"].startswith(config["cc"]): print("Error, phone number does not start with the specified country code\n") return False config["phone"] = config["phone"][len(config["cc"]):] if self.args["requestcode"]: self.handleRequestCode(self.args["requestcode"], config) elif self.args["register"]: self.handleRegister(self.args["register"], config) else: return False return True def handleRequestCode(self, method, config): from yowsup.registration import WACodeRequest codeReq = WACodeRequest(config["cc"], config["phone"], config["mcc"], config["mnc"], config["mcc"], config["mnc"], method ) result = codeReq.send() print(self.resultToString(result)) def handleRegister(self, code, config): from yowsup.registration import WARegRequest code = code.replace('-', '') req = WARegRequest(config["cc"], config["phone"], code) result = req.send() print(self.resultToString(result)) def resultToString(self, result): unistr = str if sys.version_info >= (3, 0) else unicode out = [] for k, v in result.items(): if v is None: continue out.append("%s: %s" %(k, v.encode("utf-8") if type(v) is unistr else v)) return "\n".join(out) class DemosArgParser(YowArgParser): def __init__(self, *args, **kwargs): super(DemosArgParser, self).__init__(*args, **kwargs) self.description = "Run a yowsup demo" configGroup = self.add_argument_group("Configuration options for demos") credentialsOpts = configGroup.add_mutually_exclusive_group() credentialsOpts.add_argument("-l", "--login", action="store", metavar="phone:b64password", help = "WhatsApp login credentials, in the format phonenumber:password, where password is base64 encoded.") credentialsOpts.add_argument("-c", "--config", action="store", help = "Path to config file containing authentication info. For more info about config format use --help-config") configGroup.add_argument("-M", "--unmoxie", action="store_true", help="Disable E2E Encryption") cmdopts = self.add_argument_group("Command line interface demo") cmdopts.add_argument('-y', '--yowsup', action = "store_true", help = "Start the Yowsup command line client") echoOpts = self.add_argument_group("Echo client demo") echoOpts.add_argument('-e', '--echo', action = "store_true", help = "Start the Yowsup Echo client") sendOpts = self.add_argument_group("Send client demo") sendOpts.add_argument('-s', '--send', action="store", help = "Send a message to specified phone number, " "wait for server receipt and exit", metavar=("phone", "message"), nargs = 2) syncContacts = self.add_argument_group("Sync contacts") syncContacts.add_argument('-S','--sync', action = "store" , help = "Sync ( check valid ) whatsapp contacts",metavar =("contacts")) def process(self): super(DemosArgParser, self).process() if self.args["yowsup"]: self.startCmdline() elif self.args["echo"]: self.startEcho() elif self.args["send"]: self.startSendClient() elif self.args["sync"]: self.startSyncContacts() else: return False return True def _getCredentials(self): if self.args["login"]: return tuple(self.args["login"].split(":")) elif self.args["config"]: config = self.getConfig(self.args["config"]) assert "password" in config and "phone" in config, "Must specify at least phone number and password in config file" return config["phone"], config["password"] else: return None def startCmdline(self): from yowsup.demos import cli credentials = self._getCredentials() if not credentials: print("Error: You must specify a configuration method") sys.exit(1) stack = cli.YowsupCliStack(credentials, not self.args["unmoxie"]) stack.start() def startEcho(self): from yowsup.demos import echoclient credentials = self._getCredentials() if not credentials: print("Error: You must specify a configuration method") sys.exit(1) try: stack = echoclient.YowsupEchoStack(credentials, not self.args["unmoxie"]) stack.start() except KeyboardInterrupt: print("\nYowsdown") sys.exit(0) def startSendClient(self): from yowsup.demos import sendclient credentials = self._getCredentials() if not credentials: print("Error: You must specify a configuration method") sys.exit(1) try: stack = sendclient.YowsupSendStack(credentials, [([self.args["send"][0], self.args["send"][1]])], not self.args["unmoxie"]) stack.start() except KeyboardInterrupt: print("\nYowsdown") sys.exit(0) def startSyncContacts(self): from yowsup.demos import contacts credentials = self._getCredentials() if not credentials: print("Error: You must specify a configuration method") sys.exit(1) try: stack = contacts.YowsupSyncStack(credentials,self.args["sync"].split(','), not self.args["unmoxie"]) stack.start() except KeyboardInterrupt: print("\nYowsdown") sys.exit(0) if __name__ == "__main__": args = sys.argv if(len(args) > 1): del args[0] modeDict = { "demos": DemosArgParser, "registration": RegistrationArgParser, "version": None } if(len(args) == 0 or args[0] not in modeDict): print("Available commands:\n===================") print(", ".join(modeDict.keys())) sys.exit(1) mode = args[0] if mode == "version": print("yowsup-cli v%s\nUsing yowsup v%s" % (__version__, yowsup.__version__)) sys.exit(0) else: parser = modeDict[mode]() if not parser.process(): parser.print_help() yowsup-2.4.48/yowsup/000077500000000000000000000000001263346463600145425ustar00rootroot00000000000000yowsup-2.4.48/yowsup/__init__.py000066400000000000000000000000621263346463600166510ustar00rootroot00000000000000__version__ = "2.4.48" __author__ = "Tarek Galal" yowsup-2.4.48/yowsup/common/000077500000000000000000000000001263346463600160325ustar00rootroot00000000000000yowsup-2.4.48/yowsup/common/__init__.py000066400000000000000000000000431263346463600201400ustar00rootroot00000000000000from .constants import YowConstantsyowsup-2.4.48/yowsup/common/constants.py000066400000000000000000000013171263346463600204220ustar00rootroot00000000000000class YowConstants: DOMAIN = "s.whatsapp.net" ENDPOINTS = ( ("e1.whatsapp.net", 443), ("e2.whatsapp.net", 443), ("e3.whatsapp.net", 443), ("e4.whatsapp.net", 443), ("e5.whatsapp.net", 443), ("e6.whatsapp.net", 443), ("e7.whatsapp.net", 443), ("e8.whatsapp.net", 443), ("e9.whatsapp.net", 443), ("e10.whatsapp.net", 443), ("e11.whatsapp.net", 443), ("e12.whatsapp.net", 443), ("e13.whatsapp.net", 443), ("e14.whatsapp.net", 443), ("e15.whatsapp.net", 443), ("e16.whatsapp.net", 443), ) PATH_STORAGE = "~/.yowsup" PREVIEW_WIDTH = 64 PREVIEW_HEIGHT = 64 yowsup-2.4.48/yowsup/common/http/000077500000000000000000000000001263346463600170115ustar00rootroot00000000000000yowsup-2.4.48/yowsup/common/http/__init__.py000066400000000000000000000001621263346463600211210ustar00rootroot00000000000000from .httpproxy import HttpProxy from .warequest import WARequest from .waresponseparser import JSONResponseParseryowsup-2.4.48/yowsup/common/http/httpproxy.py000066400000000000000000000063231263346463600214500ustar00rootroot00000000000000''' Copyright (c) <2012> Tarek Galal Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ''' import os, base64 try: from urllib.parse import urlparse except ImportError: from urlparse import urlparse class HttpProxy: def __init__(self, address, username = None, password = None): self.address = address self.username = username self.password = password def __repr__(self): return repr(self.address) def handler(self): return HttpProxyHandler(self) @staticmethod def getFromEnviron(): url = None for key in ('http_proxy', 'https_proxy'): url = os.environ.get(key) if url: break if not url: return None dat = urlparse(url) port = 80 if dat.scheme == 'http' else 443 if dat.port != None: port = int(dat.port) host = dat.hostname return HttpProxy((host, port), dat.username, dat.password) class HttpProxyHandler: def __init__(self, proxy): self.state = 'init' self.proxy = proxy def onConnect(self): pass def connect(self, socket, pair): proxy = self.proxy authHeader = None if proxy.username and proxy.password: key = bytes(proxy.username, 'ascii') + b':' + bytes(proxy.password, 'ascii') if (bytes != str) else bytes(proxy.username) + b':' + proxy.password auth = base64.b64encode(key) authHeader = b'Proxy-Authorization: Basic ' + auth + b'\r\n' data = bytearray('CONNECT %s:%d HTTP/1.1\r\nHost: %s:%d\r\n' % (2 * pair), 'ascii') if authHeader: data += authHeader data += b'\r\n' self.state = 'connect' self.data = data socket.connect(proxy.address) def send(self, socket): if self.state == 'connect': socket.send(self.data) self.state = 'sent' def recv(self, socket, size): if self.state == 'sent': data = socket.recv(size) data = data.decode('ascii') status = data.split(' ', 2) if status[1] != '200': raise Exception('%s' % (data[:data.index('\r\n')])) self.state = 'end' self.onConnect() return datayowsup-2.4.48/yowsup/common/http/test_warequest.py000066400000000000000000000000621263346463600224400ustar00rootroot00000000000000from yowsup.common.http.warequest import WARequestyowsup-2.4.48/yowsup/common/http/warequest.py000066400000000000000000000110051263346463600214000ustar00rootroot00000000000000import urllib,sys, os, logging import hashlib from .waresponseparser import ResponseParser from yowsup.env import S40YowsupEnv CURRENT_ENV = S40YowsupEnv() if sys.version_info < (3, 0): import httplib from urllib import urlencode if sys.version_info >= (2, 7, 9): #see https://github.com/tgalal/yowsup/issues/677 import ssl ssl._create_default_https_context = ssl._create_unverified_context else: from http import client as httplib from urllib.parse import urlencode logger = logging.getLogger(__name__) class WARequest(object): OK = 200 def __init__(self): self.pvars = [] self.port = 443 self.type = "GET" self.parser = None self.params = [] self.headers = {} self.sent = False self.response = None def setParsableVariables(self, pvars): self.pvars = pvars def onResponse(self, name, value): if name == "status": self.status = value elif name == "result": self.result = value def addParam(self,name,value): self.params.append((name,value)) def removeParam(self, name): for i in range(0, len(self.params)): if self.params[i][0] == name: del self.params[i] def addHeaderField(self, name, value): self.headers[name] = value def clearParams(self): self.params = [] def getUserAgent(self): return CURRENT_ENV.getUserAgent() def send(self, parser = None): if self.type == "POST": return self.sendPostRequest(parser) return self.sendGetRequest(parser) def setParser(self, parser): if isinstance(parser, ResponseParser): self.parser = parser else: logger.error("Invalid parser") def getConnectionParameters(self): if not self.url: return "", "", self.port try: url = self.url.split("://", 1) url = url[0] if len(url) == 1 else url[1] host, path = url.split('/', 1) except ValueError: host = url path = "" path = "/" + path return host, self.port, path def sendGetRequest(self, parser = None): self.response = None params = self.params#[param.items()[0] for param in self.params]; parser = parser or self.parser or ResponseParser() headers = dict(list({"User-Agent":self.getUserAgent(), "Accept": parser.getMeta() }.items()) + list(self.headers.items())); host,port,path = self.getConnectionParameters() self.response = WARequest.sendRequest(host, port, path, headers, params, "GET") if not self.response.status == WARequest.OK: logger.error("Request not success, status was %s"%self.response.status) return {} data = self.response.read() logger.info(data) self.sent = True return parser.parse(data.decode(), self.pvars) def sendPostRequest(self, parser = None): self.response = None params = self.params #[param.items()[0] for param in self.params]; parser = parser or self.parser or ResponseParser() headers = dict(list({"User-Agent":self.getUserAgent(), "Accept": parser.getMeta(), "Content-Type":"application/x-www-form-urlencoded" }.items()) + list(self.headers.items())) host,port,path = self.getConnectionParameters() self.response = WARequest.sendRequest(host, port, path, headers, params, "POST") if not self.response.status == WARequest.OK: logger.error("Request not success, status was %s" % self.response.status) return {} data = self.response.read() logger.info(data) self.sent = True return parser.parse(data.decode(), self.pvars) @staticmethod def sendRequest(host, port, path, headers, params, reqType="GET"): params = urlencode(params) path = path + "?"+ params if reqType == "GET" and params else path if len(headers): logger.debug(headers) if len(params): logger.debug(params) logger.debug("Opening connection to %s" % host); conn = httplib.HTTPSConnection(host ,port) if port == 443 else httplib.HTTPConnection(host ,port) logger.debug("Sending %s request to %s" % (reqType, path)) conn.request(reqType, path, params, headers); response = conn.getresponse() return response yowsup-2.4.48/yowsup/common/http/waresponseparser.py000066400000000000000000000103201263346463600227620ustar00rootroot00000000000000import json, sys from xml.dom import minidom import plistlib import logging logger = logging.getLogger(__name__) class ResponseParser(object): def __init__(self): self.meta = "*" def parse(self, text, pvars): return text def getMeta(self): return self.meta def getVars(self, pvars): if type(pvars) is dict: return pvars if type(pvars) is list: out = {} for p in pvars: out[p] = p return out class XMLResponseParser(ResponseParser): def __init__(self): try: import libxml2 except ImportError: print("libxml2 XMLResponseParser requires libxml2") sys.exit(1) self.meta = "text/xml"; def parse(self, xml, pvars): import libxml2 doc = libxml2.parseDoc(xml) pvars = self.getVars(pvars) vals = {} for k, v in pvars.items(): res = doc.xpathEval(v) vals[k] = [] for r in res: #if not vals.has_key(r.name): # vals[r.name] = [] if r.type == 'element': #vals[r.name].append(self.xmlToDict(minidom.parseString(str(r)))[r.name]) vals[k].append(self.xmlToDict(minidom.parseString(str(r)))[r.name]) elif r.type == 'attribute': vals[k].append(r.content) else: logger.error("UNKNOWN TYPE") if len(vals[k]) == 1: vals[k] = vals[k][0] elif len(vals[k]) == 0: vals[k] = None return vals def xmlToDict(self, xmlNode): if xmlNode.nodeName == "#document": node = {xmlNode.firstChild.nodeName:{}} node[xmlNode.firstChild.nodeName] = self.xmlToDict(xmlNode.firstChild) return node node = {} curr = node if xmlNode.attributes: for name, value in xmlNode.attributes.items(): curr[name] = value for n in xmlNode.childNodes: if n.nodeType == n.TEXT_NODE: curr["__TEXT__"] = n.data continue if not n.nodeName in curr: curr[n.nodeName] = [] if len(xmlNode.getElementsByTagName(n.nodeName)) > 1: #curr[n.nodeName] = [] curr[n.nodeName].append(self.xmlToDict(n)) else: curr[n.nodeName] = self.xmlToDict(n) return node class JSONResponseParser(ResponseParser): def __init__(self): self.meta = "text/json" def parse(self, jsonData, pvars): d = json.loads(jsonData) pvars = self.getVars(pvars) parsed = {} for k,v in pvars.items(): parsed[k] = self.query(d, v) return parsed def query(self, d, key): keys = key.split('.', 1) currKey = keys[0] if(currKey in d): item = d[currKey] if len(keys) == 1: return item if type(item) is dict: return self.query(item, keys[1]) elif type(item) is list: output = [] for i in item: output.append(self.query(i, keys[1])) return output else: return None class PListResponseParser(ResponseParser): def __init__(self): self.meta = "text/xml" def parse(self, xml, pvars): #tmp = minidom.parseString(xml) if sys.version_info >= (3, 0): pl = plistlib.readPlistFromBytes(xml.encode()); else: pl = plistlib.readPlistFromString(xml); parsed= {} pvars = self.getVars(pvars) for k,v in pvars.items(): parsed[k] = pl[k] if k in pl else None return parsed; yowsup-2.4.48/yowsup/common/tools.py000066400000000000000000000107111263346463600175440ustar00rootroot00000000000000import time,datetime,re, hashlib from dateutil import tz import os from .constants import YowConstants import codecs, sys import logging import tempfile import base64 import hashlib logger = logging.getLogger(__name__) class HexTools: decode_hex = codecs.getdecoder("hex_codec") @staticmethod def decodeHex(hexString): result = HexTools.decode_hex(hexString)[0] if sys.version_info >= (3,0): result = result.decode('latin-1') return result class WATools: @staticmethod def generateIdentity(): return os.urandom(20) @staticmethod def getFileHashForUpload(filePath): sha1 = hashlib.sha256() f = open(filePath, 'rb') try: sha1.update(f.read()) finally: f.close() b64Hash = base64.b64encode(sha1.digest()) return b64Hash if type(b64Hash) is str else b64Hash.decode() class StorageTools: @staticmethod def constructPath(*path): path = os.path.join(*path) fullPath = os.path.expanduser(os.path.join(YowConstants.PATH_STORAGE, path)) if not os.path.exists(os.path.dirname(fullPath)): os.makedirs(os.path.dirname(fullPath)) return fullPath @staticmethod def getStorageForPhone(phone): return StorageTools.constructPath(phone + '/') @staticmethod def writeIdentity(phone, identity): path = StorageTools.getStorageForPhone(phone) with open(os.path.join(path, "id"), 'wb') as idFile: idFile.write(identity) @staticmethod def getIdentity(phone): path = StorageTools.getStorageForPhone(phone) out = None idPath = os.path.join(path, "id") if os.path.isfile(idPath): with open(idPath, 'rb') as idFile: out = idFile.read() return out @staticmethod def writeNonce(phone, nonce): path = StorageTools.getStorageForPhone(phone) with open(os.path.join(path, "nonce"), 'wb') as idFile: idFile.write(nonce.encode("latin-1") if sys.version_info >= (3,0) else nonce) @staticmethod def getNonce(phone): path = StorageTools.getStorageForPhone(phone) out = None noncePath = os.path.join(path, "nonce") if os.path.isfile(noncePath): with open(noncePath, 'rb') as idFile: out = idFile.read() return out class TimeTools: @staticmethod def parseIso(iso): d=datetime.datetime(*map(int, re.split('[^\d]', iso)[:-1])) return d @staticmethod def utcToLocal(dt): utc = tz.gettz('UTC') local = tz.tzlocal() dtUtc = dt.replace(tzinfo=utc) return dtUtc.astimezone(local) @staticmethod def utcTimestamp(): #utc = tz.gettz('UTC') utcNow = datetime.datetime.utcnow() return TimeTools.datetimeToTimestamp(utcNow) @staticmethod def datetimeToTimestamp(dt): return time.mktime(dt.timetuple()) class ModuleTools: @staticmethod def INSTALLED_PIL(): try: import PIL return True except ImportError: return False @staticmethod def INSTALLED_AXOLOTL(): try: import axolotl return True except ImportError: return False class ImageTools: @staticmethod def scaleImage(infile, outfile, imageFormat, width, height): if ModuleTools.INSTALLED_PIL(): from PIL import Image im = Image.open(infile) #Convert P mode images if im.mode != "RGB": im = im.convert("RGB") im.thumbnail((width, height)) im.save(outfile, imageFormat) return True else: logger.warn("Python PIL library not installed") return False @staticmethod def getImageDimensions(imageFile): if ModuleTools.INSTALLED_PIL(): from PIL import Image im = Image.open(imageFile) return im.size else: logger.warn("Python PIL library not installed") @staticmethod def generatePreviewFromImage(image): fd, path = tempfile.mkstemp() preview = None if ImageTools.scaleImage(image, path, "JPEG", YowConstants.PREVIEW_WIDTH, YowConstants.PREVIEW_HEIGHT): fileObj = os.fdopen(fd, "rb+") fileObj.seek(0) preview = fileObj.read() fileObj.close() return preview yowsup-2.4.48/yowsup/demos/000077500000000000000000000000001263346463600156515ustar00rootroot00000000000000yowsup-2.4.48/yowsup/demos/__init__.py000066400000000000000000000000001263346463600177500ustar00rootroot00000000000000yowsup-2.4.48/yowsup/demos/cli/000077500000000000000000000000001263346463600164205ustar00rootroot00000000000000yowsup-2.4.48/yowsup/demos/cli/__init__.py000066400000000000000000000000421263346463600205250ustar00rootroot00000000000000from .stack import YowsupCliStack yowsup-2.4.48/yowsup/demos/cli/cli.py000066400000000000000000000136071263346463600175500ustar00rootroot00000000000000import threading, inspect, shlex try: import Queue except ImportError: import queue as Queue try: import readline except ImportError: import pyreadline as readline class clicmd(object): def __init__(self, desc, order = 0): self.desc = desc self.order = order def __call__(self, fn): fn.clidesc = self.desc fn.cliorder = self.order return fn class Cli(object): def __init__(self): self.sentCache = {} self.commands = {} self.acceptingInput = False self.lastPrompt = True self.blockingQueue = Queue.Queue() self._queuedCmds = [] readline.set_completer(self.complete) readline.parse_and_bind('tab: complete') members = inspect.getmembers(self, predicate = inspect.ismethod) for m in members: if hasattr(m[1], "clidesc"): fname = m[0] fn = m[1] try: cmd, subcommand = fname.split('_') except ValueError: cmd = fname subcommand = "_" if not cmd in self.commands: self.commands[cmd] = {} self.commands[cmd][subcommand] = { "args": inspect.getargspec(fn)[0][1:], "optional": len(inspect.getargspec(fn)[3]) if inspect.getargspec(fn)[3] else 0, "desc": fn.clidesc, "fn": fn, "order": fn.cliorder } #self.cv = threading.Condition() self.inputThread = threading.Thread(target = self.startInputThread) self.inputThread.daemon = True def queueCmd(self, cmd): self._queuedCmds.append(cmd) def startInput(self): self.inputThread.start() ################### cmd input parsing #################### def print_usage(self): line_width = 100 outArr = [] def addToOut(ind, cmd): if ind >= len(outArr): outArr.extend([None] * (ind - len(outArr) + 1)) if outArr[ind] != None: for i in range(len(outArr) - 1, 0, -1): if outArr[i] is None: outArr[i] = outArr[ind] outArr[ind] = cmd return outArr.append(cmd) else: outArr[ind] = cmd for cmd, subcommands in self.commands.items(): for subcmd, subcmdDetails in subcommands.items(): out = "" out += ("/%s " % cmd).ljust(15) out += ("%s " % subcmd if subcmd != "_" else "").ljust(15) args = ("%s " % " ".join(["<%s>" % c for c in subcmdDetails["args"][0:len(subcmdDetails["args"])-subcmdDetails["optional"]]])) args += ("%s " % " ".join(["[%s]" % c for c in subcmdDetails["args"][len(subcmdDetails["args"])-subcmdDetails["optional"]:]])) out += args.ljust(30) out += subcmdDetails["desc"].ljust(20) addToOut(subcmdDetails["order"], out) print("----------------------------------------------") print("\n" . join(outArr)) print("----------------------------------------------") def execCmd(self, cmdInput): cmdInput = cmdInput.rstrip() if not len(cmdInput) > 1: return if cmdInput.startswith("/"): cmdInput = cmdInput[1:] else: self.print_usage() return cmdInputDissect = [c for c in shlex.split(cmdInput) if c] cmd = cmdInputDissect[0] if not cmd in self.commands: return self.print_usage() cmdData = self.commands[cmd] if len(cmdData) == 1 and "_" in cmdData: subcmdData = cmdData["_"] args = cmdInputDissect[1:] if len(cmdInputDissect) > 1 else [] else: args = cmdInputDissect[2:] if len(cmdInputDissect) > 2 else [] subcmd = cmdInputDissect[1] if len(cmdInputDissect) > 1 else "" if subcmd not in cmdData: return self.print_usage() subcmdData = cmdData[subcmd] targetFn = subcmdData["fn"] if len(subcmdData["args"]) < len(args) or len(subcmdData["args"]) - subcmdData["optional"] > len(args): return self.print_usage() return self.doExecCmd(lambda :targetFn(*args)) def doExecCmd(self, fn): return fn() def startInputThread(self): #cv.acquire() # Fix Python 2.x. global input try: input = raw_input except NameError: pass while(True): cmd = self._queuedCmds.pop(0) if len(self._queuedCmds) else input(self.getPrompt()).strip() wait = self.execCmd(cmd) if wait: self.acceptingInput = False self.blockingQueue.get(True) #cv.wait() #self.inputThread.wait() self.acceptingInput = True #cv.release() def getPrompt(self): return "[%s]:" % ("connected" if self.connected else "offline") def printPrompt(self): #return "Enter Message or command: (/%s)" % ", /".join(self.commandMappings) print(self.getPrompt()) def output(self, message, tag = "general", prompt = True): if self.acceptingInput == True and self.lastPrompt is True: print("") self.lastPrompt = prompt if tag is not None: print("%s: %s" % (tag, message)) else: print(message) if prompt: self.printPrompt() def complete(self, text, state): if state == 0: for cmd in self.commands: if cmd.startswith(text) and cmd != text: return cmd def notifyInputThread(self): self.blockingQueue.put(1) if __name__ == "__main__": c = Cli() c.print_usage() yowsup-2.4.48/yowsup/demos/cli/layer.py000066400000000000000000000617001263346463600201120ustar00rootroot00000000000000from .cli import Cli, clicmd from yowsup.layers.interface import YowInterfaceLayer, ProtocolEntityCallback from yowsup.layers.auth import YowAuthenticationProtocolLayer from yowsup.layers import YowLayerEvent from yowsup.layers.network import YowNetworkLayer import sys from yowsup.common import YowConstants import datetime import os import logging from yowsup.layers.protocol_receipts.protocolentities import * from yowsup.layers.protocol_groups.protocolentities import * from yowsup.layers.protocol_presence.protocolentities import * from yowsup.layers.protocol_messages.protocolentities import * from yowsup.layers.protocol_acks.protocolentities import * from yowsup.layers.protocol_ib.protocolentities import * from yowsup.layers.protocol_iq.protocolentities import * from yowsup.layers.protocol_contacts.protocolentities import * from yowsup.layers.protocol_chatstate.protocolentities import * from yowsup.layers.protocol_privacy.protocolentities import * from yowsup.layers.protocol_media.protocolentities import * from yowsup.layers.protocol_media.mediauploader import MediaUploader from yowsup.layers.protocol_profiles.protocolentities import * from yowsup.common.tools import ModuleTools logger = logging.getLogger(__name__) class YowsupCliLayer(Cli, YowInterfaceLayer): PROP_RECEIPT_AUTO = "org.openwhatsapp.yowsup.prop.cli.autoreceipt" PROP_RECEIPT_KEEPALIVE = "org.openwhatsapp.yowsup.prop.cli.keepalive" PROP_CONTACT_JID = "org.openwhatsapp.yowsup.prop.cli.contact.jid" EVENT_LOGIN = "org.openwhatsapp.yowsup.event.cli.login" EVENT_START = "org.openwhatsapp.yowsup.event.cli.start" EVENT_SENDANDEXIT = "org.openwhatsapp.yowsup.event.cli.sendandexit" MESSAGE_FORMAT = "[{FROM}({TIME})]:[{MESSAGE_ID}]\t {MESSAGE}" DISCONNECT_ACTION_PROMPT = 0 DISCONNECT_ACTION_EXIT = 1 ACCOUNT_DEL_WARNINGS = 4 def __init__(self): super(YowsupCliLayer, self).__init__() YowInterfaceLayer.__init__(self) self.accountDelWarnings = 0 self.connected = False self.username = None self.sendReceipts = True self.sendRead = True self.disconnectAction = self.__class__.DISCONNECT_ACTION_PROMPT self.credentials = None #add aliases to make it user to use commands. for example you can then do: # /message send foobar "HI" # and then it will get automaticlaly mapped to foobar's jid self.jidAliases = { # "NAME": "PHONE@s.whatsapp.net" } def aliasToJid(self, calias): for alias, ajid in self.jidAliases.items(): if calias.lower() == alias.lower(): return self.normalizeJid(ajid) return self.normalizeJid(calias) def jidToAlias(self, jid): for alias, ajid in self.jidAliases.items(): if ajid == jid: return alias return jid def normalizeJid(self, number): if '@' in number: return number elif "-" in number: return "%s@g.us" % number return "%s@s.whatsapp.net" % number def setCredentials(self, username, password): self.getLayerInterface(YowAuthenticationProtocolLayer).setCredentials(username, password) def onEvent(self, layerEvent): if layerEvent.getName() == self.__class__.EVENT_START: self.startInput() return True elif layerEvent.getName() == self.__class__.EVENT_SENDANDEXIT: credentials = layerEvent.getArg("credentials") target = layerEvent.getArg("target") message = layerEvent.getArg("message") self.sendMessageAndDisconnect(credentials, target, message) return True elif layerEvent.getName() == YowNetworkLayer.EVENT_STATE_DISCONNECTED: self.output("Disconnected: %s" % layerEvent.getArg("reason")) if self.disconnectAction == self.__class__.DISCONNECT_ACTION_PROMPT: self.connected = False self.notifyInputThread() else: os._exit(os.EX_OK) def assertConnected(self): if self.connected: return True else: self.output("Not connected", tag = "Error", prompt = False) return False #### batch cmds ##### def sendMessageAndDisconnect(self, credentials, jid, message): self.disconnectAction = self.__class__.DISCONNECT_ACTION_EXIT self.queueCmd("/login %s %s" % credentials) self.queueCmd("/message send %s \"%s\" wait" % (jid, message)) self.queueCmd("/disconnect") self.startInput() ########## PRESENCE ############### @clicmd("Set presence name") def presence_name(self, name): if self.assertConnected(): entity = PresenceProtocolEntity(name = name) self.toLower(entity) @clicmd("Set presence as available") def presence_available(self): if self.assertConnected(): entity = AvailablePresenceProtocolEntity() self.toLower(entity) @clicmd("Set presence as unavailable") def presence_unavailable(self): if self.assertConnected(): entity = UnavailablePresenceProtocolEntity() self.toLower(entity) @clicmd("Unsubscribe from contact's presence updates") def presence_unsubscribe(self, contact): if self.assertConnected(): entity = UnsubscribePresenceProtocolEntity(self.aliasToJid(contact)) self.toLower(entity) @clicmd("Subscribe to contact's presence updates") def presence_subscribe(self, contact): if self.assertConnected(): entity = SubscribePresenceProtocolEntity(self.aliasToJid(contact)) self.toLower(entity) ########### END PRESENCE ############# ########### ib ####################### @clicmd("Send clean dirty") def ib_clean(self, dirtyType): if self.assertConnected(): entity = CleanIqProtocolEntity("groups", YowConstants.DOMAIN) self.toLower(entity) @clicmd("Ping server") def ping(self): if self.assertConnected(): entity = PingIqProtocolEntity(to = YowConstants.DOMAIN) self.toLower(entity) ###################################### ####### contacts/ profiles #################### @clicmd("Set status text") def profile_setStatus(self, text): if self.assertConnected(): def onSuccess(resultIqEntity, originalIqEntity): self.output("Status updated successfully") def onError(errorIqEntity, originalIqEntity): logger.error("Error updating status") entity = SetStatusIqProtocolEntity(text) self._sendIq(entity, onSuccess, onError) @clicmd("Get profile picture for contact") def contact_picture(self, jid): if self.assertConnected(): entity = GetPictureIqProtocolEntity(self.aliasToJid(jid), preview=False) self._sendIq(entity, self.onGetContactPictureResult) @clicmd("Get profile picture preview for contact") def contact_picturePreview(self, jid): if self.assertConnected(): entity = GetPictureIqProtocolEntity(self.aliasToJid(jid), preview=True) self._sendIq(entity, self.onGetContactPictureResult) @clicmd("Get lastseen for contact") def contact_lastseen(self, jid): if self.assertConnected(): def onSuccess(resultIqEntity, originalIqEntity): self.output("%s lastseen %s seconds ago" % (resultIqEntity.getFrom(), resultIqEntity.getSeconds())) def onError(errorIqEntity, originalIqEntity): logger.error("Error getting lastseen information for %s" % originalIqEntity.getTo()) entity = LastseenIqProtocolEntity(self.aliasToJid(jid)) self._sendIq(entity, onSuccess, onError) @clicmd("Set profile picture") def profile_setPicture(self, path): if self.assertConnected() and ModuleTools.INSTALLED_PIL(): def onSuccess(resultIqEntity, originalIqEntity): self.output("Profile picture updated successfully") def onError(errorIqEntity, originalIqEntity): logger.error("Error updating profile picture") #example by @aesedepece in https://github.com/tgalal/yowsup/pull/781 #modified to support python3 from PIL import Image src = Image.open(path) pictureData = src.resize((640, 640)).tobytes("jpeg", "RGB") picturePreview = src.resize((96, 96)).tobytes("jpeg", "RGB") iq = SetPictureIqProtocolEntity(self.getOwnJid(), picturePreview, pictureData) self._sendIq(iq, onSuccess, onError) else: logger.error("Python PIL library is not installed, can't set profile picture") @clicmd("Get profile privacy") def profile_getPrivacy(self): if self.assertConnected(): def onSuccess(resultIqEntity, originalIqEntity): self.output("Profile privacy is: %s" %(resultIqEntity)) def onError(errorIqEntity, originalIqEntity): logger.error("Error getting profile privacy") iq = GetPrivacyIqProtocolEntity() self._sendIq(iq, onSuccess, onError) @clicmd("Profile privacy. value=all|contacts|none names=profile|status|last. Names are comma separated, defaults to all.") def profile_setPrivacy(self, value="all", names=None): if self.assertConnected(): def onSuccess(resultIqEntity, originalIqEntity): self.output("Profile privacy set to: %s" %(resultIqEntity)) def onError(errorIqEntity, originalIqEntity): logger.error("Error setting profile privacy") try: names = [name for name in names.split(',')] if names else None iq = SetPrivacyIqProtocolEntity(value, names) self._sendIq(iq, onSuccess, onError) except Exception as inst: self.output(inst.message) return self.print_usage() ########### groups @clicmd("List all groups you belong to", 5) def groups_list(self): if self.assertConnected(): entity = ListGroupsIqProtocolEntity() self.toLower(entity) @clicmd("Leave a group you belong to", 4) def group_leave(self, group_jid): if self.assertConnected(): entity = LeaveGroupsIqProtocolEntity([self.aliasToJid(group_jid)]) self.toLower(entity) @clicmd("Create a new group with the specified subject and participants. Jids are a comma separated list but optional.", 3) def groups_create(self, subject, jids = None): if self.assertConnected(): jids = [self.aliasToJid(jid) for jid in jids.split(',')] if jids else [] entity = CreateGroupsIqProtocolEntity(subject, participants=jids) self.toLower(entity) @clicmd("Invite to group. Jids are a comma separated list") def group_invite(self, group_jid, jids): if self.assertConnected(): jids = [self.aliasToJid(jid) for jid in jids.split(',')] entity = AddParticipantsIqProtocolEntity(self.aliasToJid(group_jid), jids) self.toLower(entity) @clicmd("Promote admin of a group. Jids are a comma separated list") def group_promote(self, group_jid, jids): if self.assertConnected(): jids = [self.aliasToJid(jid) for jid in jids.split(',')] entity = PromoteParticipantsIqProtocolEntity(self.aliasToJid(group_jid), jids) self.toLower(entity) @clicmd("Remove admin of a group. Jids are a comma separated list") def group_demote(self, group_jid, jids): if self.assertConnected(): jids = [self.aliasToJid(jid) for jid in jids.split(',')] entity = DemoteParticipantsIqProtocolEntity(self.aliasToJid(group_jid), jids) self.toLower(entity) @clicmd("Kick from group. Jids are a comma separated list") def group_kick(self, group_jid, jids): if self.assertConnected(): jids = [self.aliasToJid(jid) for jid in jids.split(',')] entity = RemoveParticipantsIqProtocolEntity(self.aliasToJid(group_jid), jids) self.toLower(entity) @clicmd("Change group subject") def group_setSubject(self, group_jid, subject): if self.assertConnected(): entity = SubjectGroupsIqProtocolEntity(self.aliasToJid(group_jid), subject) self.toLower(entity) @clicmd("Set group picture") def group_picture(self, group_jid, path): if self.assertConnected() and ModuleTools.INSTALLED_PIL(): def onSuccess(resultIqEntity, originalIqEntity): self.output("Group picture updated successfully") def onError(errorIqEntity, originalIqEntity): logger.error("Error updating Group picture") #example by @aesedepece in https://github.com/tgalal/yowsup/pull/781 #modified to support python3 from PIL import Image src = Image.open(path) pictureData = src.resize((640, 640)).tobytes("jpeg", "RGB") picturePreview = src.resize((96, 96)).tobytes("jpeg", "RGB") iq = SetPictureIqProtocolEntity(self.aliasToJid(group_jid), picturePreview, pictureData) self._sendIq(iq, onSuccess, onError) else: logger.error("Python PIL library is not installed, can't set profile picture") @clicmd("Get group info") def group_info(self, group_jid): if self.assertConnected(): entity = InfoGroupsIqProtocolEntity(self.aliasToJid(group_jid)) self.toLower(entity) @clicmd("Get shared keys") def keys_get(self, jids): if ModuleTools.INSTALLED_AXOLOTL(): from yowsup.layers.axolotl.protocolentities.iq_key_get import GetKeysIqProtocolEntity if self.assertConnected(): jids = [self.aliasToJid(jid) for jid in jids.split(',')] entity = GetKeysIqProtocolEntity(jids) self.toLower(entity) else: logger.error("Axolotl is not installed") @clicmd("Send prekeys") def keys_set(self): if ModuleTools.INSTALLED_AXOLOTL(): from yowsup.layers.axolotl import YowAxolotlLayer if self.assertConnected(): self.broadcastEvent(YowLayerEvent(YowAxolotlLayer.EVENT_PREKEYS_SET)) else: logger.error("Axolotl is not installed") @clicmd("Send init seq") def seq(self): priv = PrivacyListIqProtocolEntity() self.toLower(priv) push = PushIqProtocolEntity() self.toLower(push) props = PropsIqProtocolEntity() self.toLower(props) crypto = CryptoIqProtocolEntity() self.toLower(crypto) @clicmd("Delete your account") def account_delete(self): if self.assertConnected(): if self.accountDelWarnings < self.__class__.ACCOUNT_DEL_WARNINGS: self.accountDelWarnings += 1 remaining = self.__class__.ACCOUNT_DEL_WARNINGS - self.accountDelWarnings self.output("Repeat delete command another %s times to send the delete request" % remaining, tag="Account delete Warning !!", prompt = False) else: entity = UnregisterIqProtocolEntity() self.toLower(entity) @clicmd("Send message to a friend") def message_send(self, number, content): if self.assertConnected(): outgoingMessage = TextMessageProtocolEntity(content.encode("utf-8") if sys.version_info >= (3,0) else content, to = self.aliasToJid(number)) self.toLower(outgoingMessage) @clicmd("Broadcast message. numbers should comma separated phone numbers") def message_broadcast(self, numbers, content): if self.assertConnected(): jids = [self.aliasToJid(number) for number in numbers.split(',')] outgoingMessage = BroadcastTextMessage(jids, content) self.toLower(outgoingMessage) #@clicmd("Send read receipt") def message_read(self, message_id): pass #@clicmd("Send delivered receipt") def message_delivered(self, message_id): pass @clicmd("Send an image with optional caption") def image_send(self, number, path, caption = None): if self.assertConnected(): jid = self.aliasToJid(number) entity = RequestUploadIqProtocolEntity(RequestUploadIqProtocolEntity.MEDIA_TYPE_IMAGE, filePath=path) successFn = lambda successEntity, originalEntity: self.onRequestUploadResult(jid, path, successEntity, originalEntity, caption) errorFn = lambda errorEntity, originalEntity: self.onRequestUploadError(jid, path, errorEntity, originalEntity) self._sendIq(entity, successFn, errorFn) @clicmd("Send audio file") def audio_send(self, number, path): if self.assertConnected(): jid = self.aliasToJid(number) entity = RequestUploadIqProtocolEntity(RequestUploadIqProtocolEntity.MEDIA_TYPE_AUDIO, filePath=path) successFn = lambda successEntity, originalEntity: self.onRequestUploadResult(jid, path, successEntity, originalEntity) errorFn = lambda errorEntity, originalEntity: self.onRequestUploadError(jid, path, errorEntity, originalEntity) self._sendIq(entity, successFn, errorFn) @clicmd("Send typing state") def state_typing(self, jid): if self.assertConnected(): entity = OutgoingChatstateProtocolEntity(ChatstateProtocolEntity.STATE_TYPING, self.aliasToJid(jid)) self.toLower(entity) @clicmd("Request contacts statuses") def statuses_get(self, contacts): if self.assertConnected(): entity = GetStatusesIqProtocolEntity([self.aliasToJid(c) for c in contacts.split(',')]) self.toLower(entity) @clicmd("Send paused state") def state_paused(self, jid): if self.assertConnected(): entity = OutgoingChatstateProtocolEntity(ChatstateProtocolEntity.STATE_PAUSED, self.aliasToJid(jid)) self.toLower(entity) @clicmd("Sync contacts, contacts should be comma separated phone numbers, with no spaces") def contacts_sync(self, contacts): if self.assertConnected(): entity = GetSyncIqProtocolEntity(contacts.split(',')) self.toLower(entity) @clicmd("Disconnect") def disconnect(self): if self.assertConnected(): self.broadcastEvent(YowLayerEvent(YowNetworkLayer.EVENT_STATE_DISCONNECT)) @clicmd("Quick login") def L(self): if self.connected: return self.output("Already connected, disconnect first") self.getLayerInterface(YowNetworkLayer).connect() return True @clicmd("Login to WhatsApp", 0) def login(self, username, b64password): self.setCredentials(username, b64password) return self.L() ######## receive ######### @ProtocolEntityCallback("chatstate") def onChatstate(self, entity): print(entity) @ProtocolEntityCallback("iq") def onIq(self, entity): print(entity) @ProtocolEntityCallback("receipt") def onReceipt(self, entity): self.toLower(entity.ack()) @ProtocolEntityCallback("ack") def onAck(self, entity): #formattedDate = datetime.datetime.fromtimestamp(self.sentCache[entity.getId()][0]).strftime('%d-%m-%Y %H:%M') #print("%s [%s]:%s"%(self.username, formattedDate, self.sentCache[entity.getId()][1])) if entity.getClass() == "message": self.output(entity.getId(), tag = "Sent") #self.notifyInputThread() @ProtocolEntityCallback("success") def onSuccess(self, entity): self.connected = True self.output("Logged in!", "Auth", prompt = False) self.notifyInputThread() @ProtocolEntityCallback("failure") def onFailure(self, entity): self.connected = False self.output("Login Failed, reason: %s" % entity.getReason(), prompt = False) @ProtocolEntityCallback("notification") def onNotification(self, notification): notificationData = notification.__str__() if notificationData: self.output(notificationData, tag = "Notification") else: self.output("From :%s, Type: %s" % (self.jidToAlias(notification.getFrom()), notification.getType()), tag = "Notification") if self.sendReceipts: self.toLower(notification.ack()) @ProtocolEntityCallback("message") def onMessage(self, message): messageOut = "" if message.getType() == "text": #self.output(message.getBody(), tag = "%s [%s]"%(message.getFrom(), formattedDate)) messageOut = self.getTextMessageBody(message) elif message.getType() == "media": messageOut = self.getMediaMessageBody(message) else: messageOut = "Unknown message type %s " % message.getType() print(messageOut.toProtocolTreeNode()) formattedDate = datetime.datetime.fromtimestamp(message.getTimestamp()).strftime('%d-%m-%Y %H:%M') sender = message.getFrom() if not message.isGroupMessage() else "%s/%s" % (message.getParticipant(False), message.getFrom()) output = self.__class__.MESSAGE_FORMAT.format( FROM = sender, TIME = formattedDate, MESSAGE = messageOut.encode('latin-1').decode() if sys.version_info >= (3, 0) else messageOut, MESSAGE_ID = message.getId() ) self.output(output, tag = None, prompt = not self.sendReceipts) if self.sendReceipts: self.toLower(message.ack(self.sendRead)) self.output("Sent delivered receipt"+" and Read" if self.sendRead else "", tag = "Message %s" % message.getId()) def getTextMessageBody(self, message): return message.getBody() def getMediaMessageBody(self, message): if message.getMediaType() in ("image", "audio", "video"): return self.getDownloadableMediaMessageBody(message) else: return "[Media Type: %s]" % message.getMediaType() def getDownloadableMediaMessageBody(self, message): return "[Media Type:{media_type}, Size:{media_size}, URL:{media_url}]".format( media_type = message.getMediaType(), media_size = message.getMediaSize(), media_url = message.getMediaUrl() ) def doSendImage(self, filePath, url, to, ip = None, caption = None): entity = ImageDownloadableMediaMessageProtocolEntity.fromFilePath(filePath, url, ip, to, caption = caption) self.toLower(entity) def doSendAudio(self, filePath, url, to, ip = None, caption = None): entity = AudioDownloadableMediaMessageProtocolEntity.fromFilePath(filePath, url, ip, to) self.toLower(entity) def __str__(self): return "CLI Interface Layer" ########### callbacks ############ def onRequestUploadResult(self, jid, filePath, resultRequestUploadIqProtocolEntity, requestUploadIqProtocolEntity, caption = None): if requestUploadIqProtocolEntity.mediaType == RequestUploadIqProtocolEntity.MEDIA_TYPE_AUDIO: doSendFn = self.doSendAudio else: doSendFn = self.doSendImage if resultRequestUploadIqProtocolEntity.isDuplicate(): doSendFn(filePath, resultRequestUploadIqProtocolEntity.getUrl(), jid, resultRequestUploadIqProtocolEntity.getIp(), caption) else: successFn = lambda filePath, jid, url: doSendFn(filePath, url, jid, resultRequestUploadIqProtocolEntity.getIp(), caption) mediaUploader = MediaUploader(jid, self.getOwnJid(), filePath, resultRequestUploadIqProtocolEntity.getUrl(), resultRequestUploadIqProtocolEntity.getResumeOffset(), successFn, self.onUploadError, self.onUploadProgress, async=False) mediaUploader.start() def onRequestUploadError(self, jid, path, errorRequestUploadIqProtocolEntity, requestUploadIqProtocolEntity): logger.error("Request upload for file %s for %s failed" % (path, jid)) def onUploadError(self, filePath, jid, url): logger.error("Upload file %s to %s for %s failed!" % (filePath, url, jid)) def onUploadProgress(self, filePath, jid, url, progress): sys.stdout.write("%s => %s, %d%% \r" % (os.path.basename(filePath), jid, progress)) sys.stdout.flush() def onGetContactPictureResult(self, resultGetPictureIqProtocolEntiy, getPictureIqProtocolEntity): # do here whatever you want # write to a file # or open # or do nothing # write to file example: #resultGetPictureIqProtocolEntiy.writeToFile("/tmp/yowpics/%s_%s.jpg" % (getPictureIqProtocolEntity.getTo(), "preview" if resultGetPictureIqProtocolEntiy.isPreview() else "full")) pass def __str__(self): return "CLI Interface Layer" @clicmd("Print this message") def help(self): self.print_usage() yowsup-2.4.48/yowsup/demos/cli/stack.py000066400000000000000000000020161263346463600200760ustar00rootroot00000000000000from yowsup.stacks import YowStackBuilder from .layer import YowsupCliLayer from yowsup.layers.auth import AuthError from yowsup.layers import YowLayerEvent from yowsup.layers.auth import YowAuthenticationProtocolLayer import sys class YowsupCliStack(object): def __init__(self, credentials, encryptionEnabled = True): stackBuilder = YowStackBuilder() self.stack = stackBuilder\ .pushDefaultLayers(encryptionEnabled)\ .push(YowsupCliLayer)\ .build() # self.stack.setCredentials(credentials) self.stack.setCredentials(credentials) def start(self): print("Yowsup Cli client\n==================\nType /help for available commands\n") self.stack.broadcastEvent(YowLayerEvent(YowsupCliLayer.EVENT_START)) try: self.stack.loop(timeout = 0.5, discrete = 0.5) except AuthError as e: print("Auth Error, reason %s" % e) except KeyboardInterrupt: print("\nYowsdown") sys.exit(0) yowsup-2.4.48/yowsup/demos/contacts/000077500000000000000000000000001263346463600174675ustar00rootroot00000000000000yowsup-2.4.48/yowsup/demos/contacts/__init__.py000066400000000000000000000000431263346463600215750ustar00rootroot00000000000000from .stack import YowsupSyncStack yowsup-2.4.48/yowsup/demos/contacts/layer.py000066400000000000000000000023161263346463600211570ustar00rootroot00000000000000from yowsup.layers.interface import YowInterfaceLayer, ProtocolEntityCallback from yowsup.layers.protocol_contacts.protocolentities import GetSyncIqProtocolEntity, ResultSyncIqProtocolEntity from yowsup.layers.protocol_iq.protocolentities import ErrorIqProtocolEntity import threading import logging logger = logging.getLogger(__name__) class SyncLayer(YowInterfaceLayer): PROP_CONTACTS = "org.openwhatsapp.yowsup.prop.syncdemo.contacts" def __init__(self): super(SyncLayer, self).__init__() #call back function when there is a successful connection to whatsapp server @ProtocolEntityCallback("success") def onSuccess(self, successProtocolEntity): contacts= self.getProp(self.__class__.PROP_CONTACTS, []) contactEntity = GetSyncIqProtocolEntity(contacts) self._sendIq(contactEntity, self.onGetSyncResult, self.onGetSyncError) def onGetSyncResult(self, resultSyncIqProtocolEntity, originalIqProtocolEntity): print(resultSyncIqProtocolEntity) raise KeyboardInterrupt() def onGetSyncError(self, errorSyncIqProtocolEntity, originalIqProtocolEntity): print(errorSyncIqProtocolEntity) raise KeyboardInterrupt() yowsup-2.4.48/yowsup/demos/contacts/stack.py000066400000000000000000000045511263346463600211530ustar00rootroot00000000000000from yowsup.stacks import YowStack from .layer import SyncLayer from yowsup.layers import YowLayerEvent from yowsup.layers.auth import YowCryptLayer, YowAuthenticationProtocolLayer, AuthError from yowsup.layers.coder import YowCoderLayer from yowsup.layers.network import YowNetworkLayer from yowsup.layers.stanzaregulator import YowStanzaRegulator from yowsup.layers.protocol_receipts import YowReceiptProtocolLayer from yowsup.layers.protocol_acks import YowAckProtocolLayer from yowsup.layers.logger import YowLoggerLayer from yowsup.layers.protocol_contacts import YowContactsIqProtocolLayer from yowsup.layers import YowParallelLayer class YowsupSyncStack(object): def __init__(self, credentials, contacts, encryptionEnabled = False): """ :param credentials: :param contacts: list of [jid ] :param encryptionEnabled: :return: """ if encryptionEnabled: from yowsup.layers.axolotl import YowAxolotlLayer layers = ( SyncLayer, YowParallelLayer([YowAuthenticationProtocolLayer, YowContactsIqProtocolLayer, YowReceiptProtocolLayer, YowAckProtocolLayer]), YowAxolotlLayer, YowLoggerLayer, YowCoderLayer, YowCryptLayer, YowStanzaRegulator, YowNetworkLayer ) else: layers = ( SyncLayer, YowParallelLayer([YowAuthenticationProtocolLayer, YowContactsIqProtocolLayer, YowReceiptProtocolLayer, YowAckProtocolLayer]), YowLoggerLayer, YowCoderLayer, YowCryptLayer, YowStanzaRegulator, YowNetworkLayer ) self.stack = YowStack(layers) self.stack.setProp(SyncLayer.PROP_CONTACTS, contacts) self.stack.setProp(YowAuthenticationProtocolLayer.PROP_PASSIVE, True) self.stack.setCredentials(credentials) def start(self): self.stack.broadcastEvent(YowLayerEvent(YowNetworkLayer.EVENT_STATE_CONNECT)) try: self.stack.loop() except AuthError as e: print("Authentication Error: %s" % e.message) yowsup-2.4.48/yowsup/demos/echoclient/000077500000000000000000000000001263346463600177665ustar00rootroot00000000000000yowsup-2.4.48/yowsup/demos/echoclient/__init__.py000066400000000000000000000000421263346463600220730ustar00rootroot00000000000000from .stack import YowsupEchoStackyowsup-2.4.48/yowsup/demos/echoclient/layer.py000066400000000000000000000031561263346463600214610ustar00rootroot00000000000000from yowsup.layers.interface import YowInterfaceLayer, ProtocolEntityCallback class EchoLayer(YowInterfaceLayer): @ProtocolEntityCallback("message") def onMessage(self, messageProtocolEntity): if messageProtocolEntity.getType() == 'text': self.onTextMessage(messageProtocolEntity) elif messageProtocolEntity.getType() == 'media': self.onMediaMessage(messageProtocolEntity) self.toLower(messageProtocolEntity.forward(messageProtocolEntity.getFrom())) self.toLower(messageProtocolEntity.ack()) self.toLower(messageProtocolEntity.ack(True)) @ProtocolEntityCallback("receipt") def onReceipt(self, entity): self.toLower(entity.ack()) def onTextMessage(self,messageProtocolEntity): # just print info print("Echoing %s to %s" % (messageProtocolEntity.getBody(), messageProtocolEntity.getFrom(False))) def onMediaMessage(self, messageProtocolEntity): # just print info if messageProtocolEntity.getMediaType() == "image": print("Echoing image %s to %s" % (messageProtocolEntity.url, messageProtocolEntity.getFrom(False))) elif messageProtocolEntity.getMediaType() == "location": print("Echoing location (%s, %s) to %s" % (messageProtocolEntity.getLatitude(), messageProtocolEntity.getLongitude(), messageProtocolEntity.getFrom(False))) elif messageProtocolEntity.getMediaType() == "vcard": print("Echoing vcard (%s, %s) to %s" % (messageProtocolEntity.getName(), messageProtocolEntity.getCardData(), messageProtocolEntity.getFrom(False))) yowsup-2.4.48/yowsup/demos/echoclient/stack.py000066400000000000000000000046431263346463600214540ustar00rootroot00000000000000from yowsup.stacks import YowStack from .layer import EchoLayer from yowsup.layers import YowLayerEvent from yowsup.layers.auth import YowCryptLayer, YowAuthenticationProtocolLayer, AuthError from yowsup.layers.coder import YowCoderLayer from yowsup.layers.network import YowNetworkLayer from yowsup.layers.protocol_messages import YowMessagesProtocolLayer from yowsup.layers.protocol_media import YowMediaProtocolLayer from yowsup.layers.stanzaregulator import YowStanzaRegulator from yowsup.layers.protocol_receipts import YowReceiptProtocolLayer from yowsup.layers.protocol_acks import YowAckProtocolLayer from yowsup.layers.logger import YowLoggerLayer from yowsup.layers.protocol_iq import YowIqProtocolLayer from yowsup.layers.protocol_calls import YowCallsProtocolLayer from yowsup.layers import YowParallelLayer class YowsupEchoStack(object): def __init__(self, credentials, encryptionEnabled = False): if encryptionEnabled: from yowsup.layers.axolotl import YowAxolotlLayer layers = ( EchoLayer, YowParallelLayer([YowAuthenticationProtocolLayer, YowMessagesProtocolLayer, YowReceiptProtocolLayer, YowAckProtocolLayer, YowMediaProtocolLayer, YowIqProtocolLayer, YowCallsProtocolLayer]), YowAxolotlLayer, YowLoggerLayer, YowCoderLayer, YowCryptLayer, YowStanzaRegulator, YowNetworkLayer ) else: layers = ( EchoLayer, YowParallelLayer([YowAuthenticationProtocolLayer, YowMessagesProtocolLayer, YowReceiptProtocolLayer, YowAckProtocolLayer, YowMediaProtocolLayer, YowIqProtocolLayer, YowCallsProtocolLayer]), YowLoggerLayer, YowCoderLayer, YowCryptLayer, YowStanzaRegulator, YowNetworkLayer ) self.stack = YowStack(layers) self.stack.setCredentials(credentials) def start(self): self.stack.broadcastEvent(YowLayerEvent(YowNetworkLayer.EVENT_STATE_CONNECT)) try: self.stack.loop() except AuthError as e: print("Authentication Error: %s" % e.message) yowsup-2.4.48/yowsup/demos/sendclient/000077500000000000000000000000001263346463600200015ustar00rootroot00000000000000yowsup-2.4.48/yowsup/demos/sendclient/__init__.py000066400000000000000000000000421263346463600221060ustar00rootroot00000000000000from .stack import YowsupSendStackyowsup-2.4.48/yowsup/demos/sendclient/layer.py000066400000000000000000000043001263346463600214640ustar00rootroot00000000000000from yowsup.layers.interface import YowInterfaceLayer, ProtocolEntityCallback from yowsup.layers.protocol_messages.protocolentities import TextMessageProtocolEntity import threading import logging logger = logging.getLogger(__name__) class SendLayer(YowInterfaceLayer): #This message is going to be replaced by the @param message in YowsupSendStack construction #i.e. list of (jid, message) tuples PROP_MESSAGES = "org.openwhatsapp.yowsup.prop.sendclient.queue" def __init__(self): super(SendLayer, self).__init__() self.ackQueue = [] self.lock = threading.Condition() #call back function when there is a successful connection to whatsapp server @ProtocolEntityCallback("success") def onSuccess(self, successProtocolEntity): self.lock.acquire() for target in self.getProp(self.__class__.PROP_MESSAGES, []): #getProp() is trying to retreive the list of (jid, message) tuples, if none exist, use the default [] phone, message = target if '@' in phone: messageEntity = TextMessageProtocolEntity(message, to = phone) elif '-' in phone: messageEntity = TextMessageProtocolEntity(message, to = "%s@g.us" % phone) else: messageEntity = TextMessageProtocolEntity(message, to = "%s@s.whatsapp.net" % phone) #append the id of message to ackQueue list #which the id of message will be deleted when ack is received. self.ackQueue.append(messageEntity.getId()) self.toLower(messageEntity) self.lock.release() #after receiving the message from the target number, target number will send a ack to sender(us) @ProtocolEntityCallback("ack") def onAck(self, entity): self.lock.acquire() #if the id match the id in ackQueue, then pop the id of the message out if entity.getId() in self.ackQueue: self.ackQueue.pop(self.ackQueue.index(entity.getId())) if not len(self.ackQueue): self.lock.release() logger.info("Message sent") raise KeyboardInterrupt() self.lock.release() yowsup-2.4.48/yowsup/demos/sendclient/stack.py000066400000000000000000000045631263346463600214700ustar00rootroot00000000000000from yowsup.stacks import YowStack from .layer import SendLayer from yowsup.layers import YowLayerEvent from yowsup.layers.auth import YowCryptLayer, YowAuthenticationProtocolLayer, AuthError from yowsup.layers.coder import YowCoderLayer from yowsup.layers.network import YowNetworkLayer from yowsup.layers.protocol_messages import YowMessagesProtocolLayer from yowsup.layers.stanzaregulator import YowStanzaRegulator from yowsup.layers.protocol_receipts import YowReceiptProtocolLayer from yowsup.layers.protocol_acks import YowAckProtocolLayer from yowsup.layers.logger import YowLoggerLayer from yowsup.layers import YowParallelLayer class YowsupSendStack(object): def __init__(self, credentials, messages, encryptionEnabled = False): """ :param credentials: :param messages: list of (jid, message) tuples :param encryptionEnabled: :return: """ if encryptionEnabled: from yowsup.layers.axolotl import YowAxolotlLayer layers = ( SendLayer, YowParallelLayer([YowAuthenticationProtocolLayer, YowMessagesProtocolLayer, YowReceiptProtocolLayer, YowAckProtocolLayer]), YowAxolotlLayer, YowLoggerLayer, YowCoderLayer, YowCryptLayer, YowStanzaRegulator, YowNetworkLayer ) else: layers = ( SendLayer, YowParallelLayer([YowAuthenticationProtocolLayer, YowMessagesProtocolLayer, YowReceiptProtocolLayer, YowAckProtocolLayer]), YowLoggerLayer, YowCoderLayer, YowCryptLayer, YowStanzaRegulator, YowNetworkLayer ) self.stack = YowStack(layers) self.stack.setProp(SendLayer.PROP_MESSAGES, messages) self.stack.setProp(YowAuthenticationProtocolLayer.PROP_PASSIVE, True) self.stack.setCredentials(credentials) def start(self): self.stack.broadcastEvent(YowLayerEvent(YowNetworkLayer.EVENT_STATE_CONNECT)) try: self.stack.loop() except AuthError as e: print("Authentication Error: %s" % e.message) yowsup-2.4.48/yowsup/env/000077500000000000000000000000001263346463600153325ustar00rootroot00000000000000yowsup-2.4.48/yowsup/env/__init__.py000066400000000000000000000001521263346463600174410ustar00rootroot00000000000000from .env_android import AndroidYowsupEnv from .env_s40 import S40YowsupEnv CURRENT_ENV = S40YowsupEnv() yowsup-2.4.48/yowsup/env/env.py000066400000000000000000000016511263346463600164770ustar00rootroot00000000000000import abc class YowsupEnv(object): __metaclass__ = abc.ABCMeta _USERAGENT_STRING = "WhatsApp/{WHATSAPP_VERSION} {OS_NAME}/{OS_VERSION} Device/{DEVICE_NAME}" @abc.abstractmethod def getToken(self, phoneNumber): pass @abc.abstractmethod def getVersion(self): pass @abc.abstractmethod def getOSVersion(self): pass @abc.abstractmethod def getOSName(self): pass @abc.abstractmethod def getDeviceName(self): pass @abc.abstractmethod def isAxolotlEnabled(self): pass def getResource(self): return self.getOSName() + "-" + self.getVersion() def getUserAgent(self): return self.__class__._USERAGENT_STRING.format( WHATSAPP_VERSION = self.getVersion(), OS_NAME = self.getOSName(), OS_VERSION = self.getOSVersion(), DEVICE_NAME = self.getDeviceName() ) yowsup-2.4.48/yowsup/env/env_android.py000066400000000000000000000054271263346463600202040ustar00rootroot00000000000000from .env import YowsupEnv import base64 import hashlib class AndroidYowsupEnv(YowsupEnv): _SIGNATURE = "MIIDMjCCAvCgAwIBAgIETCU2pDALBgcqhkjOOAQDBQAwfDELMAkGA1UEBhMCVVMxEzARBgNVBAgTCkNhbGlmb3JuaWExFDASBgNV" \ "BAcTC1NhbnRhIENsYXJhMRYwFAYDVQQKEw1XaGF0c0FwcCBJbmMuMRQwEgYDVQQLEwtFbmdpbmVlcmluZzEUMBIGA1UEAxMLQnJ" \ "pYW4gQWN0b24wHhcNMTAwNjI1MjMwNzE2WhcNNDQwMjE1MjMwNzE2WjB8MQswCQYDVQQGEwJVUzETMBEGA1UECBMKQ2FsaWZvcm5" \ "pYTEUMBIGA1UEBxMLU2FudGEgQ2xhcmExFjAUBgNVBAoTDVdoYXRzQXBwIEluYy4xFDASBgNVBAsTC0VuZ2luZWVyaW5nMRQwEg" \ "YDVQQDEwtCcmlhbiBBY3RvbjCCAbgwggEsBgcqhkjOOAQBMIIBHwKBgQD9f1OBHXUSKVLfSpwu7OTn9hG3UjzvRADDHj+AtlEm" \ "aUVdQCJR+1k9jVj6v8X1ujD2y5tVbNeBO4AdNG/yZmC3a5lQpaSfn+gEexAiwk+7qdf+t8Yb+DtX58aophUPBPuD9tPFHsMCN" \ "VQTWhaRMvZ1864rYdcq7/IiAxmd0UgBxwIVAJdgUI8VIwvMspK5gqLrhAvwWBz1AoGBAPfhoIXWmz3ey7yrXDa4V7l5lK+7+jr" \ "qgvlXTAs9B4JnUVlXjrrUWU/mcQcQgYC0SRZxI+hMKBYTt88JMozIpuE8FnqLVHyNKOCjrh4rs6Z1kW6jfwv6ITVi8ftiegEkO" \ "8yk8b6oUZCJqIPf4VrlnwaSi2ZegHtVJWQBTDv+z0kqA4GFAAKBgQDRGYtLgWh7zyRtQainJfCpiaUbzjJuhMgo4fVWZIvXHaS" \ "HBU1t5w//S0lDK2hiqkj8KpMWGywVov9eZxZy37V26dEqr/c2m5qZ0E+ynSu7sqUD7kGx/zeIcGT0H+KAVgkGNQCo5Uc0koLRW" \ "YHNtYoIvt5R3X6YZylbPftF/8ayWTALBgcqhkjOOAQDBQADLwAwLAIUAKYCp0d6z4QQdyN74JDfQ2WCyi8CFDUM4CaNB+ceVXd" \ "KtOrNTQcc0e+t" _MD5_CLASSES = "vIDGGxIcIxeBP0GoG8yL8g==" _KEY = "/UIGKU1FVQa+ATM2A0za7G2KI9S/CwPYjgAbc67v7ep42eO/WeTLx1lb1cHwxpsEgF4+PmYpLd2YpGUdX/A2JQitsHzDwgcdBpUf7psX1BU=" _VERSION = "2.12.357" _OS_NAME = "Android" _OS_VERSION = "4.3" _DEVICE_NAME = "GalaxyS3" _AXOLOTL = True def getVersion(self): return self.__class__._VERSION def getOSName(self): return self.__class__._OS_NAME def getOSVersion(self): return self.__class__._OS_VERSION def getDeviceName(self): return self.__class__._DEVICE_NAME def isAxolotlEnabled(self): return self.__class__._AXOLOTL def getToken(self, phoneNumber): keyDecoded = bytearray(base64.b64decode(self.__class__._KEY)) sigDecoded = base64.b64decode(self.__class__._SIGNATURE) clsDecoded = base64.b64decode(self.__class__._MD5_CLASSES) data = sigDecoded + clsDecoded + phoneNumber.encode() opad = bytearray() ipad = bytearray() for i in range(0, 64): opad.append(0x5C ^ keyDecoded[i]) ipad.append(0x36 ^ keyDecoded[i]) hash = hashlib.sha1() subHash = hashlib.sha1() try: subHash.update(ipad + data) hash.update(opad + subHash.digest()) except TypeError: subHash.update(bytes(ipad + data)) hash.update(bytes(opad + subHash.digest())) result = base64.b64encode(hash.digest()) return result yowsup-2.4.48/yowsup/env/env_s40.py000066400000000000000000000020611263346463600171610ustar00rootroot00000000000000from .env import YowsupEnv import base64 import hashlib class S40YowsupEnv(YowsupEnv): _VERSION = "2.13.21" _OS_NAME= "S40" _OS_VERSION = "14.26" _DEVICE_NAME = "Nokia302" _TOKEN_STRING = "PdA2DJyKoUrwLw1Bg6EIhzh502dF9noR9uFCllGk1447796090073{phone}" _AXOLOTL = True def getVersion(self): return self.__class__._VERSION def getOSName(self): return self.__class__._OS_NAME def getOSVersion(self): return self.__class__._OS_VERSION def getDeviceName(self): return self.__class__._DEVICE_NAME def isAxolotlEnabled(self): return self.__class__._AXOLOTL def getToken(self, phoneNumber): return hashlib.md5(self.__class__._TOKEN_STRING.format(phone = phoneNumber).encode()).hexdigest() def getUserAgent(self): return self.__class__._USERAGENT_STRING.format( WHATSAPP_VERSION = self.getVersion(), OS_NAME = self.getOSName() + "Version", OS_VERSION = self.getOSVersion(), DEVICE_NAME = self.getDeviceName() ) yowsup-2.4.48/yowsup/env/test_env_s40.py000066400000000000000000000006001263346463600202150ustar00rootroot00000000000000import unittest from yowsup.env import S40YowsupEnv class S40YowsupEnvTest(unittest.TestCase): def test_tokengen(self): phone = "1234567" S40YowsupEnv._TOKEN_STRING = "PdA2DJyKoUrwLw1Bg6EIhzh502dF9noR9uFCllGk1425519315543{phone}" env = S40YowsupEnv() token = env.getToken(phone) self.assertEqual(token, 'e84e1f1477704159efd46f6f0781dbde') yowsup-2.4.48/yowsup/layers/000077500000000000000000000000001263346463600160415ustar00rootroot00000000000000yowsup-2.4.48/yowsup/layers/__init__.py000066400000000000000000000154421263346463600201600ustar00rootroot00000000000000import unittest try: import Queue except ImportError: import queue as Queue class YowLayerEvent: def __init__(self, name, **kwargs): self.name = name self.detached = False if "detached" in kwargs: del kwargs["detached"] self.detached = True self.args = kwargs def isDetached(self): return self.detached def getName(self): return self.name def getArg(self, name): return self.args[name] if name in self.args else None class YowLayer(object): __upper = None __lower = None _props = {} __detachedQueue = Queue.Queue() # def __init__(self, upperLayer, lowerLayer): # self.setLayers(upperLayer, lowerLayer) def __init__(self): self.setLayers(None, None) self.interface = None def getLayerInterface(self, YowLayerClass = None): return self.interface if YowLayerClass is None else self.__stack.getLayerInterface(YowLayerClass) def setStack(self, stack): self.__stack = stack def getStack(self): return self.__stack def setLayers(self, upper, lower): self.__upper = upper self.__lower = lower def send(self, data): self.toLower(data) def receive(self, data): self.toUpper(data) def toUpper(self, data): if self.__upper: self.__upper.receive(data) def toLower(self, data): if self.__lower: self.__lower.send(data) def emitEvent(self, yowLayerEvent): if self.__upper and not self.__upper.onEvent(yowLayerEvent): if yowLayerEvent.isDetached(): yowLayerEvent.detached = False self.getStack().execDetached(lambda : self.__upper.emitEvent(yowLayerEvent)) else: self.__upper.emitEvent(yowLayerEvent) def broadcastEvent(self, yowLayerEvent): if self.__lower and not self.__lower.onEvent(yowLayerEvent): if yowLayerEvent.isDetached(): yowLayerEvent.detached = False self.getStack().execDetached(lambda:self.__lower.broadcastEvent(yowLayerEvent)) else: self.__lower.broadcastEvent(yowLayerEvent) '''return true to stop propagating the event''' def onEvent(self, yowLayerEvent): return False def getProp(self, key, default = None): return self.getStack().getProp(key, default) def setProp(self, key, val): return self.getStack().setProp(key, val) class YowProtocolLayer(YowLayer): def __init__(self, handleMap = None): super(YowProtocolLayer, self).__init__() self.handleMap = handleMap or {} self.iqRegistry = {} def receive(self, node): if not self.processIqRegistry(node): if node.tag in self.handleMap: recv, _ = self.handleMap[node.tag] if recv: recv(node) def send(self, entity): if entity.getTag() in self.handleMap: _, send = self.handleMap[entity.getTag()] if send: send(entity) def entityToLower(self, entity): #super(YowProtocolLayer, self).toLower(entity.toProtocolTreeNode()) self.toLower(entity.toProtocolTreeNode()) def isGroupJid(self, jid): return "-" in jid def raiseErrorForNode(self, node): raise ValueError("Unimplemented notification type %s " % node) def _sendIq(self, iqEntity, onSuccess = None, onError = None): self.iqRegistry[iqEntity.getId()] = (iqEntity, onSuccess, onError) self.toLower(iqEntity.toProtocolTreeNode()) def processIqRegistry(self, protocolTreeNode): if protocolTreeNode.tag == "iq": iq_id = protocolTreeNode["id"] if iq_id in self.iqRegistry: originalIq, successClbk, errorClbk = self.iqRegistry[iq_id] del self.iqRegistry[iq_id] if protocolTreeNode["type"] == "result" and successClbk: successClbk(protocolTreeNode, originalIq) elif protocolTreeNode["type"] == "error" and errorClbk: errorClbk(protocolTreeNode, originalIq) return True return False class YowParallelLayer(YowLayer): def __init__(self, sublayers = None): super(YowParallelLayer, self).__init__() self.sublayers = sublayers or [] self.sublayers = tuple([sublayer() for sublayer in sublayers]) for s in self.sublayers: #s.setLayers(self, self) s.toLower = self.toLower s.toUpper = self.toUpper s.broadcastEvent = self.subBroadcastEvent s.emitEvent = self.subEmitEvent def getLayerInterface(self, YowLayerClass): for s in self.sublayers: if s.__class__ == YowLayerClass: return s.getLayerInterface() def setStack(self, stack): super(YowParallelLayer, self).setStack(stack) for s in self.sublayers: s.setStack(self.getStack()) def receive(self, data): for s in self.sublayers: s.receive(data) def send(self, data): for s in self.sublayers: s.send(data) def subBroadcastEvent(self, yowLayerEvent): self.onEvent(yowLayerEvent) self.broadcastEvent(yowLayerEvent) def subEmitEvent(self, yowLayerEvent): self.onEvent(yowLayerEvent) self.emitEvent(yowLayerEvent) def onEvent(self, yowLayerEvent): stopEvent = False for s in self.sublayers: stopEvent = stopEvent or s.onEvent(yowLayerEvent) return stopEvent def __str__(self): return " - ".join([l.__str__() for l in self.sublayers]) class YowLayerInterface(object): def __init__(self, layer): self._layer = layer class YowLayerTest(unittest.TestCase): def __init__(self, *args): super(YowLayerTest, self).__init__(*args) self.upperSink = [] self.lowerSink = [] self.toUpper = self.receiveOverrider self.toLower = self.sendOverrider def receiveOverrider(self, data): self.upperSink.append(data) def sendOverrider(self, data): self.lowerSink.append(data) class YowProtocolLayerTest(YowLayerTest): def assertSent(self, entity): self.send(entity) try: self.assertEqual(entity.toProtocolTreeNode(), self.lowerSink.pop()) except IndexError: raise AssertionError("Entity '%s' was not sent through this layer" % (entity.getTag())) def assertReceived(self, entity): node = entity.toProtocolTreeNode() self.receive(node) try: self.assertEqual(node, self.upperSink.pop().toProtocolTreeNode()) except IndexError: raise AssertionError("'%s' was not received through this layer" % (entity.getTag())) yowsup-2.4.48/yowsup/layers/auth/000077500000000000000000000000001263346463600170025ustar00rootroot00000000000000yowsup-2.4.48/yowsup/layers/auth/__init__.py000066400000000000000000000002421263346463600211110ustar00rootroot00000000000000from .layer_crypt import YowCryptLayer from .layer_authentication import YowAuthenticationProtocolLayer from .autherror import AuthError #import protocolentities yowsup-2.4.48/yowsup/layers/auth/autherror.py000066400000000000000000000000441263346463600213650ustar00rootroot00000000000000class AuthError(Exception): passyowsup-2.4.48/yowsup/layers/auth/keystream.py000066400000000000000000000075701263346463600213710ustar00rootroot00000000000000import hashlib, hmac, sys from struct import pack from operator import xor from itertools import starmap class RC4: def __init__(self, key, drop): self.s = [] self.i = 0; self.j = 0; self.s = [0] * 256 for i in range(0, len(self.s)): self.s[i] = i for i in range(0, len(self.s)): self.j = (self.j + self.s[i] + key[i % len(key)]) % 256 RC4.swap(self.s, i, self.j) self.j = 0; self.cipher(bytearray(drop), 0, drop) def cipher(self, data, offset, length): while True: num = length length = num - 1 if num == 0: break self.i = (self.i+1) % 256 self.j = (self.j + self.s[self.i]) % 256 RC4.swap(self.s, self.i, self.j) num2 = offset offset = num2 + 1 data[num2] = (data[num2] ^ self.s[(self.s[self.i] + self.s[self.j]) % 256]) @staticmethod def swap(arr, i, j): tmp = arr[i] arr[i] = arr[j] arr[j] = tmp class KeyStream: def __init__(self, key, macKey): self.key = key if sys.version_info < (3, 0) else bytes(key) self.rc4 = RC4(self.key, 0x300) self.macKey = str(macKey) if sys.version_info < (3, 0) else bytes(macKey) self.seq = 0 def computeMac(self, bytes_buffer, int_offset, int_length): mac = hmac.new(self.macKey, None, hashlib.sha1) updateData = bytes_buffer[int_offset:] + bytearray([self.seq >> 24, (self.seq >> 16) % 256, (self.seq >> 8) % 256, self.seq % 256]) try: mac.update(updateData) except TypeError: #python3 support mac.update(bytes(updateData)) self.seq += 1 return bytearray(mac.digest()) def decodeMessage(self, bufdata, macOffset, offset, length): buf = bufdata[:-4] hashed = bufdata[-4:] numArray = self.computeMac(buf, 0, len(buf)) num = 0 while num < 4: if numArray[macOffset + num] == hashed[num]: num += 1 else: raise Exception("INVALID MAC") self.rc4.cipher(buf, 0, len(buf)) return buf def encodeMessage(self, buf, macOffset, offset, length): self.rc4.cipher(buf, offset, length) mac = self.computeMac(buf, offset, length) output = buf[0:macOffset] + mac[0:4] + buf[macOffset+4:] return output @staticmethod def generateKeys(password, nonce): resultBytes = [] for i in range(1, 5): currNonce = nonce + bytearray([i]) resultBytes.append(KeyStream.pbkdf2(password, currNonce, 2, 20)) return resultBytes #@staticmethod ##use if drop python-2.6 support #def pbkdf2( password, salt, itercount, keylen): # return bytearray(hashlib.pbkdf2_hmac('sha1', password, salt, itercount, keylen)) @staticmethod def pbkdf2( password, salt, itercount, keylen, hashfn = hashlib.sha1 ): def pbkdf2_F( h, salt, itercount, blocknum ): def prf( h, data ): hm = h.copy() try: hm.update(bytearray(data)) except TypeError: #python 3 support hm.update(bytes(data)) d = hm.digest() return bytearray(d) U = prf( h, salt + pack('>i',blocknum ) ) T = U for i in range(2, itercount + 1): U = prf( h, U ) T = starmap(xor, zip(T, U)) return T digest_size = hashfn().digest_size l = int(keylen / digest_size) if keylen % digest_size != 0: l += 1 h = hmac.new(bytes(password), None, hashfn ) T = bytearray() for i in range(1, l+1): tmp = pbkdf2_F( h, salt, itercount, i ) T.extend(tmp) return T[0: keylen]yowsup-2.4.48/yowsup/layers/auth/layer_authentication.py000066400000000000000000000136521263346463600235760ustar00rootroot00000000000000from yowsup.layers import YowLayerEvent, YowProtocolLayer from .keystream import KeyStream from yowsup.common.tools import TimeTools from .layer_crypt import YowCryptLayer from yowsup.layers.network import YowNetworkLayer from .autherror import AuthError from .protocolentities import * from yowsup.common.tools import StorageTools from .layer_interface_authentication import YowAuthenticationProtocolLayerInterface import base64 class YowAuthenticationProtocolLayer(YowProtocolLayer): EVENT_LOGIN = "org.openwhatsapp.yowsup.event.auth.login" EVENT_AUTHED = "org.openwhatsapp.yowsup.event.auth.authed" PROP_CREDENTIALS = "org.openwhatsapp.yowsup.prop.auth.credentials" PROP_PASSIVE = "org.openwhatsapp.yowsup.prop.auth.passive" def __init__(self): handleMap = { "stream:features": (self.handleStreamFeatures, None), "failure": (self.handleFailure, None), "success": (self.handleSuccess, None), "challenge": (self.handleChallenge, None), "stream:error": (self.handleStreamError, None), } super(YowAuthenticationProtocolLayer, self).__init__(handleMap) self.interface = YowAuthenticationProtocolLayerInterface(self) self.credentials = None #left for backwards-compat self._credentials = None #new style set def __str__(self): return "Authentication Layer" def __getCredentials(self, credentials = None): u, pb64 = credentials or self.getProp(YowAuthenticationProtocolLayer.PROP_CREDENTIALS) if type(pb64) is str: pb64 = pb64.encode() password = base64.b64decode(pb64) return (u, bytearray(password)) def setCredentials(self, credentials): self.setProp(YowAuthenticationProtocolLayer.PROP_CREDENTIALS, credentials) #keep for now self._credentials = self.__getCredentials(credentials) def getUsername(self, full = False): if self._credentials: return self._credentials[0] if not full else ("%s@s.whatsapp.net" % self._credentials[0]) else: prop = self.getProp(YowAuthenticationProtocolLayer.PROP_CREDENTIALS) return prop[0] if prop else None def onEvent(self, event): if event.getName() == YowNetworkLayer.EVENT_STATE_CONNECTED: self.login() ## general methods def login(self): self.credentials = self._credentials or self.__getCredentials() self._sendFeatures() self._sendAuth() ###recieved node handlers handlers def handleStreamFeatures(self, node): nodeEntity = StreamFeaturesProtocolEntity.fromProtocolTreeNode(node) self.toUpper(nodeEntity) def handleSuccess(self, node): if(node.data != None): StorageTools.writeNonce(self.credentials[0],node.data) successEvent = YowLayerEvent(self.__class__.EVENT_AUTHED, passive = self.getProp(self.__class__.PROP_PASSIVE)) self.broadcastEvent(successEvent) nodeEntity = SuccessProtocolEntity.fromProtocolTreeNode(node) self.toUpper(nodeEntity) def handleFailure(self, node): nodeEntity = FailureProtocolEntity.fromProtocolTreeNode(node) self.toUpper(nodeEntity) self.broadcastEvent(YowLayerEvent(YowNetworkLayer.EVENT_STATE_DISCONNECT, reason = "Authentication Failure")) raise AuthError(nodeEntity.getReason()) def handleChallenge(self, node): nodeEntity = ChallengeProtocolEntity.fromProtocolTreeNode(node) self._sendResponse(nodeEntity.getNonce()) def handleStreamError(self, node): if node.getChild("text"): nodeEntity = StreamErrorConflictProtocolEntity.fromProtocolTreeNode(node) elif node.getChild("ack"): nodeEntity = StreamErrorAckProtocolEntity.fromProtocolTreeNode(node) else: raise AuthError("Unhandled stream:error node:\n%s" % node) self.toUpper(nodeEntity) ##senders def _sendFeatures(self): self.entityToLower(StreamFeaturesProtocolEntity(["readreceipts", "groups_v2", "privacy", "presence"])) def _sendAuth(self): passive = self.getProp(self.__class__.PROP_PASSIVE, False) nonce = StorageTools.getNonce(self.credentials[0]) if nonce == None: self.entityToLower(AuthProtocolEntity(self.credentials[0], passive=passive)) else: inputKey, outputKey, authBlob = self.generateAuthBlob(nonce) #to prevent enr whole response self.broadcastEvent(YowLayerEvent(YowCryptLayer.EVENT_KEYS_READY, keys = (inputKey, None))) self.entityToLower(AuthProtocolEntity(self.credentials[0], passive=passive, nonce=authBlob)) self.broadcastEvent(YowLayerEvent(YowCryptLayer.EVENT_KEYS_READY, keys = (inputKey, outputKey))) def _sendResponse(self,nonce): inputKey, outputKey, authBlob = self.generateAuthBlob(nonce) responseEntity = ResponseProtocolEntity(authBlob) #to prevent enr whole response self.broadcastEvent(YowLayerEvent(YowCryptLayer.EVENT_KEYS_READY, keys = (inputKey, None))) self.entityToLower(responseEntity) self.broadcastEvent(YowLayerEvent(YowCryptLayer.EVENT_KEYS_READY, keys = (inputKey, outputKey))) #YowCryptLayer.setProp("outputKey", outputKey) def generateAuthBlob(self, nonce): keys = KeyStream.generateKeys(self.credentials[1], nonce) inputKey = KeyStream(keys[2], keys[3]) outputKey = KeyStream(keys[0], keys[1]) #YowCryptLayer.setProp("inputKey", inputKey) nums = bytearray(4) #nums = [0] * 4 username_bytes = list(map(ord, self.credentials[0])) nums.extend(username_bytes) nums.extend(nonce) utcNow = str(int(TimeTools.utcTimestamp())) time_bytes = list(map(ord, utcNow)) nums.extend(time_bytes) encoded = outputKey.encodeMessage(nums, 0, 4, len(nums) - 4) authBlob = "".join(map(chr, encoded)) return (inputKey, outputKey, authBlob) yowsup-2.4.48/yowsup/layers/auth/layer_crypt.py000066400000000000000000000040731263346463600217150ustar00rootroot00000000000000from yowsup.layers import YowLayer from yowsup.layers.network import YowNetworkLayer class YowCryptLayer(YowLayer): ''' send: bytearray -> bytearray receive: bytearray -> bytearray ''' EVENT_KEYS_READY = "org.openwhatsapp.yowsup.crypt.keys" def __init__(self): super(YowCryptLayer, self).__init__() self.keys = (None,None) def onEvent(self, yowLayerEvent): if yowLayerEvent.getName() == YowNetworkLayer.EVENT_STATE_CONNECTED: self.keys = (None,None) elif yowLayerEvent.getName() == YowCryptLayer.EVENT_KEYS_READY: self.keys = yowLayerEvent.getArg("keys") return True def send(self, data): outputKey = self.keys[1] length1 = len(data) if length1 > 1: if outputKey: length1 += 4 buf = outputKey.encodeMessage(data, len(data), 0, len(data)) res = [0,0,0] res.extend(buf) res[0] = ((8 << 4) | (length1 & 16711680) >> 16) % 256 res[1] = ((length1 & 65280) >> 8) % 256 res[2] = (length1 & 255) % 256 data = res else: prep = [0,0,0] prep.extend(data) prep[0] = ((0 << 4) | (length1 & 16711680) >> 16) % 256 prep[1] = ((length1 & 65280) >> 8) % 256 prep[2] = (length1 & 255) % 256 data = prep self.toLower(bytearray(data)) def receive(self, data): inputKey = self.keys[0] metaData = data[:3] payload = bytearray(data[3:]) firstByte = metaData[0] stanzaFlag = (firstByte & 0xF0) >> 4 stanzaSize = ((metaData[1] << 8) + metaData[2]) | ((firstByte & 0x0F) << 16) isEncrypted = ((stanzaFlag & 8) != 0) if inputKey and isEncrypted: toDecode = data[3:] payload = inputKey.decodeMessage(payload, 0, 4, len(payload) - 4) self.toUpper(payload) def __str__(self): return "Crypt Layer"yowsup-2.4.48/yowsup/layers/auth/layer_interface_authentication.py000066400000000000000000000004531263346463600256110ustar00rootroot00000000000000from yowsup.layers import YowLayerInterface class YowAuthenticationProtocolLayerInterface(YowLayerInterface): def setCredentials(self, phone, password): self._layer.setCredentials((phone, password)) def getUsername(self, full = False): return self._layer.getUsername(full) yowsup-2.4.48/yowsup/layers/auth/protocolentities/000077500000000000000000000000001263346463600224105ustar00rootroot00000000000000yowsup-2.4.48/yowsup/layers/auth/protocolentities/__init__.py000066400000000000000000000006211263346463600245200ustar00rootroot00000000000000from .auth import AuthProtocolEntity from .challenge import ChallengeProtocolEntity from .response import ResponseProtocolEntity from .stream_features import StreamFeaturesProtocolEntity from .success import SuccessProtocolEntity from .failure import FailureProtocolEntity from .stream_error_conflict import StreamErrorConflictProtocolEntity from .stream_error_ack import StreamErrorAckProtocolEntity yowsup-2.4.48/yowsup/layers/auth/protocolentities/auth.py000066400000000000000000000016741263346463600237330ustar00rootroot00000000000000from yowsup.structs import ProtocolEntity, ProtocolTreeNode class AuthProtocolEntity(ProtocolEntity): def __init__(self, user, mechanism = "WAUTH-2", passive = False, nonce = None): super(AuthProtocolEntity, self).__init__("auth") self.user = user self.mechanism = mechanism self.passive = passive self.nonce = nonce def toProtocolTreeNode(self): attributes = { "user" : self.user, "mechanism" : self.mechanism, "passive" : "true" if self.passive else "false" } return self._createProtocolTreeNode(attributes, children = None, data = self.nonce) @staticmethod def fromProtocolTreeNode(node): return AuthProtocolEntity( node.getAttributeValue("user"), node.getAttributeValue("mechanism"), node.getAttributeValue("passive") != "false", node.getData() )yowsup-2.4.48/yowsup/layers/auth/protocolentities/challenge.py000066400000000000000000000014431263346463600247060ustar00rootroot00000000000000from yowsup.structs import ProtocolEntity, ProtocolTreeNode class ChallengeProtocolEntity(ProtocolEntity): def __init__(self, nonce): super(ChallengeProtocolEntity, self).__init__("challenge") self.nonce = nonce def getNonce(self): return self.nonce def toProtocolTreeNode(self): #return self._createProtocolTreeNode({}, children = None, data = self.nonce) return self._createProtocolTreeNode({}, children = [], data = "".join(map(chr, self.nonce))) def __str__(self): out = "Challenge\n" out += "Nonce: %s\n" % self.nonce return out @staticmethod def fromProtocolTreeNode(node): nonce = list(map(ord,node.getData())) entity = ChallengeProtocolEntity(bytearray(nonce)) return entity yowsup-2.4.48/yowsup/layers/auth/protocolentities/failure.py000066400000000000000000000012541263346463600244130ustar00rootroot00000000000000from yowsup.structs import ProtocolEntity, ProtocolTreeNode class FailureProtocolEntity(ProtocolEntity): def __init__(self, reason): super(FailureProtocolEntity, self).__init__("failure") self.reason = reason def __str__(self): out = "Failure:\n" out += "Reason: %s\n" % self.reason return out def getReason(self): return self.reason def toProtocolTreeNode(self): reasonNode = ProtocolTreeNode(self.reason, {}) return self._createProtocolTreeNode({}, children = [reasonNode]) @staticmethod def fromProtocolTreeNode(node): return FailureProtocolEntity( node.getAllChildren()[0].tag )yowsup-2.4.48/yowsup/layers/auth/protocolentities/response.py000066400000000000000000000011031263346463600246130ustar00rootroot00000000000000from yowsup.structs import ProtocolEntity, ProtocolTreeNode class ResponseProtocolEntity(ProtocolEntity): def __init__(self, data, xmlns = "urn:ietf:params:xml:ns:xmpp-sasl"): super(ResponseProtocolEntity, self).__init__("response") self.xmlns = xmlns self.data = data def toProtocolTreeNode(self): return self._createProtocolTreeNode({"xmlns": self.xmlns}, children = None, data = self.data) @staticmethod def fromProtocolTreeNode(node): return ResponseProtocolEntity(node.getData(), node.getAttributeValue("xmlns"))yowsup-2.4.48/yowsup/layers/auth/protocolentities/stream_error_ack.py000066400000000000000000000012071263346463600263040ustar00rootroot00000000000000from yowsup.structs import ProtocolEntity, ProtocolTreeNode class StreamErrorAckProtocolEntity(ProtocolEntity): ''' ''' def __init__(self): super(StreamErrorAckProtocolEntity, self).__init__("stream:error") def toProtocolTreeNode(self): node = super(StreamErrorAckProtocolEntity, self).toProtocolTreeNode() node.addChild(ProtocolTreeNode("ack")) return node def __str__(self): out = "Ack Stream Error\n" return out @staticmethod def fromProtocolTreeNode(node): return StreamErrorAckProtocolEntity() yowsup-2.4.48/yowsup/layers/auth/protocolentities/stream_error_conflict.py000066400000000000000000000020461263346463600273510ustar00rootroot00000000000000from yowsup.structs import ProtocolEntity, ProtocolTreeNode class StreamErrorConflictProtocolEntity(ProtocolEntity): ''' Replaced by new connection ''' def __init__(self, text = None): super(StreamErrorConflictProtocolEntity, self).__init__("stream:error") self.setText(text) def setText(self, text = None): self.text = text or '' def getText(self): return self.text def __str__(self): out = "Conflict Stream Error\n" if self.text: out += "Text: %s\n" % self.getText() return out def toProtocolTreeNode(self): node = super(StreamErrorConflictProtocolEntity, self).toProtocolTreeNode() node.addChild(ProtocolTreeNode("conflict")) node.addChild(ProtocolTreeNode("text", data=self.text)) return node @staticmethod def fromProtocolTreeNode(node): return StreamErrorConflictProtocolEntity(node.getChild("text").getData()) yowsup-2.4.48/yowsup/layers/auth/protocolentities/stream_features.py000066400000000000000000000012731263346463600261560ustar00rootroot00000000000000from yowsup.structs import ProtocolEntity, ProtocolTreeNode class StreamFeaturesProtocolEntity(ProtocolEntity): def __init__(self, features = None): super(StreamFeaturesProtocolEntity, self).__init__("stream:features") self.setFeatures(features) def setFeatures(self, features = None): self.features = features or [] def toProtocolTreeNode(self): featureNodes = [ProtocolTreeNode(feature) for feature in self.features] return self._createProtocolTreeNode({}, children = featureNodes, data = None) @staticmethod def fromProtocolTreeNode(node): return StreamFeaturesProtocolEntity([fnode.tag for fnode in node.getAllChildren()])yowsup-2.4.48/yowsup/layers/auth/protocolentities/success.py000066400000000000000000000031731263346463600244360ustar00rootroot00000000000000from yowsup.structs import ProtocolEntity, ProtocolTreeNode class SuccessProtocolEntity(ProtocolEntity): def __init__(self, status, kind, creation, expiration, props, t, nonce = None): super(SuccessProtocolEntity, self).__init__("success") self.status = status self.kind = kind self.creation = int(creation) self.expiration = int(expiration) self.props = props self.nonce = nonce self.t = int(t) ##whatever that is ! def __str__(self): out = "Account:\n" out += "Status: %s\n" % self.status out += "Kind: %s\n" % self.kind out += "Creation: %s\n" % self.creation out += "Expiration: %s\n" % self.expiration out += "Props: %s\n" % self.props out += "t: %s\n" % self.t return out def toProtocolTreeNode(self): attributes = { "status" : self.status, "kind" : self.kind, "creation" : str(self.creation), "expiration" : str(self.expiration), "props" : self.props, "t" : str(self.t) } return self._createProtocolTreeNode(attributes, children = None, data = self.nonce) @staticmethod def fromProtocolTreeNode(node): return SuccessProtocolEntity( node.getAttributeValue("status"), node.getAttributeValue("kind"), node.getAttributeValue("creation"), node.getAttributeValue("expiration"), node.getAttributeValue("props"), node.getAttributeValue("t"), node.getData() )yowsup-2.4.48/yowsup/layers/auth/protocolentities/test_auth.py000066400000000000000000000006671263346463600247730ustar00rootroot00000000000000from yowsup.layers.auth.protocolentities import AuthProtocolEntity from yowsup.structs import ProtocolTreeNode from yowsup.structs.protocolentity import ProtocolEntityTest import unittest class AuthProtocolEntityTest(ProtocolEntityTest, unittest.TestCase): def setUp(self): self.ProtocolEntity = AuthProtocolEntity self.node = ProtocolTreeNode("auth", {"user": "testuser", "mechanism": "WAUTH-2", "passive": "false"})yowsup-2.4.48/yowsup/layers/auth/protocolentities/test_challenge.py000066400000000000000000000010211263346463600257350ustar00rootroot00000000000000from yowsup.layers.auth.protocolentities.challenge import ChallengeProtocolEntity from yowsup.structs import ProtocolTreeNode from yowsup.structs.protocolentity import ProtocolEntityTest import unittest class ChallengeProtocolEntityTest(ProtocolEntityTest, unittest.TestCase): def setUp(self): self.ProtocolEntity = ChallengeProtocolEntity attribs = {} childNodes = [] data = "dummydata" self.node = ProtocolTreeNode("challenge", attribs, [], data)yowsup-2.4.48/yowsup/layers/auth/protocolentities/test_failure.py000066400000000000000000000006661263346463600254600ustar00rootroot00000000000000from yowsup.layers.auth.protocolentities.failure import FailureProtocolEntity from yowsup.structs import ProtocolTreeNode from yowsup.structs.protocolentity import ProtocolEntityTest import unittest class FailureProtocolEntityTest(ProtocolEntityTest, unittest.TestCase): def setUp(self): self.ProtocolEntity = FailureProtocolEntity self.node = ProtocolTreeNode("failure", {}, [ProtocolTreeNode("not-authorized", {})])yowsup-2.4.48/yowsup/layers/auth/protocolentities/test_response.py000066400000000000000000000007771263346463600256720ustar00rootroot00000000000000from yowsup.layers.auth.protocolentities.response import ResponseProtocolEntity from yowsup.structs import ProtocolTreeNode from yowsup.structs.protocolentity import ProtocolEntityTest import unittest class ResponseProtocolEntityTest(ProtocolEntityTest, unittest.TestCase): def setUp(self): self.ProtocolEntity = ResponseProtocolEntity attribs = { "xmlns": "urn:ietf:params:xml:ns:xmpp-sasl" } self.node = ProtocolTreeNode("response", attribs, None, "dummydata")yowsup-2.4.48/yowsup/layers/auth/protocolentities/test_stream_features.py000066400000000000000000000010461263346463600272130ustar00rootroot00000000000000from yowsup.layers.auth.protocolentities.stream_features import StreamFeaturesProtocolEntity from yowsup.structs import ProtocolTreeNode from yowsup.structs.protocolentity import ProtocolEntityTest import unittest class StreamFeaturesProtocolEntityTest(ProtocolEntityTest, unittest.TestCase): def setUp(self): self.ProtocolEntity = StreamFeaturesProtocolEntity attribs = { } childNode = ProtocolTreeNode("receipt_acks", {}, None, None) self.node = ProtocolTreeNode("stream:features", attribs, [childNode])yowsup-2.4.48/yowsup/layers/auth/protocolentities/test_success.py000066400000000000000000000011761263346463600254760ustar00rootroot00000000000000from yowsup.layers.auth.protocolentities.success import SuccessProtocolEntity from yowsup.structs import ProtocolTreeNode from yowsup.structs.protocolentity import ProtocolEntityTest import unittest class SuccessProtocolEntityTest(ProtocolEntityTest, unittest.TestCase): def setUp(self): self.ProtocolEntity = SuccessProtocolEntity attribs = { "status": "active", "kind": "free", "creation": "1234", "expiration": "1446578937", "props": "2", "t": "1415470561" } self.node = ProtocolTreeNode("success", attribs, None, "dummydata")yowsup-2.4.48/yowsup/layers/auth/test_authenticator.py000066400000000000000000000027371263346463600232760ustar00rootroot00000000000000from yowsup.layers.auth import YowAuthenticationProtocolLayer from yowsup.layers import YowLayerEvent, YowLayerTest from yowsup.layers.auth.protocolentities import StreamFeaturesProtocolEntity,AuthProtocolEntity, ChallengeProtocolEntity from yowsup.structs import ProtocolTreeNode from yowsup.stacks import YowStack import base64 # from unittest.mock import MagicMock class AuthenticationProtocolLayerTest(YowLayerTest, YowAuthenticationProtocolLayer): def setUp(self): #YowAuthenticatorLayer.__init__(self) super(YowAuthenticationProtocolLayer, self).__init__() dummyStack = YowStack() self.setStack(dummyStack) self.credentials = ("dummyusername", bytearray("password", "latin-1")) dummyStack.setProp(YowAuthenticationProtocolLayer.PROP_CREDENTIALS, self.credentials) #ticatorLayer.setProp("credentials", self.credentials) def test_streamfeatures(self): self._sendFeatures() self.assertEqual(self.lowerSink.pop(), StreamFeaturesProtocolEntity(["readreceipts","groups_v2","privacy","presence"]).toProtocolTreeNode()) def test_auth(self): self._sendAuth() self.assertEqual(self.lowerSink.pop(), AuthProtocolEntity(self.credentials[0]).toProtocolTreeNode()) def test_handle_challenge(self): node = ProtocolTreeNode("challenge", {}, None, "salt") self.handleChallenge(node) def test_login_onconnected(self): self.onEvent(YowLayerEvent("network.state.connected")) yowsup-2.4.48/yowsup/layers/auth/test_crypt.py000066400000000000000000000025131263346463600215550ustar00rootroot00000000000000from yowsup.layers import YowLayerEvent, YowLayerTest from yowsup.structs import ProtocolTreeNode from yowsup.layers.auth import YowCryptLayer from yowsup.layers.auth.keystream import KeyStream class CryptLayerTest(YowLayerTest, YowCryptLayer): def setUp(self): YowCryptLayer.__init__(self) self.password = bytearray(list(map(ord,"password"))) self.salt = bytearray(list(map(ord,"salt"))) self.username = "username" self.inputMessage = bytearray([0,0,0,0, ord('t'), ord('a'), ord('r'), ord('e'), ord('k')]) self.inputMessageCrypted = bytearray(b'\x80\x00\r)\x99\xbe_\xee\x98\xecV<\x9d\x0c\xb7r') keys = [ bytearray(b'>\xd5\x8a\xecB\xdb\xc8\xd4}\x98\x9aBa\x89\x9fC\x08\xdcp\x8d'), bytearray(b'\xd3;\xda:\x8f\x94CX\xe4;\xbb\xcc"W\x83\xe0m\xba\xe0\xd1'), bytearray(b'\x92w{\xc2\x04~\x08;\x81w\xb7h3\xb8\xc4t\xbd\xed\xf7q'), bytearray(b'.\xc7\xe4\x15\x1a\xa0\xfd\x98\xc0\xea\xefs{\r7E\xa6\xec\xd5\xfb') ] inputKey = KeyStream(keys[2], keys[3]) outputKey = KeyStream(keys[0], keys[1]) self.onEvent(YowLayerEvent(YowCryptLayer.EVENT_KEYS_READY, keys = (inputKey, outputKey))) def test_00send(self): self.send(self.inputMessage) self.assertEqual(self.lowerSink.pop(), self.inputMessageCrypted) yowsup-2.4.48/yowsup/layers/auth/test_keystream.py000066400000000000000000000044051263346463600224220ustar00rootroot00000000000000import unittest from yowsup.layers.auth.keystream import KeyStream class KeyStreamTest(unittest.TestCase): def setUp(self): self.password = bytearray(list(map(ord,"password"))) self.salt = bytearray(list(map(ord,"salt"))) self.keysTarget = [ bytearray(b'>\xd5\x8a\xecB\xdb\xc8\xd4}\x98\x9aBa\x89\x9fC\x08\xdcp\x8d'), bytearray(b'\xd3;\xda:\x8f\x94CX\xe4;\xbb\xcc"W\x83\xe0m\xba\xe0\xd1'), bytearray(b'\x92w{\xc2\x04~\x08;\x81w\xb7h3\xb8\xc4t\xbd\xed\xf7q'), bytearray(b'.\xc7\xe4\x15\x1a\xa0\xfd\x98\xc0\xea\xefs{\r7E\xa6\xec\xd5\xfb') ] self.pbkdbf2_res = bytearray(b'\xeal\x01M\xc7-o\x8c\xcd\x1e\xd9*\xce\x1dA\xf0\xd8\xde\x89W') self.inputMessage = bytearray([0,0,0,0, ord('t'), ord('a'), ord('r'), ord('e'), ord('k')]) self.inputMessageComputedMac = bytearray(b'\xec\x82q\xab\x9f\x8d;\xac\x83\xc5X\xbb\xb6u\x1c\xb0\xd2\x82=`') self.inputMessageRC4Ciphered = bytearray(b'\x00\x00\x00\x00\xf4&-\x0c\xbc') def test_generateKeys(self): keys = KeyStream.generateKeys(self.password, self.salt) self.assertEqual(keys, self.keysTarget) def test_pbkdf2(self): result = KeyStream.pbkdf2(self.password, self.salt, 2, 20) result = bytearray(result) self.assertEqual(result, self.pbkdbf2_res) def test_computemac(self): keys = self.keysTarget kstream = KeyStream(keys[2], keys[3]) res = kstream.computeMac(self.inputMessage, 4, len(self.inputMessage) - 4) self.assertEqual(res, self.inputMessageComputedMac) def test_rc4(self): keys = self.keysTarget kstream = KeyStream(keys[2], keys[3]) kstream.rc4.cipher(self.inputMessage, 4, len(self.inputMessage) - 4) self.assertEqual(self.inputMessage, self.inputMessageRC4Ciphered) def test_encodeMessage(self): keys = self.keysTarget kstream = KeyStream(keys[2], keys[3]) encoded = kstream.encodeMessage(self.inputMessage, 0, 4, len(self.inputMessage) - 4) def test_manyEncode(self): keys = self.keysTarget kstream = KeyStream(keys[2], keys[3]) for i in range(0, 300): encoded = kstream.encodeMessage(self.inputMessage, 0, 4, len(self.inputMessage) - 4)yowsup-2.4.48/yowsup/layers/axolotl/000077500000000000000000000000001263346463600175235ustar00rootroot00000000000000yowsup-2.4.48/yowsup/layers/axolotl/__init__.py000066400000000000000000000000421263346463600216300ustar00rootroot00000000000000from .layer import YowAxolotlLayeryowsup-2.4.48/yowsup/layers/axolotl/layer.py000066400000000000000000000400311263346463600212070ustar00rootroot00000000000000from yowsup.layers import YowProtocolLayer, YowLayerEvent from .protocolentities import SetKeysIqProtocolEntity from axolotl.util.keyhelper import KeyHelper from .store.sqlite.liteaxolotlstore import LiteAxolotlStore from axolotl.sessionbuilder import SessionBuilder from yowsup.layers.protocol_messages.protocolentities.message import MessageProtocolEntity from yowsup.layers.protocol_receipts.protocolentities import OutgoingReceiptProtocolEntity from yowsup.layers.network.layer import YowNetworkLayer from yowsup.layers.auth.layer_authentication import YowAuthenticationProtocolLayer from axolotl.ecc.curve import Curve from yowsup.common.tools import StorageTools from axolotl.protocol.prekeywhispermessage import PreKeyWhisperMessage from axolotl.protocol.whispermessage import WhisperMessage from .protocolentities import EncryptedMessageProtocolEntity from axolotl.sessioncipher import SessionCipher from yowsup.structs import ProtocolTreeNode from .protocolentities import GetKeysIqProtocolEntity, ResultGetKeysIqProtocolEntity from axolotl.util.hexutil import HexUtil from axolotl.invalidmessageexception import InvalidMessageException from axolotl.duplicatemessagexception import DuplicateMessageException from .protocolentities import EncryptNotification from yowsup.layers.protocol_acks.protocolentities import OutgoingAckProtocolEntity from axolotl.invalidkeyidexception import InvalidKeyIdException from axolotl.nosessionexception import NoSessionException from axolotl.untrustedidentityexception import UntrustedIdentityException from .protocolentities.receipt_outgoing_retry import RetryOutgoingReceiptProtocolEntity import binascii import sys import logging logger = logging.getLogger(__name__) class YowAxolotlLayer(YowProtocolLayer): EVENT_PREKEYS_SET = "org.openwhatsapp.yowsup.events.axololt.setkeys" _STATE_INIT = 0 _STATE_GENKEYS = 1 _STATE_HASKEYS = 2 _COUNT_PREKEYS = 200 _DB = "axolotl.db" def __init__(self): super(YowAxolotlLayer, self).__init__() self.store = None self.state = self.__class__._STATE_INIT self.sessionCiphers = {} self.pendingMessages = {} self.pendingIncomingMessages = {} self.skipEncJids = [] self.v2Jids = [] #people we're going to send v2 enc messages @property def store(self): if self._store is None: self.store = LiteAxolotlStore( StorageTools.constructPath( self.getProp( YowAuthenticationProtocolLayer.PROP_CREDENTIALS)[0], self.__class__._DB ) ) self.state = self.__class__._STATE_HASKEYS if self.store.getLocalRegistrationId() is not None \ else self.__class__._STATE_INIT return self._store @store.setter def store(self, store): self._store = store def __str__(self): return "Axolotl Layer" ### store and state def isInitState(self): return self.store == None or self.state == self.__class__._STATE_INIT def isGenKeysState(self): return self.state == self.__class__._STATE_GENKEYS ######## ### standard layer methods ### def onEvent(self, yowLayerEvent): if yowLayerEvent.getName() == self.__class__.EVENT_PREKEYS_SET: self.sendKeys(fresh=False) elif yowLayerEvent.getName() == YowNetworkLayer.EVENT_STATE_CONNECTED: if self.isInitState(): self.setProp(YowAuthenticationProtocolLayer.PROP_PASSIVE, True) elif yowLayerEvent.getName() == YowAuthenticationProtocolLayer.EVENT_AUTHED: if yowLayerEvent.getArg("passive") and self.isInitState(): logger.info("Axolotl layer is generating keys") self.sendKeys() elif yowLayerEvent.getName() == YowNetworkLayer.EVENT_STATE_DISCONNECTED: if self.isGenKeysState(): #we requested this disconnect in this layer to switch off passive #no need to traverse it to upper layers? self.setProp(YowAuthenticationProtocolLayer.PROP_PASSIVE, False) self.state = self.__class__._STATE_HASKEYS self.getLayerInterface(YowNetworkLayer).connect() else: self.store = None def send(self, node): if node.tag == "message" and node["type"] == "text" and node["to"] not in self.skipEncJids: self.handlePlaintextNode(node) return self.toLower(node) def receive(self, protocolTreeNode): """ :type protocolTreeNode: ProtocolTreeNode """ if not self.processIqRegistry(protocolTreeNode): if protocolTreeNode.tag == "message": self.onMessage(protocolTreeNode) return elif protocolTreeNode.tag == "notification" and protocolTreeNode["type"] == "encrypt": self.onEncryptNotification(protocolTreeNode) return elif protocolTreeNode.tag == "receipt" and protocolTreeNode["type"] == "retry": # should bring up that message, resend it, but in upper layer? # as it might have to be fetched from a persistent storage pass self.toUpper(protocolTreeNode) ###### ##### handling received data ##### def onEncryptNotification(self, protocolTreeNode): entity = EncryptNotification.fromProtocolTreeNode(protocolTreeNode) ack = OutgoingAckProtocolEntity(protocolTreeNode["id"], "notification", protocolTreeNode["type"], protocolTreeNode["from"]) self.toLower(ack.toProtocolTreeNode()) self.sendKeys(fresh=False, countPreKeys = self.__class__._COUNT_PREKEYS - entity.getCount()) def onMessage(self, protocolTreeNode): encNode = protocolTreeNode.getChild("enc") if encNode: self.handleEncMessage(protocolTreeNode) else: self.toUpper(protocolTreeNode) #### def processPendingMessages(self, jid): if jid in self.pendingMessages: for messageNode in self.pendingMessages[jid]: if jid in self.skipEncJids: self.toLower(messageNode) else: self.handlePlaintextNode(messageNode) del self.pendingMessages[jid] def processPendingIncomingMessages(self, jid): if jid in self.pendingIncomingMessages: for messageNode in self.pendingIncomingMessages[jid]: self.onMessage(messageNode) del self.pendingIncomingMessages[jid] #### handling message types def handlePlaintextNode(self, node): plaintext = node.getChild("body").getData() entity = MessageProtocolEntity.fromProtocolTreeNode(node) recipient_id = entity.getTo(False) if not self.store.containsSession(recipient_id, 1): entity = GetKeysIqProtocolEntity([node["to"]]) if node["to"] not in self.pendingMessages: self.pendingMessages[node["to"]] = [] self.pendingMessages[node["to"]].append(node) self._sendIq(entity, lambda a, b: self.onGetKeysResult(a, b, self.processPendingMessages), self.onGetKeysError) else: sessionCipher = self.getSessionCipher(recipient_id) if node["to"] in self.v2Jids: version = 2 padded = bytearray() padded.append(ord("\n")) padded.extend(self.encodeInt7bit(len(plaintext))) padded.extend(plaintext) padded.append(ord("\x01")) plaintext = padded else: version = 1 ciphertext = sessionCipher.encrypt(plaintext) encEntity = EncryptedMessageProtocolEntity( EncryptedMessageProtocolEntity.TYPE_MSG if ciphertext.__class__ == WhisperMessage else EncryptedMessageProtocolEntity.TYPE_PKMSG , version, ciphertext.serialize(), MessageProtocolEntity.MESSAGE_TYPE_TEXT, _id= node["id"], to = node["to"], notify = node["notify"], timestamp= node["timestamp"], participant=node["participant"], offline=node["offline"], retry=node["retry"] ) self.toLower(encEntity.toProtocolTreeNode()) def encodeInt7bit(self, value): v = value out = bytearray() while v >= 0x80: out.append((v | 0x80) % 256) v >>= 7 out.append(v % 256) return out def handleEncMessage(self, node): try: if node.getChild("enc")["v"] == "2" and node["from"] not in self.v2Jids: self.v2Jids.append(node["from"]) if node.getChild("enc")["type"] == "pkmsg": self.handlePreKeyWhisperMessage(node) else: self.handleWhisperMessage(node) except InvalidMessageException as e: # logger.error("Invalid message from %s!! Your axololtl database data might be inconsistent with WhatsApp, or with what that contact has" % node["from"]) # sys.exit(1) logger.error(e) retry = RetryOutgoingReceiptProtocolEntity.fromMesageNode(node) retry.setRegData(self.store.getLocalRegistrationId()) self.toLower(retry.toProtocolTreeNode()) except InvalidKeyIdException as e: logger.error(e) retry = RetryOutgoingReceiptProtocolEntity.fromMesageNode(node) retry.setRegData(self.store.getLocalRegistrationId()) self.toLower(retry.toProtocolTreeNode()) except NoSessionException as e: logger.error(e) entity = GetKeysIqProtocolEntity([node["from"]]) if node["from"] not in self.pendingIncomingMessages: self.pendingIncomingMessages[node["from"]] = [] self.pendingIncomingMessages[node["from"]].append(node) self._sendIq(entity, lambda a, b: self.onGetKeysResult(a, b, self.processPendingIncomingMessages), self.onGetKeysError) except DuplicateMessageException as e: logger.error(e) logger.warning("Going to send the delivery receipt myself !") self.toLower(OutgoingReceiptProtocolEntity(node["id"], node["from"]).toProtocolTreeNode()) except UntrustedIdentityException as e: logger.error(e) logger.warning("Ignoring message with untrusted identity") def handlePreKeyWhisperMessage(self, node): pkMessageProtocolEntity = EncryptedMessageProtocolEntity.fromProtocolTreeNode(node) preKeyWhisperMessage = PreKeyWhisperMessage(serialized=pkMessageProtocolEntity.getEncData()) sessionCipher = self.getSessionCipher(pkMessageProtocolEntity.getFrom(False)) plaintext = sessionCipher.decryptPkmsg(preKeyWhisperMessage) if pkMessageProtocolEntity.getVersion() == 2: plaintext = self.unpadV2Plaintext(plaintext) bodyNode = ProtocolTreeNode("body", data = plaintext) node.addChild(bodyNode) self.toUpper(node) def handleWhisperMessage(self, node): encMessageProtocolEntity = EncryptedMessageProtocolEntity.fromProtocolTreeNode(node) whisperMessage = WhisperMessage(serialized=encMessageProtocolEntity.getEncData()) sessionCipher = self.getSessionCipher(encMessageProtocolEntity.getFrom(False)) plaintext = sessionCipher.decryptMsg(whisperMessage) if encMessageProtocolEntity.getVersion() == 2: plaintext = self.unpadV2Plaintext(plaintext) bodyNode = ProtocolTreeNode("body", data = plaintext) node.addChild(bodyNode) self.toUpper(node) def unpadV2Plaintext(self, v2plaintext): if len(v2plaintext) < 128: return v2plaintext[2:-1] else: # < 128 * 128 return v2plaintext[3: -1] #### ### keys set and get def sendKeys(self, fresh = True, countPreKeys = _COUNT_PREKEYS): identityKeyPair = KeyHelper.generateIdentityKeyPair() if fresh else self.store.getIdentityKeyPair() registrationId = KeyHelper.generateRegistrationId() if fresh else self.store.getLocalRegistrationId() preKeys = KeyHelper.generatePreKeys(KeyHelper.getRandomSequence(), countPreKeys) signedPreKey = KeyHelper.generateSignedPreKey(identityKeyPair, KeyHelper.getRandomSequence(65536)) preKeysDict = {} for preKey in preKeys: keyPair = preKey.getKeyPair() preKeysDict[self.adjustId(preKey.getId())] = self.adjustArray(keyPair.getPublicKey().serialize()[1:]) signedKeyTuple = (self.adjustId(signedPreKey.getId()), self.adjustArray(signedPreKey.getKeyPair().getPublicKey().serialize()[1:]), self.adjustArray(signedPreKey.getSignature())) setKeysIq = SetKeysIqProtocolEntity(self.adjustArray(identityKeyPair.getPublicKey().serialize()[1:]), signedKeyTuple, preKeysDict, Curve.DJB_TYPE, self.adjustId(registrationId)) onResult = lambda _, __: self.persistKeys(registrationId, identityKeyPair, preKeys, signedPreKey, fresh) self._sendIq(setKeysIq, onResult, self.onSentKeysError) def persistKeys(self, registrationId, identityKeyPair, preKeys, signedPreKey, fresh): total = len(preKeys) curr = 0 prevPercentage = 0 if fresh: self.store.storeLocalData(registrationId, identityKeyPair) self.store.storeSignedPreKey(signedPreKey.getId(), signedPreKey) for preKey in preKeys: self.store.storePreKey(preKey.getId(), preKey) curr += 1 currPercentage = int((curr * 100) / total) if currPercentage == prevPercentage: continue prevPercentage = currPercentage #logger.debug("%s" % currPercentage + "%") sys.stdout.write("Storing prekeys %d%% \r" % (currPercentage)) sys.stdout.flush() if fresh: self.state = self.__class__._STATE_GENKEYS self.broadcastEvent(YowLayerEvent(YowNetworkLayer.EVENT_STATE_DISCONNECT)) def onSentKeysError(self, errorNode, keysEntity): raise Exception("Sent keys were not accepted") def onGetKeysResult(self, resultNode, getKeysEntity, processPendingFn): entity = ResultGetKeysIqProtocolEntity.fromProtocolTreeNode(resultNode) resultJids = entity.getJids() for jid in getKeysEntity.getJids(): if jid not in resultJids: self.skipEncJids.append(jid) self.processPendingMessages(jid) continue recipient_id = jid.split('@')[0] preKeyBundle = entity.getPreKeyBundleFor(jid) sessionBuilder = SessionBuilder(self.store, self.store, self.store, self.store, recipient_id, 1) sessionBuilder.processPreKeyBundle(preKeyBundle) processPendingFn(jid) def onGetKeysError(self, errorNode, getKeysEntity): pass ### def adjustArray(self, arr): return HexUtil.decodeHex(binascii.hexlify(arr)) def adjustId(self, _id): _id = format(_id, 'x') zfiller = len(_id) if len(_id) % 2 == 0 else len(_id) + 1 _id = _id.zfill(zfiller if zfiller > 6 else 6) # if len(_id) % 2: # _id = "0" + _id return binascii.unhexlify(_id) def getSessionCipher(self, recipientId): if recipientId in self.sessionCiphers: return self.sessionCiphers[recipientId] else: self.sessionCiphers[recipientId] = SessionCipher(self.store, self.store, self.store, self.store, recipientId, 1) return self.sessionCiphers[recipientId] yowsup-2.4.48/yowsup/layers/axolotl/protocolentities/000077500000000000000000000000001263346463600231315ustar00rootroot00000000000000yowsup-2.4.48/yowsup/layers/axolotl/protocolentities/__init__.py000066400000000000000000000004221263346463600252400ustar00rootroot00000000000000from .iq_key_get import GetKeysIqProtocolEntity from .iq_keys_set import SetKeysIqProtocolEntity from .iq_keys_get_result import ResultGetKeysIqProtocolEntity from .message_encrypted import EncryptedMessageProtocolEntity from .notification_encrypt import EncryptNotificationyowsup-2.4.48/yowsup/layers/axolotl/protocolentities/iq_key_get.py000066400000000000000000000015201263346463600256210ustar00rootroot00000000000000from yowsup.layers.protocol_iq.protocolentities import IqProtocolEntity from yowsup.structs import ProtocolTreeNode class GetKeysIqProtocolEntity(IqProtocolEntity): def __init__(self, jids): super(GetKeysIqProtocolEntity, self).__init__("encrypt", _type = "get", to = "s.whatsapp.net") self.setJids(jids) def setJids(self, jids): assert type(jids) is list, "expected list of jids, got %s" % type(jids) self.jids = jids def getJids(self): return self.jids def toProtocolTreeNode(self): node = super(GetKeysIqProtocolEntity, self).toProtocolTreeNode() keyNode = ProtocolTreeNode("key") for jid in self.getJids(): userNode = ProtocolTreeNode("user", { "jid": jid }) keyNode.addChild(userNode) node.addChild(keyNode) return nodeyowsup-2.4.48/yowsup/layers/axolotl/protocolentities/iq_keys_get_result.py000066400000000000000000000130141263346463600274030ustar00rootroot00000000000000from yowsup.layers.protocol_iq.protocolentities import ResultIqProtocolEntity from yowsup.structs import ProtocolTreeNode from axolotl.state.prekeybundle import PreKeyBundle from axolotl.identitykey import IdentityKey from axolotl.ecc.curve import Curve from axolotl.ecc.djbec import DjbECPublicKey import binascii import sys class ResultGetKeysIqProtocolEntity(ResultIqProtocolEntity): """ HEX:7a9cec4b HEX:05 HEX:eeb668c8d062c99b43560c811acfe6e492798b496767eb060d99e011d3862369 HEX:000000 HEX:a1b5216ce4678143fb20aaaa2711a8c2b647230164b79414f0550b4e611ccd6c HEX:94c231327fcd664b34603838b5e9ba926718d71c206e92b2b400f5cf4ae7bf17d83557bf328c1be6d51efdbd731a26d000adb8f38f140b1ea2a5fd3df2688085 HEX:36b545 HEX:c20826f622bec24b349ced38f1854bdec89ba098ef4c06b2402800d33e9aff61 """ def __init__(self, _id, preKeyBundleMap = None): super(ResultGetKeysIqProtocolEntity, self).__init__(_from = "s.whatsapp.net", _id=_id) self.setPreKeyBundleMap(preKeyBundleMap) def getJids(self): return self.preKeyBundleMap.keys() def setPreKeyBundleMap(self, preKeyBundleMap = None): self.preKeyBundleMap = preKeyBundleMap or {} def setPreKeyBundleFor(self, jid, preKeyBundle): self.preKeyBundleMap[jid] = preKeyBundle def getPreKeyBundleFor(self, jid): if jid in self.preKeyBundleMap: return self.preKeyBundleMap[jid] @staticmethod def _intToBytes(val): return binascii.unhexlify(format(val, 'x').zfill(8).encode()) @staticmethod def _bytesToInt(val): if sys.version_info >= (3,0): valEnc = val.encode('latin-1') if type(val) is str else val else: valEnc = val return int(binascii.hexlify(valEnc), 16) @staticmethod def encStr(string): if sys.version_info >= (3,0) and type(string) is str: return string.encode('latin-1') return string @staticmethod def fromProtocolTreeNode(node): entity = ResultIqProtocolEntity.fromProtocolTreeNode(node) entity.__class__ = ResultGetKeysIqProtocolEntity entity.setPreKeyBundleMap() userNodes = node.getChild("list").getAllChildren() for userNode in userNodes: preKeyNode = userNode.getChild("key") signedPreKeyNode = userNode.getChild("skey") registrationId = ResultGetKeysIqProtocolEntity._bytesToInt(userNode.getChild("registration").getData()) identityKey = IdentityKey(DjbECPublicKey(ResultGetKeysIqProtocolEntity.encStr(userNode.getChild("identity").getData()))) preKeyId = ResultGetKeysIqProtocolEntity._bytesToInt(preKeyNode.getChild("id").getData()) preKeyPublic = DjbECPublicKey(ResultGetKeysIqProtocolEntity.encStr(preKeyNode.getChild("value").getData())) signedPreKeyId = ResultGetKeysIqProtocolEntity._bytesToInt(signedPreKeyNode.getChild("id").getData()) signedPreKeySig = ResultGetKeysIqProtocolEntity.encStr(signedPreKeyNode.getChild("signature").getData()) signedPreKeyPub = DjbECPublicKey(ResultGetKeysIqProtocolEntity.encStr(signedPreKeyNode.getChild("value").getData())) preKeyBundle = PreKeyBundle(registrationId, 1, preKeyId, preKeyPublic, signedPreKeyId, signedPreKeyPub, signedPreKeySig, identityKey) entity.setPreKeyBundleFor(userNode["jid"], preKeyBundle) return entity def toProtocolTreeNode(self): node = super(ResultGetKeysIqProtocolEntity, self).toProtocolTreeNode() listNode = ProtocolTreeNode("list") node.addChild(listNode) for jid, preKeyBundle in self.preKeyBundleMap.items(): userNode = ProtocolTreeNode("user", {"jid": jid}) registrationNode = ProtocolTreeNode("registration", data = self.__class__._intToBytes(preKeyBundle.getRegistrationId())) typeNode = ProtocolTreeNode("type", data = self.__class__._intToBytes(Curve.DJB_TYPE)) identityNode = ProtocolTreeNode("identity", data = preKeyBundle.getIdentityKey().getPublicKey().getPublicKey()) skeyNode = ProtocolTreeNode("skey") skeyNode_idNode = ProtocolTreeNode("id", data=self.__class__._intToBytes(preKeyBundle.getSignedPreKeyId())) skeyNode_valueNode = ProtocolTreeNode("value", data=preKeyBundle.getSignedPreKey().getPublicKey()) skeyNode_signatureNode = ProtocolTreeNode("signature", data=preKeyBundle.getSignedPreKeySignature()) skeyNode.addChildren([skeyNode_idNode, skeyNode_valueNode, skeyNode_signatureNode]) preKeyNode = ProtocolTreeNode("key") preKeyNode_idNode = ProtocolTreeNode("id", data = self.__class__._intToBytes(preKeyBundle.getPreKeyId())) preKeyNode_valueNode = ProtocolTreeNode("value", data= preKeyBundle.getPreKey().getPublicKey()) preKeyNode.addChildren([preKeyNode_idNode, preKeyNode_valueNode]) userNode.addChildren([ registrationNode, typeNode, identityNode, skeyNode, preKeyNode ]) listNode.addChild(userNode) return node yowsup-2.4.48/yowsup/layers/axolotl/protocolentities/iq_keys_set.py000066400000000000000000000054201263346463600260230ustar00rootroot00000000000000from yowsup.layers.protocol_iq.protocolentities import IqProtocolEntity from yowsup.structs import ProtocolTreeNode import os, time class SetKeysIqProtocolEntity(IqProtocolEntity): def __init__(self, identityKey, signedPreKey, preKeys, djbType, registrationId = None): super(SetKeysIqProtocolEntity, self).__init__("encrypt", _type = "set", to = "s.whatsapp.net") self.setProps(identityKey, signedPreKey, preKeys, djbType, registrationId) def setProps(self, identityKey, signedPreKey, preKeys, djbType, registrationId = None): assert type(preKeys) is dict, "Expected keys to be a dict key_id -> public_key" assert type(signedPreKey) is tuple, "Exception signed pre key to be tuple id,key,signature" self.preKeys = preKeys self.identityKey = identityKey self.registration = registrationId or os.urandom(4) self.djbType = int(djbType) self.signedPreKey = signedPreKey @staticmethod def fromProtocolTreeNode(node): entity = IqProtocolEntity.fromProtocolTreeNode(node) entity.__class__ = SetKeysIqProtocolEntity regVal = node.getChild("registration").data typeVal = node.getChild("type").data idVal = node.getChild("identity").data preKeys = {} for keyNode in node.getChild("list").getAllChildren(): preKeys[keyNode.getChild("id").data] = keyNode.getChild("value").data skeyNode = node.getChild("skey") entity.setProps(idVal, (skeyNode.getChild("id").data, skeyNode.getChild("value").data, skeyNode.getChild("signature").data), preKeys, typeVal, regVal) return entity def toProtocolTreeNode(self): node = super(SetKeysIqProtocolEntity, self).toProtocolTreeNode() identityNode = ProtocolTreeNode("identity", data = self.identityKey) listNode = ProtocolTreeNode("list") keyNodes = [] for keyId, pk in self.preKeys.items(): keyNode = ProtocolTreeNode("key") keyNode.addChild(ProtocolTreeNode("id", data = keyId)) keyNode.addChild(ProtocolTreeNode("value", data = pk)) keyNodes.append(keyNode) listNode.addChildren(keyNodes) regNode = ProtocolTreeNode("registration", data = self.registration) typeNode = ProtocolTreeNode("type", data = chr(self.djbType)) _id, val, signature = self.signedPreKey skeyNode = ProtocolTreeNode("skey", children = [ ProtocolTreeNode("id", data = _id), ProtocolTreeNode("value", data = val), ProtocolTreeNode("signature", data = signature) ]) node.addChildren([ listNode, identityNode, regNode, typeNode, skeyNode ]) return nodeyowsup-2.4.48/yowsup/layers/axolotl/protocolentities/message_encrypted.py000066400000000000000000000045541263346463600272140ustar00rootroot00000000000000from yowsup.layers.protocol_messages.protocolentities import MessageProtocolEntity from yowsup.structs import ProtocolTreeNode import sys class EncryptedMessageProtocolEntity(MessageProtocolEntity): ''' HEX:33089eb3c90312210510e0196be72fe65913c6a84e75a54f40a3ee290574d6a23f408df990e718da761a210521f1a3f3d5cb87fde19fadf618d3001b64941715efd3e0f36bba48c23b08c82f2242330a21059b0ce2c4720ec79719ba862ee3cda6d6332746d05689af13aabf43ea1c8d747f100018002210d31cd6ebea79e441c4935f72398c772e2ee21447eb675cfa28b99de8d2013000 ''' TYPE_PKMSG = "pkmsg" TYPE_MSG = "msg" def __init__(self, encType, encVersion, encData, _type, _id = None, _from = None, to = None, notify = None, timestamp = None, participant = None, offline = None, retry = None ): super(EncryptedMessageProtocolEntity, self).__init__(_type, _id = _id, _from = _from, to = to, notify = notify, timestamp = timestamp, participant = participant, offline = offline, retry = retry) self.setEncProps(encType, encVersion, encData) def setEncProps(self, encType, encVersion, encData): assert encType in "pkmsg", "msg" self.encType = encType self.encVersion = int(encVersion) self.encData = encData def getEncType(self): return self.encType def getEncData(self): return self.encData def getVersion(self): return self.encVersion def toProtocolTreeNode(self): node = super(EncryptedMessageProtocolEntity, self).toProtocolTreeNode() encNode = ProtocolTreeNode("enc", data = self.encData) encNode["type"] = self.encType encNode["v"] = str(self.encVersion) node.addChild(encNode) return node @staticmethod def fromProtocolTreeNode(node): entity = MessageProtocolEntity.fromProtocolTreeNode(node) entity.__class__ = EncryptedMessageProtocolEntity encNode = node.getChild("enc") entity.setEncProps(encNode["type"], encNode["v"], encNode.data.encode('latin-1') if sys.version_info >= (3,0) else encNode.data) return entityyowsup-2.4.48/yowsup/layers/axolotl/protocolentities/notification_encrypt.py000066400000000000000000000022351263346463600277370ustar00rootroot00000000000000from yowsup.layers.protocol_notifications.protocolentities import NotificationProtocolEntity from yowsup.structs import ProtocolTreeNode class EncryptNotification(NotificationProtocolEntity): """ """ def __init__(self, count, timestamp, _id = None, notify = None, offline = None): super(EncryptNotification, self).__init__("encrypt", _id, "s.whatsapp.net", timestamp, notify, offline) self.setProps(count) def setProps(self, count): self.count = int(count) def getCount(self): return self.count def toProtocolTreeNode(self): node = super(EncryptNotification, self).toProtocolTreeNode() countNode = ProtocolTreeNode("count", {"value": str(self.count)}) node.addChild(countNode) return node @staticmethod def fromProtocolTreeNode(node): entity = NotificationProtocolEntity.fromProtocolTreeNode(node) entity.__class__ = EncryptNotification entity.setProps(node.getChild("count")["value"]) return entityyowsup-2.4.48/yowsup/layers/axolotl/protocolentities/receipt_outgoing_retry.py000066400000000000000000000046311263346463600303020ustar00rootroot00000000000000from yowsup.structs import ProtocolEntity, ProtocolTreeNode from yowsup.layers.protocol_receipts.protocolentities import OutgoingReceiptProtocolEntity from yowsup.layers.axolotl.protocolentities.iq_keys_get_result import ResultGetKeysIqProtocolEntity class RetryOutgoingReceiptProtocolEntity(OutgoingReceiptProtocolEntity): ''' HEX:xxxxxxxxx ''' def __init__(self, _id, to, t, v = "1", count = "1",regData = ""): super(RetryOutgoingReceiptProtocolEntity, self).__init__(_id,to) self.setRetryData(t,v,count,regData) def setRetryData(self, t,v,count,regData): self.t = int(t) self.v = int(v) self.count = int(count) self.regData = regData def setRegData(self,regData): ''' In axolotl layer: regData = self.store.getLocalRegistrationId() ''' self.regData = ResultGetKeysIqProtocolEntity._intToBytes(regData) def toProtocolTreeNode(self): node = super(RetryOutgoingReceiptProtocolEntity, self).toProtocolTreeNode() node.setAttribute("type", "retry") retry = ProtocolTreeNode("retry", {"count": str(self.count),"t":str(self.t),"id":self.getId(),"v":str(self.v)}) node.addChild(retry) registration = ProtocolTreeNode("registration",data=self.regData) node.addChild(registration) return node def __str__(self): out = super(RetryOutgoingReceiptProtocolEntity, self).__str__() return out @staticmethod def fromProtocolTreeNode(node): entity = OutgoingReceiptProtocolEntity.fromProtocolTreeNode(node) entity.__class__ = RetryOutgoingReceiptProtocolEntity retryNode = node.getChild("retry") entity.setRetryData(retryNode["t"], retryNode["v"], retryNode["count"], node.getChild("registration").data) @staticmethod def fromMesageNode(MessageNodeToBeRetried): return RetryOutgoingReceiptProtocolEntity( MessageNodeToBeRetried.getAttributeValue("id"), MessageNodeToBeRetried.getAttributeValue("from"), MessageNodeToBeRetried.getAttributeValue("t"), MessageNodeToBeRetried.getChild("enc").getAttributeValue("v") )yowsup-2.4.48/yowsup/layers/axolotl/protocolentities/test_iq_keys_get_result.py000066400000000000000000000053511263346463600304470ustar00rootroot00000000000000from yowsup.layers.protocol_iq.protocolentities.test_iq_result import ResultIqProtocolEntityTest from yowsup.layers.axolotl.protocolentities import ResultGetKeysIqProtocolEntity from yowsup.structs import ProtocolTreeNode from axolotl.util.keyhelper import KeyHelper from axolotl.ecc.curve import Curve class ResultGetKeysIqProtocolEntityTest(ResultIqProtocolEntityTest): def setUp(self): super(ResultIqProtocolEntityTest, self).setUp() self.ProtocolEntity = ResultGetKeysIqProtocolEntity listNode = ProtocolTreeNode("list") self.node.addChild(listNode) for i in range(0, 1): userNode = ProtocolTreeNode("user", {"jid": "user_%s@s.whatsapp.net" % i}) listNode.addChild(userNode) registrationNode = ProtocolTreeNode("registration", data = ResultGetKeysIqProtocolEntity._intToBytes( KeyHelper.generateRegistrationId())) typeNode = ProtocolTreeNode("type", data = ResultGetKeysIqProtocolEntity._intToBytes(Curve.DJB_TYPE)) identityKeyPair = KeyHelper.generateIdentityKeyPair() identityNode = ProtocolTreeNode("identity", data=identityKeyPair.getPublicKey().getPublicKey().getPublicKey()) signedPreKey = KeyHelper.generateSignedPreKey(identityKeyPair, i) signedPreKeyNode = ProtocolTreeNode("skey") signedPreKeyNode_idNode = ProtocolTreeNode("id", data = ResultGetKeysIqProtocolEntity._intToBytes( signedPreKey.getId())) signedPreKeyNode_valueNode = ProtocolTreeNode("value", data = signedPreKey.getKeyPair().getPublicKey().getPublicKey()) signedPreKeyNode_sigNode = ProtocolTreeNode("signature", data = signedPreKey.getSignature()) signedPreKeyNode.addChildren([signedPreKeyNode_idNode, signedPreKeyNode_valueNode, signedPreKeyNode_sigNode]) preKey = KeyHelper.generatePreKeys(i * 10, 1)[0] preKeyNode = ProtocolTreeNode("key") preKeyNode_idNode = ProtocolTreeNode("id", data = ResultGetKeysIqProtocolEntity._intToBytes(preKey.getId())) preKeyNode_valNode = ProtocolTreeNode("value", data = preKey.getKeyPair().getPublicKey().getPublicKey()) preKeyNode.addChildren([preKeyNode_idNode, preKeyNode_valNode]) userNode.addChildren([ registrationNode, typeNode, identityNode, signedPreKeyNode, preKeyNode ]) yowsup-2.4.48/yowsup/layers/axolotl/protocolentities/test_iq_keys_set.py000066400000000000000000000017471263346463600270720ustar00rootroot00000000000000from yowsup.layers.protocol_iq.protocolentities.test_iq import IqProtocolEntityTest from yowsup.layers.axolotl.protocolentities import SetKeysIqProtocolEntity from yowsup.structs import ProtocolTreeNode class SetKeysIqProtocolEntityTest(IqProtocolEntityTest): def setUp(self): super(SetKeysIqProtocolEntityTest, self).setUp() # self.ProtocolEntity = SetKeysIqProtocolEntity # # regNode = ProtocolTreeNode("registration", data = "abcd") # idNode = ProtocolTreeNode("identity", data = "efgh") # typeNode = ProtocolTreeNode("type", data = "ijkl") # listNode = ProtocolTreeNode("list") # for i in range(0, 2): # keyNode = ProtocolTreeNode("key", children=[ # ProtocolTreeNode("id", data = "id_%s" % i), # ProtocolTreeNode("value", data = "val_%s" % i) # ]) # listNode.addChild(keyNode) # # self.node.addChildren([regNode, idNode, typeNode, listNode]) yowsup-2.4.48/yowsup/layers/axolotl/protocolentities/test_notification_encrypt.py000066400000000000000000000007461263346463600310030ustar00rootroot00000000000000from yowsup.layers.protocol_notifications.protocolentities.test_notification import NotificationProtocolEntityTest from yowsup.layers.axolotl.protocolentities import EncryptNotification from yowsup.structs import ProtocolTreeNode class TestEncryptNotification(NotificationProtocolEntityTest): def setUp(self): super(TestEncryptNotification, self).setUp() self.ProtocolEntity = EncryptNotification self.node.addChild(ProtocolTreeNode("count", {"value": "9"}))yowsup-2.4.48/yowsup/layers/axolotl/store/000077500000000000000000000000001263346463600206575ustar00rootroot00000000000000yowsup-2.4.48/yowsup/layers/axolotl/store/__init__.py000066400000000000000000000000001263346463600227560ustar00rootroot00000000000000yowsup-2.4.48/yowsup/layers/axolotl/store/sqlite/000077500000000000000000000000001263346463600221605ustar00rootroot00000000000000yowsup-2.4.48/yowsup/layers/axolotl/store/sqlite/__init__.py000066400000000000000000000000251263346463600242660ustar00rootroot00000000000000__author__ = 'tarek' yowsup-2.4.48/yowsup/layers/axolotl/store/sqlite/liteaxolotlstore.py000066400000000000000000000057641263346463600261630ustar00rootroot00000000000000from axolotl.state.axolotlstore import AxolotlStore from .liteidentitykeystore import LiteIdentityKeyStore from .liteprekeystore import LitePreKeyStore from .litesessionstore import LiteSessionStore from .litesignedprekeystore import LiteSignedPreKeyStore import sqlite3 class LiteAxolotlStore(AxolotlStore): def __init__(self, db): conn = sqlite3.connect(db, check_same_thread=False) conn.text_factory = bytes self.identityKeyStore = LiteIdentityKeyStore(conn) self.preKeyStore = LitePreKeyStore(conn) self.signedPreKeyStore = LiteSignedPreKeyStore(conn) self.sessionStore = LiteSessionStore(conn) def getIdentityKeyPair(self): return self.identityKeyStore.getIdentityKeyPair() def storeLocalData(self, registrationId, identityKeyPair): self.identityKeyStore.storeLocalData(registrationId, identityKeyPair) def getLocalRegistrationId(self): return self.identityKeyStore.getLocalRegistrationId() def saveIdentity(self, recepientId, identityKey): self.identityKeyStore.saveIdentity(recepientId, identityKey) def isTrustedIdentity(self, recepientId, identityKey): return self.identityKeyStore.isTrustedIdentity(recepientId, identityKey) def loadPreKey(self, preKeyId): return self.preKeyStore.loadPreKey(preKeyId) def loadPreKeys(self): return self.preKeyStore.loadPendingPreKeys() def storePreKey(self, preKeyId, preKeyRecord): self.preKeyStore.storePreKey(preKeyId, preKeyRecord) def containsPreKey(self, preKeyId): return self.preKeyStore.containsPreKey(preKeyId) def removePreKey(self, preKeyId): self.preKeyStore.removePreKey(preKeyId) def loadSession(self, recepientId, deviceId): return self.sessionStore.loadSession(recepientId, deviceId) def getSubDeviceSessions(self, recepientId): return self.sessionStore.getSubDeviceSessions(recepientId) def storeSession(self, recepientId, deviceId, sessionRecord): self.sessionStore.storeSession(recepientId, deviceId, sessionRecord) def containsSession(self, recepientId, deviceId): return self.sessionStore.containsSession(recepientId, deviceId) def deleteSession(self, recepientId, deviceId): self.sessionStore.deleteSession(recepientId, deviceId) def deleteAllSessions(self, recepientId): self.sessionStore.deleteAllSessions(recepientId) def loadSignedPreKey(self, signedPreKeyId): return self.signedPreKeyStore.loadSignedPreKey(signedPreKeyId) def loadSignedPreKeys(self): return self.signedPreKeyStore.loadSignedPreKeys() def storeSignedPreKey(self, signedPreKeyId, signedPreKeyRecord): self.signedPreKeyStore.storeSignedPreKey(signedPreKeyId, signedPreKeyRecord) def containsSignedPreKey(self, signedPreKeyId): return self.signedPreKeyStore.containsSignedPreKey(signedPreKeyId) def removeSignedPreKey(self, signedPreKeyId): self.signedPreKeyStore.removeSignedPreKey(signedPreKeyId)yowsup-2.4.48/yowsup/layers/axolotl/store/sqlite/liteidentitykeystore.py000066400000000000000000000053771263346463600270430ustar00rootroot00000000000000from axolotl.state.identitykeystore import IdentityKeyStore from axolotl.ecc.curve import Curve from axolotl.identitykey import IdentityKey from axolotl.util.keyhelper import KeyHelper from axolotl.identitykeypair import IdentityKeyPair from axolotl.ecc.djbec import * class LiteIdentityKeyStore(IdentityKeyStore): def __init__(self, dbConn): """ :type dbConn: Connection """ self.dbConn = dbConn dbConn.execute("CREATE TABLE IF NOT EXISTS identities (_id INTEGER PRIMARY KEY AUTOINCREMENT," "recipient_id INTEGER UNIQUE," "registration_id INTEGER, public_key BLOB, private_key BLOB," "next_prekey_id INTEGER, timestamp INTEGER);") #identityKeyPairKeys = Curve.generateKeyPair() #self.identityKeyPair = IdentityKeyPair(IdentityKey(identityKeyPairKeys.getPublicKey()), # identityKeyPairKeys.getPrivateKey()) # self.localRegistrationId = KeyHelper.generateRegistrationId() def getIdentityKeyPair(self): q = "SELECT public_key, private_key FROM identities WHERE recipient_id = -1" c = self.dbConn.cursor() c.execute(q) result = c.fetchone() publicKey, privateKey = result return IdentityKeyPair(IdentityKey(DjbECPublicKey(publicKey[1:])), DjbECPrivateKey(privateKey)) def getLocalRegistrationId(self): q = "SELECT registration_id FROM identities WHERE recipient_id = -1" c = self.dbConn.cursor() c.execute(q) result = c.fetchone() return result[0] if result else None def storeLocalData(self, registrationId, identityKeyPair): q = "INSERT INTO identities(recipient_id, registration_id, public_key, private_key) VALUES(-1, ?, ?, ?)" c = self.dbConn.cursor() c.execute(q, (registrationId, identityKeyPair.getPublicKey().getPublicKey().serialize(), identityKeyPair.getPrivateKey().serialize())) self.dbConn.commit() def saveIdentity(self, recipientId, identityKey): q = "DELETE FROM identities WHERE recipient_id=?" self.dbConn.cursor().execute(q, (recipientId,)) self.dbConn.commit() q = "INSERT INTO identities (recipient_id, public_key) VALUES(?, ?)" c = self.dbConn.cursor() c.execute(q, (recipientId, identityKey.getPublicKey().serialize())) self.dbConn.commit() def isTrustedIdentity(self, recipientId, identityKey): q = "SELECT public_key from identities WHERE recipient_id = ?" c = self.dbConn.cursor() c.execute(q, (recipientId,)) result = c.fetchone() if not result: return True return result[0] == identityKey.getPublicKey().serialize()yowsup-2.4.48/yowsup/layers/axolotl/store/sqlite/liteprekeystore.py000066400000000000000000000033211263346463600257630ustar00rootroot00000000000000from axolotl.state.prekeystore import PreKeyStore from axolotl.state.prekeyrecord import PreKeyRecord class LitePreKeyStore(PreKeyStore): def __init__(self, dbConn): """ :type dbConn: Connection """ self.dbConn = dbConn dbConn.execute("CREATE TABLE IF NOT EXISTS prekeys (_id INTEGER PRIMARY KEY AUTOINCREMENT," "prekey_id INTEGER UNIQUE, sent_to_server BOOLEAN, record BLOB);") def loadPreKey(self, preKeyId): q = "SELECT record FROM prekeys WHERE prekey_id = ?" cursor = self.dbConn.cursor() cursor.execute(q, (preKeyId,)) result = cursor.fetchone() if not result: raise Exception("No such prekeyRecord!") return PreKeyRecord(serialized = result[0]) def loadPendingPreKeys(self): q = "SELECT record FROM prekeys" cursor = self.dbConn.cursor() cursor.execute(q) result = cursor.fetchall() return [PreKeyRecord(serialized=result[0]) for result in result] def storePreKey(self, preKeyId, preKeyRecord): #self.removePreKey(preKeyId) q = "INSERT INTO prekeys (prekey_id, record) VALUES(?,?)" cursor = self.dbConn.cursor() cursor.execute(q, (preKeyId, preKeyRecord.serialize())) self.dbConn.commit() def containsPreKey(self, preKeyId): q = "SELECT record FROM prekeys WHERE prekey_id = ?" cursor = self.dbConn.cursor() cursor.execute(q, (preKeyId,)) return cursor.fetchone() is not None def removePreKey(self, preKeyId): q = "DELETE FROM prekeys WHERE prekey_id = ?" cursor = self.dbConn.cursor() cursor.execute(q, (preKeyId,)) self.dbConn.commit() yowsup-2.4.48/yowsup/layers/axolotl/store/sqlite/litesessionstore.py000066400000000000000000000041531263346463600261530ustar00rootroot00000000000000from axolotl.state.sessionstore import SessionStore from axolotl.state.sessionrecord import SessionRecord class LiteSessionStore(SessionStore): def __init__(self, dbConn): """ :type dbConn: Connection """ self.dbConn = dbConn dbConn.execute("CREATE TABLE IF NOT EXISTS sessions (_id INTEGER PRIMARY KEY AUTOINCREMENT," "recipient_id INTEGER UNIQUE, device_id INTEGER, record BLOB, timestamp INTEGER);") def loadSession(self, recipientId, deviceId): q = "SELECT record FROM sessions WHERE recipient_id = ? AND device_id = ?" c = self.dbConn.cursor() c.execute(q, (recipientId, deviceId)) result = c.fetchone() if result: return SessionRecord(serialized=result[0]) else: return SessionRecord() def getSubDeviceSessions(self, recipientId): q = "SELECT device_id from sessions WHERE recipient_id = ?" c = self.dbConn.cursor() c.execute(q, (recipientId,)) result = c.fetchall() deviceIds = [r[0] for r in result] return deviceIds def storeSession(self, recipientId, deviceId, sessionRecord): self.deleteSession(recipientId, deviceId) q = "INSERT INTO sessions(recipient_id, device_id, record) VALUES(?,?,?)" c = self.dbConn.cursor() c.execute(q, (recipientId, deviceId, sessionRecord.serialize())) self.dbConn.commit() def containsSession(self, recipientId, deviceId): q = "SELECT record FROM sessions WHERE recipient_id = ? AND device_id = ?" c = self.dbConn.cursor() c.execute(q, (recipientId, deviceId)) result = c.fetchone() return result is not None def deleteSession(self, recipientId, deviceId): q = "DELETE FROM sessions WHERE recipient_id = ? AND device_id = ?" self.dbConn.cursor().execute(q, (recipientId, deviceId)) self.dbConn.commit() def deleteAllSessions(self, recipientId): q = "DELETE FROM sessions WHERE recipient_id = ?" self.dbConn.cursor().execute(q, (recipientId,)) self.dbConn.commit() yowsup-2.4.48/yowsup/layers/axolotl/store/sqlite/litesignedprekeystore.py000066400000000000000000000042171263346463600271620ustar00rootroot00000000000000from axolotl.state.signedprekeystore import SignedPreKeyStore from axolotl.state.signedprekeyrecord import SignedPreKeyRecord from axolotl.invalidkeyidexception import InvalidKeyIdException class LiteSignedPreKeyStore(SignedPreKeyStore): def __init__(self, dbConn): """ :type dbConn: Connection """ self.dbConn = dbConn dbConn.execute("CREATE TABLE IF NOT EXISTS signed_prekeys (_id INTEGER PRIMARY KEY AUTOINCREMENT," "prekey_id INTEGER UNIQUE, timestamp INTEGER, record BLOB);") def loadSignedPreKey(self, signedPreKeyId): q = "SELECT record FROM signed_prekeys WHERE prekey_id = ?" cursor = self.dbConn.cursor() cursor.execute(q, (signedPreKeyId,)) result = cursor.fetchone() if not result: raise InvalidKeyIdException("No such signedprekeyrecord! %s " % signedPreKeyId) return SignedPreKeyRecord(serialized=result[0]) def loadSignedPreKeys(self): q = "SELECT record FROM signed_prekeys" cursor = self.dbConn.cursor() cursor.execute(q,) result = cursor.fetchall() results = [] for row in result: results.append(SignedPreKeyRecord(serialized=row[0])) return results def storeSignedPreKey(self, signedPreKeyId, signedPreKeyRecord): #q = "DELETE FROM signed_prekeys WHERE prekey_id = ?" #self.dbConn.cursor().execute(q, (signedPreKeyId,)) #self.dbConn.commit() q = "INSERT INTO signed_prekeys (prekey_id, record) VALUES(?,?)" cursor = self.dbConn.cursor() cursor.execute(q, (signedPreKeyId, signedPreKeyRecord.serialize())) self.dbConn.commit() def containsSignedPreKey(self, signedPreKeyId): q = "SELECT record FROM signed_prekeys WHERE prekey_id = ?" cursor = self.dbConn.cursor() cursor.execute(q, (signedPreKeyId,)) return cursor.fetchone() is not None def removeSignedPreKey(self, signedPreKeyId): q = "DELETE FROM signed_prekeys WHERE prekey_id = ?" cursor = self.dbConn.cursor() cursor.execute(q, (signedPreKeyId,)) self.dbConn.commit() yowsup-2.4.48/yowsup/layers/coder/000077500000000000000000000000001263346463600171355ustar00rootroot00000000000000yowsup-2.4.48/yowsup/layers/coder/__init__.py000066400000000000000000000000401263346463600212400ustar00rootroot00000000000000from .layer import YowCoderLayeryowsup-2.4.48/yowsup/layers/coder/decoder.py000066400000000000000000000123511263346463600211160ustar00rootroot00000000000000from yowsup.structs import ProtocolTreeNode import math class ReadDecoder: def __init__(self, tokenDictionary): self.streamStarted = False; self.tokenDictionary = tokenDictionary def reset(self): self.streamStarted = False def getProtocolTreeNode(self, data): if not self.streamStarted: return self.streamStart(data) return self.nextTreeInternal(data) def _getToken(self, index, data): token = self.tokenDictionary.getToken(index) if not token: index = self.readInt8(data) token = self.tokenDictionary.getToken(index, True) if not token: raise ValueError("Invalid token %s" % token) return token def streamStart(self, data): self.streamStarted = True tag = data.pop(0) size = self.readListSize(tag, data) tag = data.pop(0) if tag != 1: if tag == 236: tag = data.pop(0) + 237 token = self._getToken(tag, data)#self.tokenDictionary.getToken(tag) raise Exception("expecting STREAM_START in streamStart, instead got token: %s" % token) attribCount = (size - 2 + size % 2) / 2 self.readAttributes(attribCount, data) def readNibble(self, data): _byte = self.readInt8(data) ignoreLastNibble = bool(_byte & 0x80) size = (_byte & 0x7f); nrOfNibbles = size * 2 - int(ignoreLastNibble) dataArr = self.readArray(size, data) string = '' for i in range(0, nrOfNibbles): _byte = dataArr[int(math.floor(i/2))] _shift = 4 * (1 - i % 2) dec = (_byte & (15 << _shift)) >> _shift if dec in (0,1,2,3,4,5,6,7,8,9): string += str(dec) elif dec in (10, 11): string += chr(dec - 10 + 45) else: raise Exception("Bad nibble %s" % dec) return string def readInt8(self,data): return data.pop(0); def readInt16(self, data): intTop = data.pop(0) intBot = data.pop(0) value = (intTop << 8) + intBot if value is not None: return value else: return "" def readInt24(self,data): int1 = data.pop(0) int2 = data.pop(0) int3 = data.pop(0) value = (int1 << 16) + (int2 << 8) + (int3 << 0) return value def readListSize(self,token, data): size = 0 if token == 0: size = 0 else: if token == 248: size = self.readInt8(data) else: if token == 249: size = self.readInt16(data) else: raise Exception("invalid list size in readListSize: token " + str(token)) return size def readAttributes(self, attribCount, data): attribs = {} for i in range(0, int(attribCount)): key = self.readString(data.pop(0), data) value = self.readString(data.pop(0), data) attribs[key]=value return attribs def readString(self,token, data): if token == -1: raise Exception("-1 token in readString") if token > 2 and token < 245: return self._getToken(token, data) if token == 0: return None if token == 252: size8 = self.readInt8(data) buf8 = self.readArray(size8, data) return "".join(map(chr, buf8)) if token == 253: size24 = self.readInt24(data) buf24 = self.readArray(size24, data) return "".join(map(chr, buf24)) if token == 250: user = self.readString(data.pop(0), data) server = self.readString(data.pop(0), data) if user is not None and server is not None: return user + "@" + server if server is not None: return server raise Exception("readString couldn't reconstruct jid") elif token == 255: return self.readNibble(data) raise Exception("readString couldn't match token "+str(token)) def readArray(self, length, data): out = [] for i in range(0, length): out.append(data.pop(0)) return out def nextTreeInternal(self, data): b = data.pop(0) size = self.readListSize(b, data) b = data.pop(0) if b == 2: return None tag = self.readString(b, data) if size == 0 or tag is None: raise ValueError("nextTree sees 0 list or null tag") attribCount = (size - 2 + size % 2)/2; attribs = self.readAttributes(attribCount, data) if size % 2 ==1: return ProtocolTreeNode(tag, attribs) b = data.pop(0) if self.isListTag(b): return ProtocolTreeNode(tag,attribs,self.readList(b, data)) return ProtocolTreeNode(tag, attribs, None, self.readString(b, data)) def readList(self,token, data): size = self.readListSize(token, data) listx = [] for i in range(0,size): listx.append(self.nextTreeInternal(data)) return listx; def isListTag(self, b): return b in (248, 0, 249) yowsup-2.4.48/yowsup/layers/coder/encoder.py000066400000000000000000000076461263346463600211430ustar00rootroot00000000000000class WriteEncoder: def __init__(self, tokenDictionary): self.tokenDictionary = tokenDictionary self.streamStarted = False def reset(self): self.streamStarted = False def getStreamStartBytes(self, domain, resource): data = [] self.streamStarted = True data.append(87) data.append(65) data.append(1) data.append(5) streamOpenAttributes = {"to": domain, "resource": resource} self.writeListStart(len(streamOpenAttributes) * 2 + 1, data) data.append(1); self.writeAttributes(streamOpenAttributes, data) return data def protocolTreeNodeToBytes(self, node): outBytes = [] self.writeInternal(node, outBytes) return outBytes def writeInternal(self, node, data): x = 1 + \ (0 if node.attributes is None else len(node.attributes) * 2) + \ (0 if not node.hasChildren() else 1) + \ (0 if node.data is None else 1) self.writeListStart(x, data) self.writeString(node.tag, data) self.writeAttributes(node.attributes, data); if node.data is not None: self.writeBytes(node.data, data) if node.hasChildren(): self.writeListStart(len(node.children), data); for c in node.children: self.writeInternal(c, data); def writeAttributes(self, attributes, data): if attributes is not None: for key, value in attributes.items(): self.writeString(key, data); self.writeString(value, data); def writeBytes(self, bytes, data): length = len(bytes) if length >= 256: data.append(253) self.writeInt24(length, data) else: data.append(252) self.writeInt8(length, data) for b in bytes: if type(b) is int: data.append(b) else: data.append(ord(b)) def writeInt8(self, v, data): data.append(v & 0xFF) def writeInt16(self, v, data): data.append((v & 0xFF00) >> 8); data.append((v & 0xFF) >> 0); def writeInt24(self, v, data): data.append((v & 0xFF0000) >> 16) data.append((v & 0xFF00) >> 8) data.append((v & 0xFF) >> 0) def writeListStart(self, i, data): if i == 0: data.append(0) elif i < 256: data.append(248) self.writeInt8(i, data) else: data.append(249) self.writeInt16(i, data) def writeToken(self, intValue, data): if intValue < 245: data.append(intValue) elif intValue <=500: data.append(254) data.append(intValue - 245) def writeString(self, tag, data): tok = self.tokenDictionary.getIndex(tag) if tok: index, secondary = tok if secondary: self.writeToken(236, data) self.writeToken(index, data) else: at = '@'.encode() if type(tag) == bytes else '@' try: atIndex = tag.index(at) if atIndex < 1: raise ValueError("atIndex < 1") else: server = tag[atIndex+1:] user = tag[0:atIndex] self.writeJid(user, server, data) except ValueError: self.writeBytes(self.encodeString(tag), data) def encodeString(self, string): res = [] if type(string) == bytes: for char in string: res.append(char) else: for char in string: res.append(ord(char)) return res; def writeJid(self, user, server, data): data.append(250) if user is not None: self.writeString(user, data) else: self.writeToken(0, data) self.writeString(server, data) yowsup-2.4.48/yowsup/layers/coder/layer.py000066400000000000000000000027101263346463600206230ustar00rootroot00000000000000from yowsup.layers import YowLayer, YowLayerEvent from yowsup.layers.network import YowNetworkLayer from .encoder import WriteEncoder from .decoder import ReadDecoder from .tokendictionary import TokenDictionary class YowCoderLayer(YowLayer): PROP_DOMAIN = "org.openwhatsapp.yowsup.prop.domain" PROP_RESOURCE = "org.openwhatsapp.yowsup.prop.resource" def __init__(self): YowLayer.__init__(self) tokenDictionary = TokenDictionary() self.writer = WriteEncoder(tokenDictionary) self.reader = ReadDecoder(tokenDictionary) def onEvent(self, event): if event.getName() == YowNetworkLayer.EVENT_STATE_CONNECTED: self.writer.reset() self.reader.reset() streamStartBytes = self.writer.getStreamStartBytes( self.getProp(self.__class__.PROP_DOMAIN), self.getProp(self.__class__.PROP_RESOURCE) ) for i in range(0, 4): self.write(streamStartBytes.pop(0)) self.write(streamStartBytes) def send(self, data): self.write(self.writer.protocolTreeNodeToBytes(data)) def receive(self, data): node = self.reader.getProtocolTreeNode(data) if node: self.toUpper(node) def write(self, i): if(type(i) in(list, tuple)): self.toLower(bytearray(i)) else: self.toLower(bytearray([i])) def __str__(self): return "Coder Layer"yowsup-2.4.48/yowsup/layers/coder/test_decoder.py000066400000000000000000000014601263346463600221540ustar00rootroot00000000000000import unittest from yowsup.layers.coder.decoder import ReadDecoder from yowsup.layers.coder.tokendictionary import TokenDictionary from yowsup.structs import ProtocolTreeNode class DecoderTest(unittest.TestCase): def setUp(self): self.decoder = ReadDecoder(TokenDictionary()) self.decoder.streamStarted = True def test_decode(self): data = [248, 6, 89, 165, 252, 3, 120, 121, 122, 252, 4, 102, 111, 114, 109, 252, 3, 97, 98, 99, 248, 1, 248, 4, 87, 236, 99, 252, 3, 49, 50, 51, 252, 6, 49, 50, 51, 52, 53, 54] node = self.decoder.getProtocolTreeNode(data) targetNode = ProtocolTreeNode("message", {"form": "abc", "to":"xyz"}, [ProtocolTreeNode("media", {"width" : "123"}, data="123456")]) self.assertEqual(node, targetNode) yowsup-2.4.48/yowsup/layers/coder/test_encoder.py000066400000000000000000000017711263346463600221730ustar00rootroot00000000000000import unittest from yowsup.structs import ProtocolTreeNode from yowsup.layers.coder.encoder import WriteEncoder from yowsup.layers.coder.tokendictionary import TokenDictionary class EncoderTest(unittest.TestCase): def setUp(self): self.res = [] self.encoder = WriteEncoder(TokenDictionary()) def test_encode(self): node = ProtocolTreeNode("message", {"form": "abc", "to":"xyz"}, [ProtocolTreeNode("media", {"width" : "123"}, data="123456")]) result = self.encoder.protocolTreeNodeToBytes(node) self.assertTrue(result in ( [248, 6, 89, 252, 4, 102, 111, 114, 109, 252, 3, 97, 98, 99, 165, 252, 3, 120, 121, 122, 248, 1, 248, 4, 87, 236, 99, 252, 3, 49, 50, 51, 252, 6, 49, 50, 51, 52, 53, 54], [248, 6, 89, 165, 252, 3, 120, 121, 122, 252, 4, 102, 111, 114, 109, 252, 3, 97, 98, 99, 248, 1, 248, 4, 87, 236, 99, 252, 3, 49, 50, 51, 252, 6, 49, 50, 51, 52, 53, 54]) ) yowsup-2.4.48/yowsup/layers/coder/test_tokendictionary.py000066400000000000000000000013371263346463600237600ustar00rootroot00000000000000from yowsup.layers.coder.tokendictionary import TokenDictionary import unittest class TokenDictionaryTest(unittest.TestCase): def setUp(self): self.tokenDictionary = TokenDictionary() def test_getToken(self): self.assertEqual(self.tokenDictionary.getToken(74), "iq") def test_getIndex(self): self.assertEqual(self.tokenDictionary.getIndex("iq"), (74, False)) def test_getSecondaryToken(self): self.assertEqual(self.tokenDictionary.getToken(238), "wmv") def test_getSecondaryTokenExplicit(self): self.assertEqual(self.tokenDictionary.getToken(1, True), "wmv") def test_getSecondaryIndex(self): self.assertEqual(self.tokenDictionary.getIndex("wmv"), (1, True))yowsup-2.4.48/yowsup/layers/coder/tokendictionary.py000066400000000000000000000267671263346463600227370ustar00rootroot00000000000000class TokenDictionary: def __init__(self): self.dictionary = [ "", "", "", "account", "ack", "action", "active", "add", "after", "all", "allow", "apple", "auth", "author", "available", "bad-protocol", "bad-request", "before", "body", "broadcast", "cancel", "category", "challenge", "chat", "clean", "code", "composing", "config", "contacts", "count", "create", "creation", "debug", "default", "delete", "delivery", "delta", "deny", "digest", "dirty", "duplicate", "elapsed", "enable", "encoding", "error", "event", "expiration", "expired", "fail", "failure", "false", "favorites", "feature", "features", "feature-not-implemented", "field", "first", "free", "from", "g.us", "get", "google", "group", "groups", "groups_v2", "http://etherx.jabber.org/streams", "http://jabber.org/protocol/chatstates", "ib", "id", "image", "img", "index", "internal-server-error", "ip", "iq", "item-not-found", "item", "jabber:iq:last", "jabber:iq:privacy", "jabber:x:event", "jid", "kind", "last", "leave", "list", "max", "mechanism", "media", "message_acks", "message", "method", "microsoft", "missing", "modify", "mute", "name", "nokia", "none", "not-acceptable", "not-allowed", "not-authorized", "notification", "notify", "off", "offline", "order", "owner", "owning", "p_o", "p_t", "paid", "participant", "participants", "participating", "paused", "picture", "pin", "ping", "platform", "port", "presence", "preview", "probe", "prop", "props", "query", "raw", "read", "readreceipts", "reason", "receipt", "relay", "remote-server-timeout", "remove", "request", "required", "resource-constraint", "resource", "response", "result", "retry", "rim", "s_o", "s_t", "s.us", "s.whatsapp.net", "seconds", "server-error", "server", "service-unavailable", "set", "show", "silent", "stat", "status", "stream:error", "stream:features", "subject", "subscribe", "success", "sync", "t", "text", "timeout", "timestamp", "to", "true", "type", "unavailable", "unsubscribe", "uri", "url", "urn:ietf:params:xml:ns:xmpp-sasl", "urn:ietf:params:xml:ns:xmpp-stanzas", "urn:ietf:params:xml:ns:xmpp-streams", "urn:xmpp:ping", "urn:xmpp:whatsapp:account", "urn:xmpp:whatsapp:dirty", "urn:xmpp:whatsapp:mms", "urn:xmpp:whatsapp:push", "urn:xmpp:whatsapp", "user", "user-not-found", "value", "version", "w:g", "w:p:r", "w:p", "w:profile:picture", "w", "wait", "WAUTH-2", "xmlns:stream", "xmlns", "1", "chatstate", "crypto", "phash", "enc", "class", "off_cnt", "w:g2", "promote", "demote", "creator", "Bell.caf", "Boing.caf", "Glass.caf", "Harp.caf", "TimePassing.caf", "Tri-tone.caf", "Xylophone.caf", "background", "backoff", "chunked", "context", "full", "in", "interactive", "out", "registration", "sid", "urn:xmpp:whatsapp:sync", "flt", "s16", "u8", "adpcm", "amrnb", "amrwb", "mp3", "pcm", "qcelp", "wma", "h263", "h264", "jpeg" ] self.secondaryDictionary = [ "mpeg4", "wmv", "audio/3gpp", "audio/aac", "audio/amr", "audio/mp4", "audio/mpeg", "audio/ogg", "audio/qcelp", "audio/wav", "audio/webm", "audio/x-caf", "audio/x-ms-wma", "image/gif", "image/jpeg", "image/png", "video/3gpp", "video/avi", "video/mp4", "video/mpeg", "video/quicktime", "video/x-flv", "video/x-ms-asf", "302", "400", "401", "402", "403", "404", "405", "406", "407", "409", "410", "500", "501", "503", "504", "abitrate", "acodec", "app_uptime", "asampfmt", "asampfreq", "audio", "clear", "conflict", "conn_no_nna", "cost", "currency", "duration", "extend", "file", "fps", "g_notify", "g_sound", "gcm", "gone", "google_play", "hash", "height", "invalid", "jid-malformed", "latitude", "lc", "lg", "live", "location", "log", "longitude", "max_groups", "max_participants", "max_subject", "mimetype", "mode", "napi_version", "normalize", "orighash", "origin", "passive", "password", "played", "policy-violation", "pop_mean_time", "pop_plus_minus", "price", "pricing", "redeem", "Replaced by new connection", "resume", "signature", "size", "sound", "source", "system-shutdown", "username", "vbitrate", "vcard", "vcodec", "video", "width", "xml-not-well-formed", "checkmarks", "image_max_edge", "image_max_kbytes", "image_quality", "ka", "ka_grow", "ka_shrink", "newmedia", "library", "caption", "forward", "c0", "c1", "c2", "c3", "clock_skew", "cts", "k0", "k1", "login_rtt", "m_id", "nna_msg_rtt", "nna_no_off_count", "nna_offline_ratio", "nna_push_rtt", "no_nna_con_count", "off_msg_rtt", "on_msg_rtt", "stat_name", "sts", "suspect_conn", "lists", "self", "qr", "web", "w:b", "recipient", "w:stats", "forbidden", "aurora.m4r", "bamboo.m4r", "chord.m4r", "circles.m4r", "complete.m4r", "hello.m4r", "input.m4r", "keys.m4r", "note.m4r", "popcorn.m4r", "pulse.m4r", "synth.m4r", "filehash", "max_list_recipients", "en-AU", "en-GB", "es-MX", "pt-PT", "zh-Hans", "zh-Hant", "relayelection", "relaylatency", "interruption", "Apex.m4r", "Beacon.m4r", "Bulletin.m4r", "By The Seaside.m4r", "Chimes.m4r", "Circuit.m4r", "Constellation.m4r", "Cosmic.m4r", "Crystals.m4r", "Hillside.m4r", "Illuminate.m4r", "Night Owl.m4r", "Opening.m4r", "Playtime.m4r", "Presto.m4r", "Radar.m4r", "Radiate.m4r", "Ripples.m4r", "Sencha.m4r", "Signal.m4r", "Silk.m4r", "Slow Rise.m4r", "Stargaze.m4r", "Summit.m4r", "Twinkle.m4r", "Uplift.m4r", "Waves.m4r", "voip", "eligible", "upgrade", "planned", "current", "future", "disable", "expire", "start", "stop", "accuracy", "speed", "bearing", "recording", "encrypt", "key", "identity", "w:gp2", "admin", "locked", "unlocked", "new", "battery", "archive", "adm", "plaintext_size", "compressed_size", "delivered", "msg", "pkmsg", "everyone", "v", "transport", "call-id" ] def getToken(self, index, secondary = False): targetDict = self.dictionary if secondary: targetDict = self.secondaryDictionary elif index > 236 and index < (236 + len(self.secondaryDictionary)): targetDict = self.secondaryDictionary index = index - 237 if index < 0 or index > len(targetDict) - 1: return None return targetDict[index] def getIndex(self, token): if token in self.dictionary: return (self.dictionary.index(token), False) elif token in self.secondaryDictionary: return (self.secondaryDictionary.index(token), True) return None yowsup-2.4.48/yowsup/layers/interface/000077500000000000000000000000001263346463600200015ustar00rootroot00000000000000yowsup-2.4.48/yowsup/layers/interface/__init__.py000066400000000000000000000001001263346463600221010ustar00rootroot00000000000000from .interface import YowInterfaceLayer, ProtocolEntityCallbackyowsup-2.4.48/yowsup/layers/interface/interface.py000066400000000000000000000074711263346463600223240ustar00rootroot00000000000000from yowsup.layers import YowLayer, YowLayerEvent from yowsup.layers.protocol_iq.protocolentities import IqProtocolEntity from yowsup.layers.network import YowNetworkLayer from yowsup.layers.auth import YowAuthenticationProtocolLayer from yowsup.layers.protocol_receipts.protocolentities import OutgoingReceiptProtocolEntity from yowsup.layers.protocol_acks.protocolentities import IncomingAckProtocolEntity import inspect class ProtocolEntityCallback(object): def __init__(self, entityType): self.entityType = entityType def __call__(self, fn): fn.callback = self.entityType return fn class YowInterfaceLayer(YowLayer): def __init__(self): super(YowInterfaceLayer, self).__init__() self.callbacks = {} self.iqRegistry = {} # self.receiptsRegistry = {} members = inspect.getmembers(self, predicate=inspect.ismethod) for m in members: if hasattr(m[1], "callback"): fname = m[0] fn = m[1] self.callbacks[fn.callback] = getattr(self, fname) def _sendIq(self, iqEntity, onSuccess = None, onError = None): assert iqEntity.getTag() == "iq", "Expected *IqProtocolEntity in _sendIq, got %s" % iqEntity.getTag() self.iqRegistry[iqEntity.getId()] = (iqEntity, onSuccess, onError) self.toLower(iqEntity) # def _sendReceipt(self, outgoingReceiptProtocolEntity, onAck = None): # assert outgoingReceiptProtocolEntity.__class__ == OutgoingReceiptProtocolEntity,\ # "Excepted OutgoingReceiptProtocolEntity in _sendReceipt, got %s" % outgoingReceiptProtocolEntity.__class__ # self.receiptsRegistry[outgoingReceiptProtocolEntity.getId()] = (outgoingReceiptProtocolEntity, onAck) # self.toLower(outgoingReceiptProtocolEntity) # def processReceiptsRegistry(self, incomingAckProtocolEntity): # ''' # entity: IncomingAckProtocolEntity # ''' # # if incomingAckProtocolEntity.__class__ != IncomingAckProtocolEntity: # return False # # receipt_id = incomingAckProtocolEntity.getId() # if receipt_id in self.receiptsRegistry: # originalReceiptEntity, ackClbk = self.receiptsRegistry[receipt_id] # del self.receiptsRegistry[receipt_id] # # if ackClbk: # ackClbk(incomingAckProtocolEntity, originalReceiptEntity) # # return True # # return False def processIqRegistry(self, entity): """ :type entity: IqProtocolEntity """ if entity.getTag() == "iq": iq_id = entity.getId() if iq_id in self.iqRegistry: originalIq, successClbk, errorClbk = self.iqRegistry[iq_id] del self.iqRegistry[iq_id] if entity.getType() == IqProtocolEntity.TYPE_RESULT and successClbk: successClbk(entity, originalIq) elif entity.getType() == IqProtocolEntity.TYPE_ERROR and errorClbk: errorClbk(entity, originalIq) return True return False def getOwnJid(self, full = True): return self.getLayerInterface(YowAuthenticationProtocolLayer).getUsername(full) def connect(self): self.getLayerInterface(YowNetworkLayer).connect() def disconnect(self): disconnectEvent = YowLayerEvent(YowNetworkLayer.EVENT_STATE_DISCONNECT) self.broadcastEvent(disconnectEvent) def send(self, data): self.toLower(data) def receive(self, entity): if not self.processIqRegistry(entity): entityType = entity.getTag() if entityType in self.callbacks: self.callbacks[entityType](entity) else: self.toUpper(entity) def __str__(self): return "Interface Layer" yowsup-2.4.48/yowsup/layers/logger/000077500000000000000000000000001263346463600173205ustar00rootroot00000000000000yowsup-2.4.48/yowsup/layers/logger/__init__.py000066400000000000000000000000421263346463600214250ustar00rootroot00000000000000from .layer import YowLoggerLayer yowsup-2.4.48/yowsup/layers/logger/layer.py000066400000000000000000000007531263346463600210130ustar00rootroot00000000000000from yowsup.layers import YowLayer import logging logger = logging.getLogger(__name__) class YowLoggerLayer(YowLayer): def send(self, data): ldata = list(data) if type(data) is bytearray else data logger.debug("tx:\n%s" % ldata) self.toLower(data) def receive(self, data): ldata = list(data) if type(data) is bytearray else data logger.debug("rx:\n%s" % ldata) self.toUpper(data) def __str__(self): return "Logger Layer"yowsup-2.4.48/yowsup/layers/network/000077500000000000000000000000001263346463600175325ustar00rootroot00000000000000yowsup-2.4.48/yowsup/layers/network/__init__.py000066400000000000000000000000431263346463600216400ustar00rootroot00000000000000from .layer import YowNetworkLayer yowsup-2.4.48/yowsup/layers/network/layer.py000066400000000000000000000070641263346463600212270ustar00rootroot00000000000000from yowsup.layers import YowLayer, YowLayerEvent from yowsup.common.http.httpproxy import HttpProxy from yowsup.layers.network.layer_interface import YowNetworkLayerInterface import asyncore, socket, logging logger = logging.getLogger(__name__) class YowNetworkLayer(YowLayer, asyncore.dispatcher_with_send): ''' send: bytearray -> None receive: bytearray -> bytearray ''' EVENT_STATE_CONNECT = "org.openwhatsapp.yowsup.event.network.connect" EVENT_STATE_DISCONNECT = "org.openwhatsapp.yowsup.event.network.disconnect" EVENT_STATE_CONNECTED = "org.openwhatsapp.yowsup.event.network.connected" EVENT_STATE_DISCONNECTED = "org.openwhatsapp.yowsup.event.network.disconnected" PROP_ENDPOINT = "org.openwhatsapp.yowsup.prop.endpoint" PROP_NET_READSIZE = "org.openwhatsapp.yowsup.prop.net.readSize" def __init__(self): YowLayer.__init__(self) self.interface = YowNetworkLayerInterface(self) asyncore.dispatcher.__init__(self) httpProxy = HttpProxy.getFromEnviron() proxyHandler = None if httpProxy != None: logger.debug("HttpProxy initialize: %s" % httpProxy) def onConnect(): logger.debug("HttpProxy connected") self.proxyHandler = None self.handle_connect() proxyHandler = httpProxy.handler() proxyHandler.onConnect = onConnect self.proxyHandler = proxyHandler def onEvent(self, ev): if ev.getName() == YowNetworkLayer.EVENT_STATE_CONNECT: self.createConnection() return True elif ev.getName() == YowNetworkLayer.EVENT_STATE_DISCONNECT: self.destroyConnection(ev.getArg("reason")) return True def createConnection(self): self.create_socket(socket.AF_INET, socket.SOCK_STREAM) self.out_buffer = bytearray() endpoint = self.getProp(self.__class__.PROP_ENDPOINT) logger.debug("Connecting to %s:%s" % endpoint) if self.proxyHandler != None: logger.debug("HttpProxy connect: %s:%d" % endpoint) self.proxyHandler.connect(self, endpoint) else: self.connect(endpoint) def destroyConnection(self, reason = None): self.handle_close(reason or "Requested") def getStatus(self): return self.connected def handle_connect(self): self.connected = True if self.proxyHandler != None: logger.debug("HttpProxy handle connect") self.proxyHandler.send(self) else: self.emitEvent(YowLayerEvent(YowNetworkLayer.EVENT_STATE_CONNECTED)) def handle_close(self, reason = "Connection Closed"): self.connected = False logger.debug("Disconnected, reason: %s" % reason) self.emitEvent(YowLayerEvent(self.__class__.EVENT_STATE_DISCONNECTED, reason = reason, detached=True)) self.close() def handle_error(self): raise def handle_read(self): readSize = self.getProp(self.__class__.PROP_NET_READSIZE, 1024) if self.proxyHandler != None: data = self.proxyHandler.recv(self, readSize) logger.debug("HttpProxy handle read: %s" % data) else: data = self.recv(readSize) self.receive(data) def send(self, data): if self.connected: self.out_buffer = self.out_buffer + data self.initiate_send() def receive(self, data): self.toUpper(data) def __str__(self): return "Network Layer" yowsup-2.4.48/yowsup/layers/network/layer_interface.py000066400000000000000000000004401263346463600232360ustar00rootroot00000000000000from yowsup.layers import YowLayerInterface class YowNetworkLayerInterface(YowLayerInterface): def connect(self): self._layer.createConnection() def disconnect(self): self._layer.destroyConnection() def getStatus(self): return self._layer.getStatus()yowsup-2.4.48/yowsup/layers/protocol_acks/000077500000000000000000000000001263346463600207035ustar00rootroot00000000000000yowsup-2.4.48/yowsup/layers/protocol_acks/__init__.py000066400000000000000000000000471263346463600230150ustar00rootroot00000000000000from .layer import YowAckProtocolLayer yowsup-2.4.48/yowsup/layers/protocol_acks/layer.py000066400000000000000000000010211263346463600223630ustar00rootroot00000000000000from yowsup.layers import YowProtocolLayer from .protocolentities import * class YowAckProtocolLayer(YowProtocolLayer): def __init__(self): handleMap = { "ack": (self.recvAckNode, self.sendAckEntity) } super(YowAckProtocolLayer, self).__init__(handleMap) def __str__(self): return "Ack Layer" def sendAckEntity(self, entity): self.entityToLower(entity) def recvAckNode(self, node): self.toUpper(IncomingAckProtocolEntity.fromProtocolTreeNode(node)) yowsup-2.4.48/yowsup/layers/protocol_acks/protocolentities/000077500000000000000000000000001263346463600243115ustar00rootroot00000000000000yowsup-2.4.48/yowsup/layers/protocol_acks/protocolentities/__init__.py000066400000000000000000000002121263346463600264150ustar00rootroot00000000000000from .ack import AckProtocolEntity from .ack_incoming import IncomingAckProtocolEntity from .ack_outgoing import OutgoingAckProtocolEntityyowsup-2.4.48/yowsup/layers/protocol_acks/protocolentities/ack.py000066400000000000000000000017431263346463600254260ustar00rootroot00000000000000from yowsup.structs import ProtocolEntity, ProtocolTreeNode class AckProtocolEntity(ProtocolEntity): ''' ''' def __init__(self, _id, _class): super(AckProtocolEntity, self).__init__("ack") self._id = _id self._class = _class def getId(self): return self._id def getClass(self): return self._class def toProtocolTreeNode(self): attribs = { "id" : self._id, "class" : self._class, } return self._createProtocolTreeNode(attribs, None, data = None) def __str__(self): out = "ACK:\n" out += "ID: %s\n" % self._id out += "Class: %s\n" % self._class return out @staticmethod def fromProtocolTreeNode(node): return AckProtocolEntity( node.getAttributeValue("id"), node.getAttributeValue("class") ) yowsup-2.4.48/yowsup/layers/protocol_acks/protocolentities/ack_incoming.py000066400000000000000000000024301263346463600273030ustar00rootroot00000000000000from yowsup.structs import ProtocolEntity, ProtocolTreeNode from .ack import AckProtocolEntity class IncomingAckProtocolEntity(AckProtocolEntity): ''' ''' def __init__(self, _id, _class, _from, timestamp): super(IncomingAckProtocolEntity, self).__init__(_id, _class) self.setIncomingData(_from, timestamp) def setIncomingData(self, _from, timestamp): self._from = _from self.timestamp = timestamp def toProtocolTreeNode(self): node = super(IncomingAckProtocolEntity, self).toProtocolTreeNode() node.setAttribute("from", self._from) node.setAttribute("t", self.timestamp) return node def __str__(self): out = super(IncomingAckProtocolEntity, self).__str__() out += "From: %s\n" % self._from out += "timestamp: %s\n" % self.timestamp return out @staticmethod def fromProtocolTreeNode(node): entity = AckProtocolEntity.fromProtocolTreeNode(node) entity.__class__ = IncomingAckProtocolEntity entity.setIncomingData( node.getAttributeValue("from"), node.getAttributeValue("t") ) return entity yowsup-2.4.48/yowsup/layers/protocol_acks/protocolentities/ack_outgoing.py000066400000000000000000000033021263346463600273320ustar00rootroot00000000000000from yowsup.structs import ProtocolEntity, ProtocolTreeNode from .ack import AckProtocolEntity class OutgoingAckProtocolEntity(AckProtocolEntity): ''' ''' def __init__(self, _id, _class, _type, _to, _participant = None): super(OutgoingAckProtocolEntity, self).__init__(_id, _class) self.setOutgoingData(_type, _to, _participant) def setOutgoingData(self, _type, _to, _participant): self._type = _type self._to = _to self._participant = _participant def toProtocolTreeNode(self): node = super(OutgoingAckProtocolEntity, self).toProtocolTreeNode() if self._type: node.setAttribute("type", self._type) node.setAttribute("to", self._to) if self._participant: node.setAttribute("participant", self._participant) return node def __str__(self): out = super(OutgoingAckProtocolEntity, self).__str__() out += "Type: %s\n" % self._type out += "To: %s\n" % self._to if self._participant: out += "Participant: %s\n" % self._participant return out @staticmethod def fromProtocolTreeNode(node): entity = AckProtocolEntity.fromProtocolTreeNode(node) entity.__class__ = OutgoingAckProtocolEntity entity.setOutgoingData( node.getAttributeValue("type"), node.getAttributeValue("to"), node.getAttributeValue("participant") ) return entity yowsup-2.4.48/yowsup/layers/protocol_acks/protocolentities/test_ack_incoming.py000066400000000000000000000007461263346463600303520ustar00rootroot00000000000000from yowsup.layers.protocol_acks.protocolentities.ack_incoming import IncomingAckProtocolEntity from yowsup.structs.protocolentity import ProtocolEntityTest import unittest import time entity = IncomingAckProtocolEntity("12345", "message", "sender@s.whatsapp.com", int(time.time())) class IncomingAckProtocolEntityTest(ProtocolEntityTest, unittest.TestCase): def setUp(self): self.ProtocolEntity = IncomingAckProtocolEntity self.node = entity.toProtocolTreeNode() yowsup-2.4.48/yowsup/layers/protocol_acks/protocolentities/test_ack_outgoing.py000066400000000000000000000007051263346463600303750ustar00rootroot00000000000000from yowsup.layers.protocol_acks.protocolentities.ack_outgoing import OutgoingAckProtocolEntity from yowsup.structs.protocolentity import ProtocolEntityTest import unittest entity = OutgoingAckProtocolEntity("12345", "receipt", "delivery", "to_jid") class OutgoingAckProtocolEntityTest(ProtocolEntityTest, unittest.TestCase): def setUp(self): self.ProtocolEntity = OutgoingAckProtocolEntity self.node = entity.toProtocolTreeNode() yowsup-2.4.48/yowsup/layers/protocol_acks/test_layer.py000066400000000000000000000011241263346463600234260ustar00rootroot00000000000000from yowsup.layers import YowProtocolLayerTest from yowsup.layers.protocol_acks import YowAckProtocolLayer from yowsup.layers.protocol_acks.protocolentities.test_ack_incoming import entity as incomingAckEntity from yowsup.layers.protocol_acks.protocolentities.test_ack_outgoing import entity as outgoingAckEntity class YowAckProtocolLayerTest(YowProtocolLayerTest, YowAckProtocolLayer): def setUp(self): YowAckProtocolLayer.__init__(self) def test_receive(self): self.assertReceived(incomingAckEntity) def test_send(self): self.assertSent(outgoingAckEntity) yowsup-2.4.48/yowsup/layers/protocol_calls/000077500000000000000000000000001263346463600210605ustar00rootroot00000000000000yowsup-2.4.48/yowsup/layers/protocol_calls/__init__.py000066400000000000000000000000511263346463600231650ustar00rootroot00000000000000from .layer import YowCallsProtocolLayer yowsup-2.4.48/yowsup/layers/protocol_calls/layer.py000066400000000000000000000021371263346463600225510ustar00rootroot00000000000000from yowsup.layers import YowProtocolLayer from .protocolentities import * from yowsup.layers.protocol_acks.protocolentities import OutgoingAckProtocolEntity from yowsup.layers.protocol_receipts.protocolentities import OutgoingReceiptProtocolEntity class YowCallsProtocolLayer(YowProtocolLayer): def __init__(self): handleMap = { "call": (self.recvCall, self.sendCall) } super(YowCallsProtocolLayer, self).__init__(handleMap) def __str__(self): return "call Layer" def sendCall(self, entity): if entity.getTag() == "call": self.toLower(entity.toProtocolTreeNode()) def recvCall(self, node): entity = CallProtocolEntity.fromProtocolTreeNode(node) if entity.getType() == "offer": receipt = OutgoingReceiptProtocolEntity(node["id"], node["from"], callId = entity.getCallId()) self.toLower(receipt.toProtocolTreeNode()) else: ack = OutgoingAckProtocolEntity(node["id"], "call", None, node["from"]) self.toLower(ack.toProtocolTreeNode()) self.toUpper(entity) yowsup-2.4.48/yowsup/layers/protocol_calls/protocolentities/000077500000000000000000000000001263346463600244665ustar00rootroot00000000000000yowsup-2.4.48/yowsup/layers/protocol_calls/protocolentities/__init__.py000066400000000000000000000000661263346463600266010ustar00rootroot00000000000000from .call import CallProtocolEntity yowsup-2.4.48/yowsup/layers/protocol_calls/protocolentities/call.py000066400000000000000000000073651263346463600257660ustar00rootroot00000000000000from yowsup.structs import ProtocolEntity, ProtocolTreeNode class CallProtocolEntity(ProtocolEntity): ''' ''' def __init__(self, _id, _type, timestamp, notify = None, offline = None, retry = None, e = None, callId = None, _from = None, _to = None): super(CallProtocolEntity, self).__init__("call") self._id = _id or self._generateId() self._type = _type self._from = _from self._to = _to self.timestamp = int(timestamp) self.notify = notify self.offline = offline == "1" self.retry = retry self.e = e self.callId = callId def __str__(self): out = "Call\n" if self.getFrom() is not None: out += "From: %s\n" % self.getFrom() if self.getTo() is not None: out += "To: %s\n" % self.getTo() if self.getType() is not None: out += "Type: %s\n" % self.getType() if self.getCallId() is not None: out += "Call ID: %s\n" % self.getCallId() return out def getFrom(self, full = True): return self._from if full else self._from.split('@')[0] def getTo(self): return self._to def getId(self): return self._id def getType(self): return self._type def getCallId(self): return self.callId def getTimestamp(self): return self.timestamp def toProtocolTreeNode(self): children = [] attribs = { "t" : str(self.timestamp), "offline" : "1" if self.offline else "0", "id" : self._id, } if self._from is not None: attribs["from"] = self._from if self._to is not None: attribs["to"] = self._to if self.retry is not None: attribs["retry"] = self.retry if self.e is not None: attribs["e"] = self.e if self.notify is not None: attribs["notify"] = self.notify if self._type in ["offer", "transport", "relaylatency", "reject", "terminate"]: child = ProtocolTreeNode(self._type, {"call-id": self.callId}) children.append(child) return self._createProtocolTreeNode(attribs, children = children, data = None) @staticmethod def fromProtocolTreeNode(node): (_type, callId) = [None] * 2 offer = node.getChild("offer") transport = node.getChild("transport") relaylatency = node.getChild("relaylatency") reject = node.getChild("reject") terminate = node.getChild("terminate") if offer: _type = "offer" callId = offer.getAttributeValue("call-id") elif transport: _type = "transport" callId = transport.getAttributeValue("call-id") elif relaylatency: _type = "relaylatency" callId = relaylatency.getAttributeValue("call-id") elif reject: _type = "reject" callId = reject.getAttributeValue("call-id") elif terminate: _type = "terminate" callId = terminate.getAttributeValue("call-id") return CallProtocolEntity( node.getAttributeValue("id"), _type, node.getAttributeValue("t"), node.getAttributeValue("notify"), node.getAttributeValue("offline"), node.getAttributeValue("retry"), node.getAttributeValue("e"), callId, node.getAttributeValue("from"), node.getAttributeValue("to") ) yowsup-2.4.48/yowsup/layers/protocol_calls/protocolentities/test_call.py000066400000000000000000000012261263346463600270130ustar00rootroot00000000000000from yowsup.layers.protocol_calls.protocolentities.call import CallProtocolEntity from yowsup.structs import ProtocolTreeNode from yowsup.structs.protocolentity import ProtocolEntityTest import unittest class CallProtocolEntityTest(ProtocolEntityTest, unittest.TestCase): def setUp(self): self.ProtocolEntity = CallProtocolEntity children = [ProtocolTreeNode("offer", {"call-id": "call_id"})] attribs = { "t": "12345", "from": "from_jid", "offline": "0", "id": "message_id", "notify": "notify_name" } self.node = ProtocolTreeNode("call", attribs, children) yowsup-2.4.48/yowsup/layers/protocol_chatstate/000077500000000000000000000000001263346463600217425ustar00rootroot00000000000000yowsup-2.4.48/yowsup/layers/protocol_chatstate/__init__.py000066400000000000000000000000551263346463600240530ustar00rootroot00000000000000from .layer import YowChatstateProtocolLayer yowsup-2.4.48/yowsup/layers/protocol_chatstate/layer.py000066400000000000000000000011401263346463600234240ustar00rootroot00000000000000from yowsup.layers import YowLayer, YowLayerEvent, YowProtocolLayer from .protocolentities import * class YowChatstateProtocolLayer(YowProtocolLayer): def __init__(self): handleMap = { "chatstate": (self.recvChatstateNode, self.sendChatstateEntity) } super(YowChatstateProtocolLayer, self).__init__(handleMap) def __str__(self): return "Chatstate Layer" def sendChatstateEntity(self, entity): self.entityToLower(entity) def recvChatstateNode(self, node): self.toUpper(IncomingChatstateProtocolEntity.fromProtocolTreeNode(node)) yowsup-2.4.48/yowsup/layers/protocol_chatstate/protocolentities/000077500000000000000000000000001263346463600253505ustar00rootroot00000000000000yowsup-2.4.48/yowsup/layers/protocol_chatstate/protocolentities/__init__.py000066400000000000000000000002571263346463600274650ustar00rootroot00000000000000from .chatstate import ChatstateProtocolEntity from .chatstate_incoming import IncomingChatstateProtocolEntity from .chatstate_outgoing import OutgoingChatstateProtocolEntity yowsup-2.4.48/yowsup/layers/protocol_chatstate/protocolentities/chatstate.py000066400000000000000000000023221263346463600277010ustar00rootroot00000000000000from yowsup.structs import ProtocolEntity, ProtocolTreeNode class ChatstateProtocolEntity(ProtocolEntity): ''' INCOMING <{{composing|paused}}> OUTGOING <{{composing|paused}}> ''' STATE_TYPING = "composing" STATE_PAUSED = "paused" STATES = (STATE_TYPING, STATE_PAUSED) def __init__(self, _state): super(ChatstateProtocolEntity, self).__init__("chatstate") assert _state in self.__class__.STATES, "Expected chat state to be in %s, got %s" % (self.__class__.STATES, _state) self._state = _state def getState(self): return self._state def toProtocolTreeNode(self): node = self._createProtocolTreeNode({}, None, data = None) node.addChild(ProtocolTreeNode(self._state)) return node def __str__(self): out = "CHATSTATE:\n" out += "State: %s\n" % self._state return out @staticmethod def fromProtocolTreeNode(node): return ChatstateProtocolEntity( node.getAllChildren()[0].tag, ) yowsup-2.4.48/yowsup/layers/protocol_chatstate/protocolentities/chatstate_incoming.py000066400000000000000000000023161263346463600315670ustar00rootroot00000000000000from .chatstate import ChatstateProtocolEntity class IncomingChatstateProtocolEntity(ChatstateProtocolEntity): ''' INCOMING <{{composing|paused}}> OUTGOING <{{composing|paused}}> ''' def __init__(self, _state, _from): super(IncomingChatstateProtocolEntity, self).__init__(_state) self.setIncomingData(_from) def setIncomingData(self, _from): self._from = _from def toProtocolTreeNode(self): node = super(IncomingChatstateProtocolEntity, self).toProtocolTreeNode() node.setAttribute("from", self._from) return node def __str__(self): out = super(IncomingChatstateProtocolEntity, self).__str__() out += "From: %s\n" % self._from return out @staticmethod def fromProtocolTreeNode(node): entity = ChatstateProtocolEntity.fromProtocolTreeNode(node) entity.__class__ = IncomingChatstateProtocolEntity entity.setIncomingData( node.getAttributeValue("from"), ) return entity yowsup-2.4.48/yowsup/layers/protocol_chatstate/protocolentities/chatstate_outgoing.py000066400000000000000000000022721263346463600316200ustar00rootroot00000000000000from .chatstate import ChatstateProtocolEntity class OutgoingChatstateProtocolEntity(ChatstateProtocolEntity): ''' INCOMING <{{composing|paused}}> OUTGOING <{{composing|paused}}> ''' def __init__(self, _state, _to): super(OutgoingChatstateProtocolEntity, self).__init__(_state) self.setOutgoingData(_to) def setOutgoingData(self, _to): self._to = _to def toProtocolTreeNode(self): node = super(OutgoingChatstateProtocolEntity, self).toProtocolTreeNode() node.setAttribute("to", self._to) return node def __str__(self): out = super(OutgoingChatstateProtocolEntity, self).__str__() out += "To: %s\n" % self._to return out @staticmethod def fromProtocolTreeNode(node): entity = ChatstateProtocolEntity.fromProtocolTreeNode(node) entity.__class__ = OutgoingChatstateProtocolEntity entity.setOutgoingData( node.getAttributeValue("to"), ) return entity yowsup-2.4.48/yowsup/layers/protocol_chatstate/protocolentities/test_chatstate_incoming.py000066400000000000000000000010021263346463600326150ustar00rootroot00000000000000from yowsup.layers.protocol_chatstate.protocolentities.chatstate_incoming import IncomingChatstateProtocolEntity from yowsup.structs.protocolentity import ProtocolEntityTest import unittest entity = IncomingChatstateProtocolEntity(IncomingChatstateProtocolEntity.STATE_TYPING, "jid@s.whatsapp.net") class IncomingChatstateProtocolEntityTest(ProtocolEntityTest, unittest.TestCase): def setUp(self): self.ProtocolEntity = IncomingChatstateProtocolEntity self.node = entity.toProtocolTreeNode() yowsup-2.4.48/yowsup/layers/protocol_chatstate/protocolentities/test_chatstate_outgoing.py000066400000000000000000000010021263346463600326450ustar00rootroot00000000000000from yowsup.layers.protocol_chatstate.protocolentities.chatstate_outgoing import OutgoingChatstateProtocolEntity from yowsup.structs.protocolentity import ProtocolEntityTest import unittest entity = OutgoingChatstateProtocolEntity(OutgoingChatstateProtocolEntity.STATE_PAUSED, "jid@s.whatsapp.net") class OutgoingChatstateProtocolEntityTest(ProtocolEntityTest, unittest.TestCase): def setUp(self): self.ProtocolEntity = OutgoingChatstateProtocolEntity self.node = entity.toProtocolTreeNode() yowsup-2.4.48/yowsup/layers/protocol_chatstate/test_layer.py000066400000000000000000000013661263346463600244750ustar00rootroot00000000000000from yowsup.layers import YowProtocolLayerTest from yowsup.layers.protocol_chatstate import YowChatstateProtocolLayer from yowsup.layers.protocol_chatstate.protocolentities import IncomingChatstateProtocolEntity, OutgoingChatstateProtocolEntity class YowChatStateProtocolLayerTest(YowProtocolLayerTest, YowChatstateProtocolLayer): def setUp(self): YowChatstateProtocolLayer.__init__(self) def test_send(self): entity = OutgoingChatstateProtocolEntity(OutgoingChatstateProtocolEntity.STATE_PAUSED, "jid@s.whatsapp.net") self.assertSent(entity) def test_receive(self): entity = IncomingChatstateProtocolEntity(IncomingChatstateProtocolEntity.STATE_TYPING, "jid@s.whatsapp.net") self.assertReceived(entity)yowsup-2.4.48/yowsup/layers/protocol_contacts/000077500000000000000000000000001263346463600216005ustar00rootroot00000000000000yowsup-2.4.48/yowsup/layers/protocol_contacts/__init__.py000066400000000000000000000000551263346463600237110ustar00rootroot00000000000000from .layer import YowContactsIqProtocolLayeryowsup-2.4.48/yowsup/layers/protocol_contacts/layer.py000066400000000000000000000033201263346463600232640ustar00rootroot00000000000000from yowsup.layers import YowLayer, YowLayerEvent, YowProtocolLayer from yowsup.common import YowConstants from .protocolentities import * class YowContactsIqProtocolLayer(YowProtocolLayer): def __init__(self): handleMap = { "iq": (self.recvIq, self.sendIq), "notification": (self.recvNotification, None) } super(YowContactsIqProtocolLayer, self).__init__(handleMap) def __str__(self): return "Iq Layer" def recvNotification(self, node): if node["type"] == "contacts": if node.getChild("remove"): self.toUpper(RemoveContactNotificationProtocolEntity.fromProtocolTreeNode(node)) elif node.getChild("add"): self.toUpper(AddContactNotificationProtocolEntity.fromProtocolTreeNode(node)) elif node.getChild("update"): self.toUpper(UpdateContactNotificationProtocolEntity.fromProtocolTreeNode(node)) elif node.getChild("sync"): self.toUpper(ContactsSyncNotificationProtocolEntity.fromProtocolTreeNode(node)) else: self.raiseErrorForNode(node) def recvIq(self, node): if node["type"] == "result" and node.getChild("sync"): self.toUpper(ResultSyncIqProtocolEntity.fromProtocolTreeNode(node)) elif node["type"] == "result" and node.getChild("status"): self.toUpper(ResultStatusesIqProtocolEntity.fromProtocolTreeNode(node)) def sendIq(self, entity): if entity.getXmlns() == "urn:xmpp:whatsapp:sync": self.toLower(entity.toProtocolTreeNode()) elif entity.getXmlns() == GetStatusesIqProtocolEntity.XMLNS: self.toLower(entity.toProtocolTreeNode()) yowsup-2.4.48/yowsup/layers/protocol_contacts/protocolentities/000077500000000000000000000000001263346463600252065ustar00rootroot00000000000000yowsup-2.4.48/yowsup/layers/protocol_contacts/protocolentities/__init__.py000066400000000000000000000011071263346463600273160ustar00rootroot00000000000000from .iq_sync import SyncIqProtocolEntity from .iq_sync_get import GetSyncIqProtocolEntity from .iq_sync_result import ResultSyncIqProtocolEntity from .notification_contact_add import AddContactNotificationProtocolEntity from .notification_contact_remove import RemoveContactNotificationProtocolEntity from .notification_contact_update import UpdateContactNotificationProtocolEntity from .notificiation_contacts_sync import ContactsSyncNotificationProtocolEntity from .iq_statuses_get import GetStatusesIqProtocolEntity from .iq_statuses_result import ResultStatusesIqProtocolEntity yowsup-2.4.48/yowsup/layers/protocol_contacts/protocolentities/iq_statuses_get.py000066400000000000000000000031041263346463600307610ustar00rootroot00000000000000from yowsup.layers.protocol_iq.protocolentities import IqProtocolEntity from yowsup.structs import ProtocolTreeNode class GetStatusesIqProtocolEntity(IqProtocolEntity): XMLNS = "status" def __init__(self, jids, _id = None): """ Request the statuses of users. Should be sent once after login. Args: - jids: A list of jids representing the users whose statuses you are trying to get. """ super(GetStatusesIqProtocolEntity, self).__init__(self.__class__.XMLNS, _id, _type = "get", to = "s.whatsapp.net") self.setGetStatusesProps(jids) def setGetStatusesProps(self, jids): assert type(jids) is list, "jids must be a list of jids" self.jids = jids def __str__(self): out = super(GetStatusesIqProtocolEntity, self).__str__() out += "Numbers: %s\n" % (",".join(self.numbers)) return out def toProtocolTreeNode(self): users = [ProtocolTreeNode("user", {'jid': jid}) for jid in self.jids] node = super(GetStatusesIqProtocolEntity, self).toProtocolTreeNode() statusNode = ProtocolTreeNode("status", None, users) node.addChild(statusNode) return node @staticmethod def fromProtocolTreeNode(node): entity = IqProtocolEntity.fromProtocolTreeNode(node) entity.__class__ = GetStatusesIqProtocolEntity statusNode = node.getChild("status") userNodes = statusNode.getAllChildren() jids = [user['jid'] for user in userNodes] entity.setGetStatusesProps(jids) return entity yowsup-2.4.48/yowsup/layers/protocol_contacts/protocolentities/iq_statuses_result.py000066400000000000000000000037741263346463600315350ustar00rootroot00000000000000from yowsup.structs import ProtocolTreeNode from .iq_sync import SyncIqProtocolEntity from yowsup.layers.protocol_iq.protocolentities import IqProtocolEntity class ResultStatusesIqProtocolEntity(IqProtocolEntity): ''' {status message} HEX:{status message in hex} {status message} HEX:{status message in hex} ''' XMLNS = 'status' def __init__(self, _id, _from, statuses): super(ResultStatusesIqProtocolEntity, self).__init__(self.__class__.XMLNS, _id, 'result', _from=_from) setResultStatusesProps(statusesp) def setResultStatusesProps(self, statuses): assert type(statuses) is dict, "statuses must be dict" self.statuses = statuses def __str__(self): out = super(ResultStatusesIqProtocolEntity, self).__str__() out += "Statuses: %s\n" % ','.join(jid + '(' + str(v) + ')' for jid, v in self.statuses.iteritems()) return out def toProtocolTreeNode(self): node = super(ResultStatusesIqProtocolEntity, self).toProtcolTreeNode() users = [ProtocolTreeNode('user', {'jid': jid, 't': t}, None, status) for jid, (status, t) in self.statuses.iteritems()] statusNode = ProtocolTreeNode('status', None, users) node.addChild(statusNode) return node @staticmethod def fromProtocolTreeNode(node): statusNode = node.getChild('status') users = statusNode.getAllChildren() statuses = dict() for user in users: statuses[user['jid']] = (user.getData(), user['t']) entity = IqProtocolEntity.fromProtocolTreeNode(node) entity.__class__ = ResultStatusesIqProtocolEntity entity.setResultStatusesProps(statuses) return entity yowsup-2.4.48/yowsup/layers/protocol_contacts/protocolentities/iq_sync.py000066400000000000000000000035571263346463600272370ustar00rootroot00000000000000from yowsup.structs import ProtocolTreeNode from yowsup.layers.protocol_iq.protocolentities import IqProtocolEntity import time class SyncIqProtocolEntity(IqProtocolEntity): ''' ''' def __init__(self, _type, _id = None, sid = None, index = 0, last = True): super(SyncIqProtocolEntity, self).__init__("urn:xmpp:whatsapp:sync", _id = _id, _type = _type) self.setSyncProps(sid, index, last) def setSyncProps(self, sid, index, last): self.sid = sid if sid else str((int(time.time()) + 11644477200) * 10000000) self.index = int(index) self.last = last def __str__(self): out = super(SyncIqProtocolEntity, self).__str__() out += "sid: %s\n" % self.sid out += "index: %s\n" % self.index out += "last: %s\n" % self.last return out def toProtocolTreeNode(self): syncNodeAttrs = { "sid": self.sid, "index": str(self.index), "last": "true" if self.last else "false" } syncNode = ProtocolTreeNode("sync", syncNodeAttrs) node = super(SyncIqProtocolEntity, self).toProtocolTreeNode() node.addChild(syncNode) return node @staticmethod def fromProtocolTreeNode(node): syncNode = node.getChild("sync") entity = IqProtocolEntity.fromProtocolTreeNode(node) entity.__class__ = SyncIqProtocolEntity entity.setSyncProps( syncNode.getAttributeValue("sid"), syncNode.getAttributeValue("index"), syncNode.getAttributeValue("last") ) return entity yowsup-2.4.48/yowsup/layers/protocol_contacts/protocolentities/iq_sync_get.py000066400000000000000000000052741263346463600300740ustar00rootroot00000000000000from yowsup.structs import ProtocolTreeNode from yowsup.layers.protocol_iq.protocolentities import IqProtocolEntity from .iq_sync import SyncIqProtocolEntity class GetSyncIqProtocolEntity(SyncIqProtocolEntity): MODE_FULL = "full" MODE_DELTA = "delta" CONTEXT_REGISTRATION = "registration" CONTEXT_INTERACTIVE = "interactive" CONTEXTS = (CONTEXT_REGISTRATION, CONTEXT_INTERACTIVE) MODES = (MODE_FULL, MODE_DELTA) ''' {{num1}} {{num2}} ''' def __init__(self, numbers, mode = MODE_FULL, context = CONTEXT_INTERACTIVE, sid = None, index = 0, last = True): super(GetSyncIqProtocolEntity, self).__init__("get", sid = sid, index = index, last = last) self.setGetSyncProps(numbers, mode, context) def setGetSyncProps(self, numbers, mode, context): assert type(numbers) is list, "numbers must be a list" assert mode in self.__class__.MODES, "mode must be in %s" % self.__class__.MODES assert context in self.__class__.CONTEXTS, "context must be in %s" % self.__class__.CONTEXTS self.numbers = numbers self.mode = mode self.context = context def __str__(self): out = super(GetSyncIqProtocolEntity, self).__str__() out += "Mode: %s\n" % self.mode out += "Context: %s\n" % self.context out += "numbers: %s\n" % (",".join(self.numbers)) return out def toProtocolTreeNode(self): users = [ProtocolTreeNode("user", {}, None, number) for number in self.numbers] node = super(GetSyncIqProtocolEntity, self).toProtocolTreeNode() syncNode = node.getChild("sync") syncNode.setAttribute("mode", self.mode) syncNode.setAttribute("context", self.context) syncNode.addChildren(users) return node @staticmethod def fromProtocolTreeNode(node): syncNode = node.getChild("sync") userNodes = syncNode.getAllChildren() numbers = [userNode.data for userNode in userNodes] entity = SyncIqProtocolEntity.fromProtocolTreeNode(node) entity.__class__ = GetSyncIqProtocolEntity entity.setGetSyncProps(numbers, syncNode.getAttributeValue("mode"), syncNode.getAttributeValue("context"), ) return entity yowsup-2.4.48/yowsup/layers/protocol_contacts/protocolentities/iq_sync_result.py000066400000000000000000000076321263346463600306330ustar00rootroot00000000000000from yowsup.structs import ProtocolTreeNode from .iq_sync import SyncIqProtocolEntity class ResultSyncIqProtocolEntity(SyncIqProtocolEntity): ''' {{number}} abcdefgh ''' def __init__(self,_id, sid, index, last, version, inNumbers, outNumbers, invalidNumbers, wait = None): super(ResultSyncIqProtocolEntity, self).__init__("result", _id, sid, index, last) self.setResultSyncProps(version, inNumbers, outNumbers, invalidNumbers, wait) def setResultSyncProps(self, version, inNumbers, outNumbers, invalidNumbers, wait = None): assert type(inNumbers) is dict, "in numbers must be a dict {number -> jid}" assert type(outNumbers) is dict, "out numbers must be a dict {number -> jid}" assert type(invalidNumbers) is list, "invalid numbers must be a list" self.inNumbers = inNumbers self.outNumbers = outNumbers self.invalidNumbers = invalidNumbers self.wait = int(wait) if wait is not None else None self.version = version def __str__(self): out = super(SyncIqProtocolEntity, self).__str__() if self.wait is not None: out += "Wait: %s\n" % self.wait out += "Version: %s\n" % self.version out += "In Numbers: %s\n" % (",".join(self.inNumbers)) out += "Out Numbers: %s\n" % (",".join(self.outNumbers)) out += "Invalid Numbers: %s\n" % (",".join(self.invalidNumbers)) return out def toProtocolTreeNode(self): outUsers = [ProtocolTreeNode("user", {"jid": jid}, None, number) for number, jid in self.outNumbers.items()] inUsers = [ProtocolTreeNode("user", {"jid": jid}, None, number) for number, jid in self.inNumbers.items()] invalidUsers = [ProtocolTreeNode("user", {}, None, number) for number in self.invalidNumbers] node = super(ResultSyncIqProtocolEntity, self).toProtocolTreeNode() syncNode = node.getChild("sync") syncNode.setAttribute("version", self.version) if self.wait is not None: syncNode.setAttribute("wait", str(self.wait)) if len(outUsers): syncNode.addChild(ProtocolTreeNode("out", children = outUsers)) if len(inUsers): syncNode.addChild(ProtocolTreeNode("in", children = inUsers)) if len(invalidUsers): syncNode.addChildren([ProtocolTreeNode("invalid", children = invalidUsers)]) return node @staticmethod def fromProtocolTreeNode(node): syncNode = node.getChild("sync") outNode = syncNode.getChild("out") inNode = syncNode.getChild("in") invalidNode = syncNode.getChild("invalid") outUsers = outNode.getAllChildren() if outNode else [] inUsers = inNode.getAllChildren() if inNode else [] invalidUsers = [inode.data for inode in invalidNode.getAllChildren()] if invalidNode else [] outUsersDict = {} for u in outUsers: outUsersDict[u.data] = u.getAttributeValue("jid") inUsersDict = {} for u in inUsers: inUsersDict[u.data] = u.getAttributeValue("jid") entity = SyncIqProtocolEntity.fromProtocolTreeNode(node) entity.__class__ = ResultSyncIqProtocolEntity entity.setResultSyncProps(syncNode.getAttributeValue("version"), inUsersDict, outUsersDict, invalidUsers, syncNode.getAttributeValue("wait") ) return entity yowsup-2.4.48/yowsup/layers/protocol_contacts/protocolentities/notification_contact.py000066400000000000000000000014541263346463600317650ustar00rootroot00000000000000from yowsup.structs import ProtocolEntity, ProtocolTreeNode from yowsup.layers.protocol_notifications.protocolentities import NotificationProtocolEntity class ContactNotificationProtocolEntity(NotificationProtocolEntity): ''' ''' def __init__(self, _id, _from, timestamp, notify, offline = False): super(ContactNotificationProtocolEntity, self).__init__("contacts", _id, _from, timestamp, notify, offline) @staticmethod def fromProtocolTreeNode(node): entity = NotificationProtocolEntity.fromProtocolTreeNode(node) entity.__class__ = ContactNotificationProtocolEntity return entityyowsup-2.4.48/yowsup/layers/protocol_contacts/protocolentities/notification_contact_add.py000066400000000000000000000023671263346463600326010ustar00rootroot00000000000000from yowsup.structs import ProtocolTreeNode from .notification_contact import ContactNotificationProtocolEntity class AddContactNotificationProtocolEntity(ContactNotificationProtocolEntity): ''' ''' def __init__(self, _id, _from, timestamp, notify, offline, contactJid): super(AddContactNotificationProtocolEntity, self).__init__(_id, _from, timestamp, notify, offline) self.setData(contactJid) def setData(self, jid): self.contactJid = jid def toProtocolTreeNode(self): node = super(AddContactNotificationProtocolEntity, self).toProtocolTreeNode() removeNode = ProtocolTreeNode("add", {"jid": self.contactJid}, None, None) node.addChild(removeNode) return node @staticmethod def fromProtocolTreeNode(node): entity = ContactNotificationProtocolEntity.fromProtocolTreeNode(node) entity.__class__ = AddContactNotificationProtocolEntity removeNode = node.getChild("add") entity.setData(removeNode.getAttributeValue("jid")) return entityyowsup-2.4.48/yowsup/layers/protocol_contacts/protocolentities/notification_contact_remove.py000066400000000000000000000024171263346463600333420ustar00rootroot00000000000000from yowsup.structs import ProtocolTreeNode from .notification_contact import ContactNotificationProtocolEntity class RemoveContactNotificationProtocolEntity(ContactNotificationProtocolEntity): ''' ''' def __init__(self, _id, _from, timestamp, notify, offline, contactJid): super(RemoveContactNotificationProtocolEntity, self).__init__(_id, _from, timestamp, notify, offline) self.setData(contactJid) def setData(self, jid): self.contactJid = jid def toProtocolTreeNode(self): node = super(RemoveContactNotificationProtocolEntity, self).toProtocolTreeNode() removeNode = ProtocolTreeNode("remove", {"jid": self.contactJid}, None, None) node.addChild(removeNode) return node @staticmethod def fromProtocolTreeNode(node): entity = ContactNotificationProtocolEntity.fromProtocolTreeNode(node) entity.__class__ = RemoveContactNotificationProtocolEntity removeNode = node.getChild("remove") entity.setData(removeNode.getAttributeValue("jid")) return entityyowsup-2.4.48/yowsup/layers/protocol_contacts/protocolentities/notification_contact_update.py000066400000000000000000000024171263346463600333270ustar00rootroot00000000000000from yowsup.structs import ProtocolTreeNode from .notification_contact import ContactNotificationProtocolEntity class UpdateContactNotificationProtocolEntity(ContactNotificationProtocolEntity): ''' ''' def __init__(self, _id, _from, timestamp, notify, offline, contactJid): super(UpdateContactNotificationProtocolEntity, self).__init__(_id, _from, timestamp, notify, offline) self.setData(contactJid) def setData(self, jid): self.contactJid = jid def toProtocolTreeNode(self): node = super(UpdateContactNotificationProtocolEntity, self).toProtocolTreeNode() removeNode = ProtocolTreeNode("update", {"jid": self.contactJid}, None, None) node.addChild(removeNode) return node @staticmethod def fromProtocolTreeNode(node): entity = ContactNotificationProtocolEntity.fromProtocolTreeNode(node) entity.__class__ = UpdateContactNotificationProtocolEntity removeNode = node.getChild("update") entity.setData(removeNode.getAttributeValue("jid")) return entityyowsup-2.4.48/yowsup/layers/protocol_contacts/protocolentities/notificiation_contacts_sync.py000066400000000000000000000023251263346463600333530ustar00rootroot00000000000000from yowsup.structs import ProtocolTreeNode from .notification_contact import ContactNotificationProtocolEntity class ContactsSyncNotificationProtocolEntity(ContactNotificationProtocolEntity): ''' ''' def __init__(self, _id, _from, timestamp, notify, offline, after): super(ContactsSyncNotificationProtocolEntity, self).__init__(_id, _from, timestamp, notify, offline) self.setData(after) def setData(self, after): self.after = int(after) def toProtocolTreeNode(self): node = super(ContactsSyncNotificationProtocolEntity, self).toProtocolTreeNode() syncNode = ProtocolTreeNode("sync", {"after": str(self.after)}, None, None) node.addChild(syncNode) return node @staticmethod def fromProtocolTreeNode(node): entity = ContactNotificationProtocolEntity.fromProtocolTreeNode(node) entity.__class__ = ContactsSyncNotificationProtocolEntity syncNode = node.getChild("sync") entity.setData(syncNode.getAttributeValue("after")) return entityyowsup-2.4.48/yowsup/layers/protocol_contacts/protocolentities/test_iq_sync_get.py000066400000000000000000000006611263346463600311260ustar00rootroot00000000000000from yowsup.layers.protocol_contacts.protocolentities.iq_sync_get import GetSyncIqProtocolEntity from yowsup.structs.protocolentity import ProtocolEntityTest import unittest entity = GetSyncIqProtocolEntity(["12345678", "8764543121"]) class GetSyncIqProtocolEntityTest(ProtocolEntityTest, unittest.TestCase): def setUp(self): self.ProtocolEntity = GetSyncIqProtocolEntity self.node = entity.toProtocolTreeNode()yowsup-2.4.48/yowsup/layers/protocol_contacts/protocolentities/test_iq_sync_result.py000066400000000000000000000013701263346463600316630ustar00rootroot00000000000000from yowsup.layers.protocol_contacts.protocolentities.iq_sync_result import ResultSyncIqProtocolEntity from yowsup.structs.protocolentity import ProtocolEntityTest import unittest entity = ResultSyncIqProtocolEntity("123", "1.30615237617e+17", 0, True, "123456", {"12345678": "12345678@s.whatsapp.net"}, {"12345678": "12345678@s.whatsapp.net"}, ["1234"]) class ResultSyncIqProtocolEntityTest(ProtocolEntityTest, unittest.TestCase): def setUp(self): self.ProtocolEntity = ResultSyncIqProtocolEntity self.node = entity.toProtocolTreeNode() def test_delta_result(self): del self.node.getChild("sync")["wait"] self.test_generation() yowsup-2.4.48/yowsup/layers/protocol_contacts/protocolentities/test_notification_contact_add.py000066400000000000000000000012401263346463600336250ustar00rootroot00000000000000from yowsup.layers.protocol_contacts.protocolentities import AddContactNotificationProtocolEntity from yowsup.structs.protocolentity import ProtocolEntityTest import time import unittest entity = AddContactNotificationProtocolEntity("1234", "jid@s.whatsapp.net", int(time.time()), "notify", False, "sender@s.whatsapp.net") class AddContactNotificationProtocolEntityTest(ProtocolEntityTest, unittest.TestCase): def setUp(self): super(AddContactNotificationProtocolEntityTest, self).setUp() self.ProtocolEntity = AddContactNotificationProtocolEntity self.node = entity.toProtocolTreeNode() yowsup-2.4.48/yowsup/layers/protocol_contacts/protocolentities/test_notification_contact_remove.py000066400000000000000000000011451263346463600343760ustar00rootroot00000000000000from yowsup.layers.protocol_contacts.protocolentities import RemoveContactNotificationProtocolEntity from yowsup.structs.protocolentity import ProtocolEntityTest import time import unittest entity = RemoveContactNotificationProtocolEntity("1234", "jid@s.whatsapp.net", int(time.time()), "notify", False, "contactjid@s.whatsapp.net") class RemoveContactNotificationProtocolEntityTest(ProtocolEntityTest, unittest.TestCase): def setUp(self): self.ProtocolEntity = RemoveContactNotificationProtocolEntity self.node = entity.toProtocolTreeNode() yowsup-2.4.48/yowsup/layers/protocol_contacts/protocolentities/test_notification_contact_update.py000066400000000000000000000011441263346463600343620ustar00rootroot00000000000000from yowsup.layers.protocol_contacts.protocolentities import UpdateContactNotificationProtocolEntity from yowsup.structs.protocolentity import ProtocolEntityTest import time import unittest entity = UpdateContactNotificationProtocolEntity("1234", "jid@s.whatsapp.net", int(time.time()), "notify", False,"contactjid@s.whatsapp.net") class UpdateContactNotificationProtocolEntityTest(ProtocolEntityTest, unittest.TestCase): def setUp(self): self.ProtocolEntity = UpdateContactNotificationProtocolEntity self.node = entity.toProtocolTreeNode() yowsup-2.4.48/yowsup/layers/protocol_contacts/test_layer.py000066400000000000000000000023001263346463600243200ustar00rootroot00000000000000from yowsup.layers import YowProtocolLayerTest from yowsup.layers.protocol_contacts import YowContactsIqProtocolLayer from yowsup.layers.protocol_contacts.protocolentities.test_notification_contact_add import entity as addEntity from yowsup.layers.protocol_contacts.protocolentities.test_notification_contact_update import entity as updateEntity from yowsup.layers.protocol_contacts.protocolentities.test_notification_contact_remove import entity as removeEntity from yowsup.layers.protocol_contacts.protocolentities.test_iq_sync_result import entity as syncResultEntity from yowsup.layers.protocol_contacts.protocolentities.test_iq_sync_get import entity as syncGetEntity class YowContactsIqProtocolLayerTest(YowProtocolLayerTest, YowContactsIqProtocolLayer): def setUp(self): YowContactsIqProtocolLayer.__init__(self) def test_sync(self): self.assertSent(syncGetEntity) def test_syncResult(self): self.assertReceived(syncResultEntity) def test_notificationAdd(self): self.assertReceived(addEntity) def test_notificationUpdate(self): self.assertReceived(updateEntity) def test_notificationRemove(self): self.assertReceived(removeEntity) yowsup-2.4.48/yowsup/layers/protocol_groups/000077500000000000000000000000001263346463600213015ustar00rootroot00000000000000yowsup-2.4.48/yowsup/layers/protocol_groups/__init__.py000066400000000000000000000000521263346463600234070ustar00rootroot00000000000000from .layer import YowGroupsProtocolLayer yowsup-2.4.48/yowsup/layers/protocol_groups/layer.py000066400000000000000000000134031263346463600227700ustar00rootroot00000000000000from yowsup.layers import YowLayer, YowLayerEvent, YowProtocolLayer from .protocolentities import * import logging logger = logging.getLogger(__name__) class YowGroupsProtocolLayer(YowProtocolLayer): HANDLE = ( CreateGroupsIqProtocolEntity, InfoGroupsIqProtocolEntity, LeaveGroupsIqProtocolEntity, ListGroupsIqProtocolEntity, SubjectGroupsIqProtocolEntity, ParticipantsGroupsIqProtocolEntity, AddParticipantsIqProtocolEntity, PromoteParticipantsIqProtocolEntity, DemoteParticipantsIqProtocolEntity, RemoveParticipantsIqProtocolEntity ) def __init__(self): handleMap = { "iq": (None, self.sendIq), "notification": (self.recvNotification, None) } super(YowGroupsProtocolLayer, self).__init__(handleMap) def __str__(self): return "Groups Iq Layer" def sendIq(self, entity): if entity.__class__ in self.__class__.HANDLE: if entity.__class__ == SubjectGroupsIqProtocolEntity: self._sendIq(entity, self.onSetSubjectSuccess, self.onSetSubjectFailed) elif entity.__class__ == CreateGroupsIqProtocolEntity: self._sendIq(entity, self.onCreateGroupSuccess, self.onCreateGroupFailed) elif entity.__class__ == ParticipantsGroupsIqProtocolEntity: self._sendIq(entity, self.onGetParticipantsResult) elif entity.__class__ == AddParticipantsIqProtocolEntity: self._sendIq(entity, self.onAddParticipantsSuccess, self.onAddParticipantsFailed) elif entity.__class__ == PromoteParticipantsIqProtocolEntity: self._sendIq(entity, self.onPromoteParticipantsSuccess, self.onPromoteParticipantsFailed) elif entity.__class__ == DemoteParticipantsIqProtocolEntity: self._sendIq(entity, self.onDemoteParticipantsSuccess, self.onDemoteParticipantsFailed) elif entity.__class__ == RemoveParticipantsIqProtocolEntity: self._sendIq(entity, self.onRemoveParticipantsSuccess, self.onRemoveParticipantsFailed) elif entity.__class__ == ListGroupsIqProtocolEntity: self._sendIq(entity, self.onListGroupsResult) elif entity.__class__ == LeaveGroupsIqProtocolEntity: self._sendIq(entity, self.onLeaveGroupSuccess, self.onLeaveGroupFailed) elif entity.__class__ == InfoGroupsIqProtocolEntity: self._sendIq(entity, self.onInfoGroupSuccess, self.onInfoGroupFailed) else: self.entityToLower(entity) def onCreateGroupSuccess(self, node, originalIqEntity): logger.info("Group create success") self.toUpper(SuccessCreateGroupsIqProtocolEntity.fromProtocolTreeNode(node)) def onCreateGroupFailed(self, node, originalIqEntity): logger.error("Group create failed") def onSetSubjectSuccess(self, node, originalIqEntity): logger.info("Group subject change success") def onSetSubjectFailed(self, node, originalIqEntity): logger.error("Group subject change failed") def onGetParticipantsResult(self, node, originalIqEntity): self.toUpper(ListParticipantsResultIqProtocolEntity.fromProtocolTreeNode(node)) def onAddParticipantsSuccess(self, node, originalIqEntity): logger.info("Group add participants success") self.toUpper(SuccessAddParticipantsIqProtocolEntity.fromProtocolTreeNode(node)) def onRemoveParticipantsFailed(self, node, originalIqEntity): logger.error("Group remove participants failed") def onRemoveParticipantsSuccess(self, node, originalIqEntity): logger.info("Group remove participants success") self.toUpper(SuccessRemoveParticipantsIqProtocolEntity.fromProtocolTreeNode(node)) def onPromoteParticipantsFailed(self, node, originalIqEntity): logger.error("Group promote participants failed") def onPromoteParticipantsSuccess(self, node, originalIqEntity): logger.info("Group promote participants success") def onDemoteParticipantsFailed(self, node, originalIqEntity): logger.error("Group demote participants failed") def onDemoteParticipantsSuccess(self, node, originalIqEntity): logger.info("Group demote participants success") def onAddParticipantsFailed(self, node, originalIqEntity): logger.error("Group add participants failed") self.toUpper(FailureAddParticipantsIqProtocolEntity.fromProtocolTreeNode(node)) def onListGroupsResult(self, node, originalIqEntity): self.toUpper(ListGroupsResultIqProtocolEntity.fromProtocolTreeNode(node)) def onLeaveGroupSuccess(self, node, originalIqEntity): logger.info("Group leave success") self.toUpper(SuccessLeaveGroupsIqProtocolEntity.fromProtocolTreeNode(node)) def onLeaveGroupFailed(self, node, originalIqEntity): logger.error("Group leave failed") def onInfoGroupSuccess(self, node, originalIqEntity): logger.info("Group info success") self.toUpper(InfoGroupsResultIqProtocolEntity.fromProtocolTreeNode(node)) def onInfoGroupFailed(self, node, originalIqEntity): logger.error("Group info failed") def recvNotification(self, node): if node["type"] == "w:gp2": if node.getChild("subject"): self.toUpper(SubjectGroupsNotificationProtocolEntity.fromProtocolTreeNode(node)) elif node.getChild("create"): self.toUpper(CreateGroupsNotificationProtocolEntity.fromProtocolTreeNode(node)) elif node.getChild("remove"): self.toUpper(RemoveGroupsNotificationProtocolEntity.fromProtocolTreeNode(node)) elif node.getChild("add"): self.toUpper(AddGroupsNotificationProtocolEntity.fromProtocolTreeNode(node)) yowsup-2.4.48/yowsup/layers/protocol_groups/protocolentities/000077500000000000000000000000001263346463600247075ustar00rootroot00000000000000yowsup-2.4.48/yowsup/layers/protocol_groups/protocolentities/__init__.py000066400000000000000000000032521263346463600270220ustar00rootroot00000000000000from .iq_groups_create import CreateGroupsIqProtocolEntity from .iq_groups_create_success import SuccessCreateGroupsIqProtocolEntity from .iq_groups_leave import LeaveGroupsIqProtocolEntity from .iq_groups_leave_success import SuccessLeaveGroupsIqProtocolEntity from .iq_groups_list import ListGroupsIqProtocolEntity from .iq_groups_info import InfoGroupsIqProtocolEntity from .iq_groups_subject import SubjectGroupsIqProtocolEntity from .iq_groups_participants import ParticipantsGroupsIqProtocolEntity from .iq_groups_participants_add import AddParticipantsIqProtocolEntity from .iq_groups_participants_promote import PromoteParticipantsIqProtocolEntity from .iq_groups_participants_demote import DemoteParticipantsIqProtocolEntity from .iq_groups_participants_add_success import SuccessAddParticipantsIqProtocolEntity from .iq_groups_participants_add_failure import FailureAddParticipantsIqProtocolEntity from .iq_groups_participants_remove import RemoveParticipantsIqProtocolEntity from .iq_groups_participants_remove_success import SuccessRemoveParticipantsIqProtocolEntity from .iq_result_groups_list import ListGroupsResultIqProtocolEntity from .iq_result_participants_list import ListParticipantsResultIqProtocolEntity from .iq_result_groups_info import InfoGroupsResultIqProtocolEntity from .notification_groups import GroupsNotificationProtocolEntity from .notification_groups_subject import SubjectGroupsNotificationProtocolEntity from .notification_groups_create import CreateGroupsNotificationProtocolEntity from .notification_groups_add import AddGroupsNotificationProtocolEntity from .notification_groups_remove import RemoveGroupsNotificationProtocolEntity yowsup-2.4.48/yowsup/layers/protocol_groups/protocolentities/iq_groups.py000066400000000000000000000007071263346463600272750ustar00rootroot00000000000000from yowsup.structs import ProtocolEntity, ProtocolTreeNode from yowsup.layers.protocol_iq.protocolentities import IqProtocolEntity class GroupsIqProtocolEntity(IqProtocolEntity): ''' ''' def __init__(self, to = None, _from = None, _id = None, _type = None): super(GroupsIqProtocolEntity, self).__init__("w:g2", _id, _type, to = to, _from = _from) yowsup-2.4.48/yowsup/layers/protocol_groups/protocolentities/iq_groups_create.py000066400000000000000000000033361263346463600306210ustar00rootroot00000000000000from yowsup.structs import ProtocolEntity, ProtocolTreeNode from .iq_groups import GroupsIqProtocolEntity class CreateGroupsIqProtocolEntity(GroupsIqProtocolEntity): ''' ''' def __init__(self, subject, _id = None, participants = None): super(CreateGroupsIqProtocolEntity, self).__init__(to = "g.us", _id = _id, _type = "set") self.setProps(subject) self.setParticipants(participants or []) def setProps(self, subject): self.subject = subject def setParticipants(self, participants): self.participantList = participants def toProtocolTreeNode(self): node = super(CreateGroupsIqProtocolEntity, self).toProtocolTreeNode() cnode = ProtocolTreeNode("create",{ "subject": self.subject}) participantNodes = [ ProtocolTreeNode("participant", { "jid": participant }) for participant in self.participantList ] cnode.addChildren(participantNodes) node.addChild(cnode) return node @staticmethod def fromProtocolTreeNode(node): entity = super(CreateGroupsIqProtocolEntity,CreateGroupsIqProtocolEntity).fromProtocolTreeNode(node) entity.__class__ = CreateGroupsIqProtocolEntity entity.setProps(node.getChild("create").getAttributeValue("subject")) participantList = [] for participantNode in node.getChild("create").getAllChildren(): participantList.append(participantNode["jid"]) entity.setParticipants(participantList) return entity yowsup-2.4.48/yowsup/layers/protocol_groups/protocolentities/iq_groups_create_success.py000066400000000000000000000020641263346463600323460ustar00rootroot00000000000000from yowsup.structs import ProtocolTreeNode from yowsup.layers.protocol_iq.protocolentities import ResultIqProtocolEntity class SuccessCreateGroupsIqProtocolEntity(ResultIqProtocolEntity): ''' ''' def __init__(self, _id, groupId): super(SuccessCreateGroupsIqProtocolEntity, self).__init__(_from = "g.us", _id = _id) self.setProps(groupId) def setProps(self, groupId): self.groupId = groupId def toProtocolTreeNode(self): node = super(SuccessCreateGroupsIqProtocolEntity, self).toProtocolTreeNode() node.addChild(ProtocolTreeNode("group",{"id": self.groupId})) return node @staticmethod def fromProtocolTreeNode(node): entity = super(SuccessCreateGroupsIqProtocolEntity, SuccessCreateGroupsIqProtocolEntity).fromProtocolTreeNode(node) entity.__class__ = SuccessCreateGroupsIqProtocolEntity entity.setProps(node.getChild("group").getAttributeValue("id")) return entity yowsup-2.4.48/yowsup/layers/protocol_groups/protocolentities/iq_groups_info.py000066400000000000000000000024211263346463600303030ustar00rootroot00000000000000from yowsup.structs import ProtocolEntity, ProtocolTreeNode from .iq_groups import GroupsIqProtocolEntity class InfoGroupsIqProtocolEntity(GroupsIqProtocolEntity): ''' ''' def __init__(self, group_jid, _id=None): super(InfoGroupsIqProtocolEntity, self).__init__(to = group_jid, _id = _id, _type = "get") self.setProps(group_jid) def setProps(self, group_jid): self.group_jid = group_jid def __str__(self): out = super(InfoGroupsIqProtocolEntity, self).__str__() out += "Group JID: %s\n" % self.group_jid return out def toProtocolTreeNode(self): node = super(InfoGroupsIqProtocolEntity, self).toProtocolTreeNode() node.addChild(ProtocolTreeNode("query", {"request": "interactive"})) return node @staticmethod def fromProtocolTreeNode(node): assert node.getChild("query") is not None, "Not a groups info iq node %s" % node entity = super(InfoGroupsIqProtocolEntity, InfoGroupsIqProtocolEntity).fromProtocolTreeNode(node) entity.__class__ = InfoGroupsIqProtocolEntity entity.setProps(node.getAttributeValue("to")) return entity yowsup-2.4.48/yowsup/layers/protocol_groups/protocolentities/iq_groups_leave.py000066400000000000000000000032141263346463600304450ustar00rootroot00000000000000from yowsup.structs import ProtocolEntity, ProtocolTreeNode from .iq_groups import GroupsIqProtocolEntity class LeaveGroupsIqProtocolEntity(GroupsIqProtocolEntity): ''' ''' def __init__(self, groupList): super(LeaveGroupsIqProtocolEntity, self).__init__(to = "g.us", _type = "set") self.setProps(groupList if type(groupList) is list else [groupList]) def setProps(self, groupList): assert type(groupList) is list and len(groupList), "Must specify a list of group jids to leave" self.groupList = groupList def toProtocolTreeNode(self): node = super(LeaveGroupsIqProtocolEntity, self).toProtocolTreeNode() groupNodes = [ ProtocolTreeNode("group", { "id": groupid }) for groupid in self.groupList ] node.addChild(ProtocolTreeNode("leave", {"action": "delete"}, groupNodes)) return node @staticmethod def fromProtocolTreeNode(node): assert node.getChild("leave") is not None, "Not a group leave iq node %s" % node assert node.getChild("leave").getAttributeValue("action") == "delete", "Not a group leave action %s" % node entity = super(LeaveGroupsIqProtocolEntity, LeaveGroupsIqProtocolEntity).fromProtocolTreeNode(node) entity.__class__ = LeaveGroupsIqProtocolEntity entity.setProps([group.getAttributeValue("id") for group in node.getChild("leave").getAllChildren()] ) return entity yowsup-2.4.48/yowsup/layers/protocol_groups/protocolentities/iq_groups_leave_success.py000066400000000000000000000026201263346463600321750ustar00rootroot00000000000000from yowsup.structs import ProtocolTreeNode from yowsup.layers.protocol_iq.protocolentities import ResultIqProtocolEntity class SuccessLeaveGroupsIqProtocolEntity(ResultIqProtocolEntity): ''' ''' def __init__(self, _id, groupId): super(SuccessLeaveGroupsIqProtocolEntity, self).\ __init__(_from="g.us", _id=_id) self.setProps(groupId) def setProps(self, groupId): self.groupId = groupId def __str__(self): out = super(SuccessLeaveGroupsIqProtocolEntity, self).__str__() out += "Group Id: %s\n" % self.groupId return out def toProtocolTreeNode(self): node = super(SuccessLeaveGroupsIqProtocolEntity, self).\ toProtocolTreeNode() leaveNode = ProtocolTreeNode( "leave", {}, [ProtocolTreeNode("group", {"id": self.groupId})] ) node.addChild(leaveNode) return node @staticmethod def fromProtocolTreeNode(node): entity = super(SuccessLeaveGroupsIqProtocolEntity, SuccessLeaveGroupsIqProtocolEntity).fromProtocolTreeNode(node) entity.__class__ = SuccessLeaveGroupsIqProtocolEntity entity.setProps( node.getChild("leave").getChild("group").getAttributeValue("id") ) return entity yowsup-2.4.48/yowsup/layers/protocol_groups/protocolentities/iq_groups_list.py000066400000000000000000000041041263346463600303230ustar00rootroot00000000000000from yowsup.structs import ProtocolEntity, ProtocolTreeNode from .iq_groups import GroupsIqProtocolEntity class ListGroupsIqProtocolEntity(GroupsIqProtocolEntity): ''' <"{{participating | owning}}"> result (processed in iq_result_groups_list.py): ''' GROUP_TYPE_PARTICIPATING = "participating" GROUP_TYPE_OWNING = "owning" GROUPS_TYPES = (GROUP_TYPE_PARTICIPATING, GROUP_TYPE_OWNING) def __init__(self, groupsType = GROUP_TYPE_PARTICIPATING, _id = None): super(ListGroupsIqProtocolEntity, self).__init__(_id=_id, to = "g.us", _type = "get") self.setProps(groupsType) def setProps(self, groupsType): assert groupsType in self.__class__.GROUPS_TYPES,\ "Groups type must be %s, not %s" % (" or ".join(self.__class__.GROUPS_TYPES), groupsType) self.groupsType = groupsType def toProtocolTreeNode(self): node = super(ListGroupsIqProtocolEntity, self).toProtocolTreeNode() node.addChild(ProtocolTreeNode(self.groupsType)) return node @staticmethod def fromProtocolTreeNode(node): entity = super(ListGroupsIqProtocolEntity, ListGroupsIqProtocolEntity).fromProtocolTreeNode(node) entity.__class__ = ListGroupsIqProtocolEntity entity.setProps(node.getChild(0).tag) return entity yowsup-2.4.48/yowsup/layers/protocol_groups/protocolentities/iq_groups_participants.py000066400000000000000000000031511263346463600320520ustar00rootroot00000000000000from yowsup.structs import ProtocolEntity, ProtocolTreeNode from .iq_groups import GroupsIqProtocolEntity class ParticipantsGroupsIqProtocolEntity(GroupsIqProtocolEntity): ''' ''' modes=["add","promote","remove","demote"] def __init__(self, jid, participantList, _mode, _id = None): super(ParticipantsGroupsIqProtocolEntity, self).__init__(to = jid, _id = _id, _type = "set") self.setProps(group_jid = jid, participantList = participantList, mode = _mode) def setProps(self, group_jid, participantList, mode): assert type(participantList) is list, "Must be a list of jids, got %s instead." % type(participantList) assert mode in self.modes, "Mode should be in: '" + "', '".join(self.modes) + "' but is '" + mode + "'" self.group_jid = group_jid self.participantList = participantList self.mode = mode def toProtocolTreeNode(self): node = super(ParticipantsGroupsIqProtocolEntity, self).toProtocolTreeNode() participantNodes = [ ProtocolTreeNode("participant", { "jid": participant }) for participant in self.participantList ] node.addChild(ProtocolTreeNode(self.mode,{}, participantNodes)) return node @staticmethod def fromProtocolTreeNode(node): entity = super(ParticipantsGroupsIqProtocolEntity, ParticipantsGroupsIqProtocolEntity).fromProtocolTreeNode(node) entity.__class__ = ParticipantsGroupsIqProtocolEntity return entity yowsup-2.4.48/yowsup/layers/protocol_groups/protocolentities/iq_groups_participants_add.py000066400000000000000000000021011263346463600326540ustar00rootroot00000000000000from yowsup.structs import ProtocolEntity, ProtocolTreeNode from .iq_groups_participants import ParticipantsGroupsIqProtocolEntity class AddParticipantsIqProtocolEntity(ParticipantsGroupsIqProtocolEntity): ''' ''' def __init__(self, group_jid, participantList, _id = None): super(AddParticipantsIqProtocolEntity, self).__init__(group_jid, participantList, "add", _id = _id) @staticmethod def fromProtocolTreeNode(node): entity = super(AddParticipantsIqProtocolEntity, AddParticipantsIqProtocolEntity).fromProtocolTreeNode(node) entity.__class__ = AddParticipantsIqProtocolEntity participantList = [] for participantNode in node.getChild("add").getAllChildren(): participantList.append(participantNode["jid"]) entity.setProps(node.getAttributeValue("to"), participantList) return entity yowsup-2.4.48/yowsup/layers/protocol_groups/protocolentities/iq_groups_participants_add_failure.py000066400000000000000000000015161263346463600343740ustar00rootroot00000000000000from yowsup.layers.protocol_iq.protocolentities import ErrorIqProtocolEntity class FailureAddParticipantsIqProtocolEntity(ErrorIqProtocolEntity): ''' ''' def __init__(self, _id, _from, _code, _text, _backoff= 0 ): super(FailureAddParticipantsIqProtocolEntity, self).__init__(_from = _from, _id = _id, code = _code, text = _text, backoff = _backoff) @staticmethod def fromProtocolTreeNode(node): entity = ErrorIqProtocolEntity.fromProtocolTreeNode(node) entity.__class__ = FailureAddParticipantsIqProtocolEntity return entityyowsup-2.4.48/yowsup/layers/protocol_groups/protocolentities/iq_groups_participants_add_success.py000066400000000000000000000033711263346463600344160ustar00rootroot00000000000000from yowsup.structs import ProtocolTreeNode from yowsup.layers.protocol_iq.protocolentities import ResultIqProtocolEntity class SuccessAddParticipantsIqProtocolEntity(ResultIqProtocolEntity): ''' ''' def __init__(self, _id, groupId, participantList): super(SuccessAddParticipantsIqProtocolEntity, self).__init__(_from = groupId, _id = _id) self.setProps(groupId, participantList) def setProps(self, groupId, participantList): self.groupId = groupId self.participantList = participantList self.action = 'add' def getAction(self): return self.action def toProtocolTreeNode(self): node = super(SuccessAddParticipantsIqProtocolEntity, self).toProtocolTreeNode() participantNodes = [ ProtocolTreeNode("add", { "type": "success", "participant": participant }) for participant in self.participantList ] node.addChildren(participantNodes) return node @staticmethod def fromProtocolTreeNode(node): entity = super(SuccessAddParticipantsIqProtocolEntity, SuccessAddParticipantsIqProtocolEntity).fromProtocolTreeNode(node) entity.__class__ = SuccessAddParticipantsIqProtocolEntity participantList = [] for participantNode in node.getAllChildren(): if participantNode["type"]=="success": participantList.append(participantNode["participant"]) entity.setProps(node.getAttributeValue("from"), participantList) return entity yowsup-2.4.48/yowsup/layers/protocol_groups/protocolentities/iq_groups_participants_demote.py000066400000000000000000000021411263346463600334050ustar00rootroot00000000000000from yowsup.structs import ProtocolEntity, ProtocolTreeNode from .iq_groups_participants import ParticipantsGroupsIqProtocolEntity class DemoteParticipantsIqProtocolEntity(ParticipantsGroupsIqProtocolEntity): ''' ''' def __init__(self, group_jid, participantList, _id = None): super(DemoteParticipantsIqProtocolEntity, self).__init__(group_jid, participantList, "demote", _id = _id) @staticmethod def fromProtocolTreeNode(node): entity = super(DemoteParticipantsIqProtocolEntity, DemoteParticipantsIqProtocolEntity).fromProtocolTreeNode(node) entity.__class__ = DemoteParticipantsIqProtocolEntity participantList = [] for participantNode in node.getChild("demote").getAllChildren(): participantList.append(participantNode["jid"]) entity.setProps(node.getAttributeValue("to"), participantList) return entity yowsup-2.4.48/yowsup/layers/protocol_groups/protocolentities/iq_groups_participants_promote.py000066400000000000000000000021521263346463600336170ustar00rootroot00000000000000from yowsup.structs import ProtocolEntity, ProtocolTreeNode from .iq_groups_participants import ParticipantsGroupsIqProtocolEntity class PromoteParticipantsIqProtocolEntity(ParticipantsGroupsIqProtocolEntity): ''' ''' def __init__(self, group_jid, participantList, _id = None): super(PromoteParticipantsIqProtocolEntity, self).__init__(group_jid, participantList, "promote", _id = _id) @staticmethod def fromProtocolTreeNode(node): entity = super(PromoteParticipantsIqProtocolEntity, PromoteParticipantsIqProtocolEntity).fromProtocolTreeNode(node) entity.__class__ = PromoteParticipantsIqProtocolEntity participantList = [] for participantNode in node.getChild("promote").getAllChildren(): participantList.append(participantNode["jid"]) entity.setProps(node.getAttributeValue("to"), participantList) return entity yowsup-2.4.48/yowsup/layers/protocol_groups/protocolentities/iq_groups_participants_remove.py000066400000000000000000000021501263346463600334250ustar00rootroot00000000000000from yowsup.structs import ProtocolEntity, ProtocolTreeNode from .iq_groups_participants import ParticipantsGroupsIqProtocolEntity class RemoveParticipantsIqProtocolEntity(ParticipantsGroupsIqProtocolEntity): ''' ''' def __init__(self, group_jid, participantList, _id = None): super(RemoveParticipantsIqProtocolEntity, self).__init__(group_jid, participantList, "remove", _id = _id) @staticmethod def fromProtocolTreeNode(node): entity = super(RemoveParticipantsIqProtocolEntity, RemoveParticipantsIqProtocolEntity).fromProtocolTreeNode(node) entity.__class__ = RemoveParticipantsIqProtocolEntity participantList = [] for participantNode in node.getChild("remove").getAllChildren(): participantList.append(participantNode["jid"]) entity.setProps(node.getAttributeValue("to"), participantList) return entity iq_groups_participants_remove_success.py000066400000000000000000000034351263346463600351050ustar00rootroot00000000000000yowsup-2.4.48/yowsup/layers/protocol_groups/protocolentitiesfrom yowsup.structs import ProtocolTreeNode from yowsup.layers.protocol_iq.protocolentities import ResultIqProtocolEntity class SuccessRemoveParticipantsIqProtocolEntity(ResultIqProtocolEntity): ''' ''' def __init__(self, _id, groupId, participantList): super(SuccessRemoveParticipantsIqProtocolEntity, self).__init__(_from = groupId, _id = _id) self.setProps(groupId, participantList) def setProps(self, groupId, participantList): self.groupId = groupId self.participantList = participantList self.action = 'remove' def getAction(self): return self.action def toProtocolTreeNode(self): node = super(SuccessRemoveParticipantsIqProtocolEntity, self).toProtocolTreeNode() participantNodes = [ ProtocolTreeNode("remove", { "type": "success", "participant": participant }) for participant in self.participantList ] node.addChildren(participantNodes) return node @staticmethod def fromProtocolTreeNode(node): entity = super(SuccessRemoveParticipantsIqProtocolEntity, SuccessRemoveParticipantsIqProtocolEntity).fromProtocolTreeNode(node) entity.__class__ = SuccessRemoveParticipantsIqProtocolEntity participantList = [] for participantNode in node.getAllChildren(): if participantNode["type"]=="success": participantList.append(participantNode["participant"]) entity.setProps(node.getAttributeValue("from"), participantList) return entity yowsup-2.4.48/yowsup/layers/protocol_groups/protocolentities/iq_groups_subject.py000066400000000000000000000020641263346463600310120ustar00rootroot00000000000000from yowsup.structs import ProtocolEntity, ProtocolTreeNode from .iq_groups import GroupsIqProtocolEntity class SubjectGroupsIqProtocolEntity(GroupsIqProtocolEntity): ''' {{NEW_VAL}} ''' def __init__(self, jid, subject, _id = None): super(SubjectGroupsIqProtocolEntity, self).__init__(to = jid, _id = _id, _type = "set") self.setProps(subject) def setProps(self, subject): self.subject = subject def toProtocolTreeNode(self): node = super(SubjectGroupsIqProtocolEntity, self).toProtocolTreeNode() node.addChild(ProtocolTreeNode("subject",{}, None, self.subject)) return node @staticmethod def fromProtocolTreeNode(node): entity = super(SubjectGroupsIqProtocolEntity, SubjectGroupsIqProtocolEntity).fromProtocolTreeNode(node) entity.__class__ = SubjectGroupsIqProtocolEntity entity.setProps(node.getChild("subject").getData()) return entity yowsup-2.4.48/yowsup/layers/protocol_groups/protocolentities/iq_result_groups_info.py000066400000000000000000000102401263346463600316770ustar00rootroot00000000000000from yowsup.structs import ProtocolTreeNode from yowsup.layers.protocol_iq.protocolentities import ResultIqProtocolEntity class InfoGroupsResultIqProtocolEntity(ResultIqProtocolEntity): ''' ''' TYPE_PARTICIPANT_ADMIN = "admin" def __init__(self, _id, _from, groupId, creationTimestamp, creatorJid, subject, subjectTime, subjectOwnerJid, participants): super(InfoGroupsResultIqProtocolEntity, self).__init__(_id = _id, _from = _from) self.setGroupProps(groupId, creationTimestamp, creatorJid, subject, subjectTime, subjectOwnerJid, participants) def setGroupProps(self, groupId, creationTimestamp, creatorJid, subject, subjectTime, subjectOwnerJid, participants): assert type(participants) is dict, "Participants must be a dict {jid => type?}" self.groupId = groupId self.creationTimestamp = int(creationTimestamp) self.creatorJid = creatorJid self.subject = subject self.subjectTime = int(subjectTime) self.subjectOwnerJid = subjectOwnerJid self.participants = participants def getParticipants(self): return self.participants def getSubject(self): return self.subject def getGroupId(self): return self.groupId def getCreationTimestamp(self): return self.creationTimestamp def getCreatorJid(self, full = True): return self.creatorJid if full else self.creatorJid.split('@')[0] def getSubjectTimestamp(self): return self.subjectTime def getSubjectOwnerJid(self, full = True): return self.subjectOwnerJid if full else self.subjectOwnerJid.split('@')[0] def getGroupAdmins(self, full = True): admins = [] for jid, _type in self.participants.items(): if _type == self.__class__.TYPE_PARTICIPANT_ADMIN: admins.append(jid if full else jid.split('@')[0]) return admins def __str__(self): out = super(InfoGroupsResultIqProtocolEntity, self).__str__() out += "Group ID: %s\n" % self.groupId out += "Created: %s\n" % self.creationTimestamp out += "Creator JID: %s\n" % self.creatorJid out += "Subject: %s\n" % self.subject out += "Subject Timestamp: %s\n" % self.subjectTime out += "Subject owner JID: %s\n" % self.subjectOwnerJid out += "Participants: %s\n" % self.participants return out def toProtocolTreeNode(self): node = super(InfoGroupsResultIqProtocolEntity, self).toProtocolTreeNode() groupNode = ProtocolTreeNode("group", { "subject": self.getSubject(), "creation": str(self.getCreationTimestamp()), "creator": self.getCreatorJid(), "s_t": self.getSubjectTimestamp(), "s_o": self.getSubjectOwnerJid(), "id": self.getGroupId() }) participants = [] for jid, _type in self.getParticipants().items(): pnode = ProtocolTreeNode("participant", {"jid": jid}) if _type: pnode["type"] = _type participants.append(pnode) groupNode.addChildren(participants) node.addChild(groupNode) return node @staticmethod def fromProtocolTreeNode(node): groupNode = node.getChild("group") participants = {} for p in groupNode.getAllChildren("participant"): participants[p["jid"]] = p["type"] return InfoGroupsResultIqProtocolEntity( node["id"], node["from"], groupNode["id"], groupNode["creation"], groupNode["creator"], groupNode["subject"], groupNode["s_t"], groupNode["s_o"], participants ) yowsup-2.4.48/yowsup/layers/protocol_groups/protocolentities/iq_result_groups_list.py000066400000000000000000000063711263346463600317310ustar00rootroot00000000000000from yowsup.structs import ProtocolEntity, ProtocolTreeNode from yowsup.layers.protocol_iq.protocolentities import ResultIqProtocolEntity from ..structs import Group class ListGroupsResultIqProtocolEntity(ResultIqProtocolEntity): ''' ''' def __init__(self, groupsList): super(ListGroupsResultIqProtocolEntity, self).__init__(_from = "g.us") self.setProps(groupsList) def __str__(self): out = super(ListGroupsResultIqProtocolEntity, self).__str__() out += "Groups:\n" for g in self.groupsList: out += "%s\n" % g return out def getGroups(self): return self.groupsList def setProps(self, groupsList): assert type(groupsList) is list and (len(groupsList) == 0 or groupsList[0].__class__ is Group),\ "groupList must be a list of Group instances" self.groupsList = groupsList def toProtocolTreeNode(self): node = super(ListGroupsResultIqProtocolEntity, self).toProtocolTreeNode() groupsNodes = [] for group in self.groupsList: groupNode = ProtocolTreeNode("group", { "id": group.getId(), "creator": group.getCreator(), "subject": group.getSubject(), "s_o": group.getSubjectOwner(), "s_t": str(group.getSubjectTime()), "creation": str(group.getCreationTime()) }, ) participants = [] for jid, _type in group.getParticipants().items(): pnode = ProtocolTreeNode("participant", {"jid": jid}) if _type: pnode["type"] = _type participants.append(pnode) groupNode.addChildren(participants) groupsNodes.append(groupNode) node.addChild(ProtocolTreeNode("groups", children = groupsNodes)) return node @staticmethod def fromProtocolTreeNode(node): entity = super(ListGroupsResultIqProtocolEntity, ListGroupsResultIqProtocolEntity).fromProtocolTreeNode(node) entity.__class__ = ListGroupsResultIqProtocolEntity groups = [] for groupNode in node.getChild("groups").getAllChildren(): participants = {} for p in groupNode.getAllChildren("participant"): participants[p["jid"]] = p["type"] groups.append( Group(groupNode["id"], groupNode["creator"], groupNode["subject"], groupNode["s_o"], groupNode["s_t"], groupNode["creation"], participants) ) entity.setProps(groups) return entityyowsup-2.4.48/yowsup/layers/protocol_groups/protocolentities/iq_result_participants_list.py000066400000000000000000000031341263346463600331050ustar00rootroot00000000000000from yowsup.structs import ProtocolTreeNode from yowsup.layers.protocol_iq.protocolentities import ResultIqProtocolEntity class ListParticipantsResultIqProtocolEntity(ResultIqProtocolEntity): ''' ''' def __init__(self, _from, participantList): super(ListParticipantsResultIqProtocolEntity, self).__init__(_from = _from) self.setParticipants(participantList) def __str__(self): out = super(ListParticipantsResultIqProtocolEntity, self).__str__() out += "Participants: %s\n" % " ".join(self.participantList) return out def getParticipants(self): return self.participantList def setParticipants(self, participants): self.participantList = participants def toProtocolTreeNode(self): node = super(ListParticipantsResultIqProtocolEntity, self).toProtocolTreeNode() participantNodes = [ ProtocolTreeNode("participant", { "jid": participant }) for participant in self.participantList ] node.addChildren(participantNodes) return node @staticmethod def fromProtocolTreeNode(node): entity = super(ListParticipantsResultIqProtocolEntity, ListParticipantsResultIqProtocolEntity).fromProtocolTreeNode(node) entity.__class__ = ListParticipantsResultIqProtocolEntity entity.setParticipants([ pNode.getAttributeValue("jid") for pNode in node.getAllChildren() ]) return entity yowsup-2.4.48/yowsup/layers/protocol_groups/protocolentities/notification_groups.py000066400000000000000000000033141263346463600313470ustar00rootroot00000000000000from yowsup.structs import ProtocolEntity, ProtocolTreeNode from yowsup.layers.protocol_notifications.protocolentities import NotificationProtocolEntity class GroupsNotificationProtocolEntity(NotificationProtocolEntity): ''' ''' def __init__(self, _id, _from, timestamp, notify, participant, offline): super(GroupsNotificationProtocolEntity, self).__init__("w:gp2", _id, _from, timestamp, notify, offline) self.setParticipant(participant) self.setGroupId(_from) def setParticipant(self, participant): self._participant = participant def getParticipant(self, full = True): return self._participant if full else self._participant.split('@')[0] def getGroupId(self): return self.groupId def setGroupId(self, groupId): self.groupId = groupId def __str__(self): out = super(GroupsNotificationProtocolEntity, self).__str__() out += "Participant: %s\n" % self.getParticipant() return out def toProtocolTreeNode(self): node = super(GroupsNotificationProtocolEntity, self).toProtocolTreeNode() node.setAttribute("participant", self.getParticipant()) return node @staticmethod def fromProtocolTreeNode(node): entity = super(GroupsNotificationProtocolEntity, GroupsNotificationProtocolEntity).fromProtocolTreeNode(node) entity.__class__ = GroupsNotificationProtocolEntity entity.setParticipant(node.getAttributeValue("participant")) entity.setGroupId(node.getAttributeValue("from")) return entity yowsup-2.4.48/yowsup/layers/protocol_groups/protocolentities/notification_groups_add.py000066400000000000000000000036321263346463600321620ustar00rootroot00000000000000from .notification_groups import GroupsNotificationProtocolEntity from yowsup.structs import ProtocolTreeNode class AddGroupsNotificationProtocolEntity(GroupsNotificationProtocolEntity): ''' ''' def __init__(self, _id, _from, timestamp, notify, participant, offline, participants): super(AddGroupsNotificationProtocolEntity, self).__init__(_id, _from, timestamp, notify, participant, offline) self.setParticipants(participants) def setParticipants(self, participants): assert type(participants) is list, "Must be a list of jids, got %s instead." % type(participants) self.participants = participants def getParticipants(self): return self.participants def __str__(self): out = super(AddGroupsNotificationProtocolEntity, self).__str__() out += "Participants: %s\n" % " ".join(self.getParticipants()) return out def toProtocolTreeNode(self): node = super(AddGroupsNotificationProtocolEntity, self).toProtocolTreeNode() addNode = ProtocolTreeNode("add") participants = [] for jid in self.getParticipants(): pnode = ProtocolTreeNode("participant", {"jid": jid}) participants.append(pnode) addNode.addChildren(participants) node.addChild(addNode) return node @staticmethod def fromProtocolTreeNode(node): addNode = node.getChild("add") participants = [] for p in addNode.getAllChildren("participant"): participants.append(p["jid"]) return AddGroupsNotificationProtocolEntity( node["id"], node["from"], node["t"], node["notify"], node["participant"], node["offline"], participants )yowsup-2.4.48/yowsup/layers/protocol_groups/protocolentities/notification_groups_create.py000066400000000000000000000112631263346463600326740ustar00rootroot00000000000000from .notification_groups import GroupsNotificationProtocolEntity from yowsup.structs import ProtocolTreeNode class CreateGroupsNotificationProtocolEntity(GroupsNotificationProtocolEntity): ''' ''' TYPE_CREATE_NEW = "new" TYPE_PARTICIPANT_ADMIN = "admin" def __init__(self, _id, _from, timestamp, notify, participant, offline, createType, groupId, creationTimestamp, creatorJid, subject, subjectTime, subjectOwnerJid, participants): super(CreateGroupsNotificationProtocolEntity, self).__init__(_id, _from, timestamp, notify, participant, offline) self.setGroupProps(createType, groupId, creationTimestamp, creatorJid, subject, subjectTime, subjectOwnerJid, participants) def setGroupProps(self, createType, groupId, creationTimestamp, creatorJid, subject, subjectTime, subjectOwnerJid, participants): assert type(participants) is dict, "Participants must be a dict {jid => type?}" self.createType = createType self.groupId = groupId self.creationTimestamp = int(creationTimestamp) self.creatorJid = creatorJid self.subject = subject self.subjectTime = int(subjectTime) self.subjectOwnerJid = subjectOwnerJid self.participants = participants def getParticipants(self): return self.participants def getSubject(self): return self.subject def getGroupId(self): return self.groupId def getCreationTimestamp(self): return self.creationTimestamp def getCreatorJid(self, full = True): return self.creatorJid if full else self.creatorJid.split('@')[0] def getSubjectTimestamp(self): return self.subjectTime def getSubjectOwnerJid(self, full = True): return self.subjectOwnerJid if full else self.subjectOwnerJid.split('@')[0] def getCreatetype(self): return self.createType def getGroupAdmin(self, full = True): for jid, _type in self.participants.items(): if _type == self.__class__.TYPE_PARTICIPANT_ADMIN: return jid if full else jid.split('@')[0] def __str__(self): out = super(CreateGroupsNotificationProtocolEntity, self).__str__() out += "Creator: %s\n" % self.getCreatorJid() out += "Create type: %s\n" % self.getCreatetype() out += "Creation timestamp: %s\n" % self.getCreationTimestamp() out += "Subject: %s\n" % self.getSubject() out += "Subject owner: %s\n" % self.getSubjectOwnerJid() out += "Subject timestamp: %s\n" % self.getSubjectTimestamp() out += "Participants: %s\n" % self.getParticipants() return out def toProtocolTreeNode(self): node = super(CreateGroupsNotificationProtocolEntity, self).toProtocolTreeNode() createNode = ProtocolTreeNode("create", {"type": self.getCreatetype()}) groupNode = ProtocolTreeNode("group", { "subject": self.getSubject(), "creation": str(self.getCreationTimestamp()), "creator": self.getCreatorJid(), "s_t": self.getSubjectTimestamp(), "s_o": self.getSubjectOwnerJid(), "id": self.getGroupId() }) participants = [] for jid, _type in self.getParticipants().items(): pnode = ProtocolTreeNode("participant", {"jid": jid}) if _type: pnode["type"] = _type participants.append(pnode) groupNode.addChildren(participants) createNode.addChild(groupNode) node.addChild(createNode) return node @staticmethod def fromProtocolTreeNode(node): createNode = node.getChild("create") groupNode = createNode.getChild("group") participants = {} for p in groupNode.getAllChildren("participant"): participants[p["jid"]] = p["type"] return CreateGroupsNotificationProtocolEntity( node["id"], node["from"], node["t"], node["notify"], node["participant"], node["offline"], createNode["type"], groupNode["id"], groupNode["creation"], groupNode["creator"], groupNode["subject"], groupNode["s_t"], groupNode["s_o"], participants ) yowsup-2.4.48/yowsup/layers/protocol_groups/protocolentities/notification_groups_remove.py000066400000000000000000000040651263346463600327300ustar00rootroot00000000000000from .notification_groups import GroupsNotificationProtocolEntity from yowsup.structs import ProtocolTreeNode class RemoveGroupsNotificationProtocolEntity(GroupsNotificationProtocolEntity): ''' ''' TYPE_PARTICIPANT_ADMIN = "admin" def __init__(self, _id, _from, timestamp, notify, participant, offline, subject, participants): super(RemoveGroupsNotificationProtocolEntity, self).__init__(_id, _from, timestamp, notify, participant, offline) self.setGroupProps(subject, participants) def setGroupProps(self, subject, participants): assert type(participants) is dict, "Participants must be a dict {jid => type?}" self.subject = subject self.participants = participants def getParticipants(self): return self.participants def getSubject(self): return self.subject def toProtocolTreeNode(self): node = super(RemoveGroupsNotificationProtocolEntity, self).toProtocolTreeNode() removeNode = ProtocolTreeNode("remove", {"subject": self.subject}) participants = [] for jid in self.getParticipants(): pnode = ProtocolTreeNode("participant", {"jid": jid}) participants.append(pnode) removeNode.addChildren(participants) node.addChild(removeNode) return node @staticmethod def fromProtocolTreeNode(node): removeNode = node.getChild("remove") participants = {} for p in removeNode.getAllChildren("participant"): participants[p["jid"]] = p["type"] return RemoveGroupsNotificationProtocolEntity( node["id"], node["from"], node["t"], node["notify"], node["participant"], node["offline"], removeNode["subject"], participants ) yowsup-2.4.48/yowsup/layers/protocol_groups/protocolentities/notification_groups_subject.py000066400000000000000000000044001263346463600330630ustar00rootroot00000000000000from yowsup.structs import ProtocolEntity, ProtocolTreeNode from yowsup.layers.protocol_notifications.protocolentities import NotificationProtocolEntity from .notification_groups import GroupsNotificationProtocolEntity class SubjectGroupsNotificationProtocolEntity(GroupsNotificationProtocolEntity): ''' ''' def __init__(self, _type, _id, _from, timestamp, notify, participant, subject): super(SubjectGroupsNotificationProtocolEntity, self).__init__(_id, _from, timestamp, notify, participant) self.setSubjectData(subject) def setSubjectData(self, subject, subjectOwner, subjectTimestamp): self.subject = subject self.subjectOwner = subjectOwner self.subjectTimestamp = int(subjectTimestamp) def getSubject(self): return self.subject def getSubjectOwner(self, full = True): return self.subjectOwner if full else self.subjectOwner.split('@')[0] def getSubjectTimestamp(self): return self.subjectTimestamp def __str__(self): out = super(SubjectGroupsNotificationProtocolEntity, self).__str__() out += "New subject: %s\n" % self.getSubject() out += "Set by: %s\n" % self.getSubjectOwner() return out def toProtocolTreeNode(self): node = super(SubjectGroupsNotificationProtocolEntity, self).toProtocolTreeNode() subjectNode = ProtocolTreeNode("subject", { "s_t": str(self.getSubjectTimestamp()), "s_o": self.getSubjectOwner(), "subject": self.getSubject() }) node.addChild(subjectNode) return node @staticmethod def fromProtocolTreeNode(node): entity = super(SubjectGroupsNotificationProtocolEntity, SubjectGroupsNotificationProtocolEntity).fromProtocolTreeNode(node) entity.__class__ = SubjectGroupsNotificationProtocolEntity subjectNode = node.getChild("subject") entity.setSubjectData(subjectNode["subject"], subjectNode["s_o"], subjectNode["s_t"]) return entity yowsup-2.4.48/yowsup/layers/protocol_groups/protocolentities/test_iq_groups.py000066400000000000000000000002261263346463600303300ustar00rootroot00000000000000from yowsup.layers.protocol_iq.protocolentities.test_iq import IqProtocolEntityTest class GroupsIqProtocolEntityTest(IqProtocolEntityTest): pass yowsup-2.4.48/yowsup/layers/protocol_groups/protocolentities/test_iq_groups_create.py000066400000000000000000000006761263346463600316640ustar00rootroot00000000000000from yowsup.layers.protocol_groups.protocolentities.iq_groups_create import CreateGroupsIqProtocolEntity from yowsup.structs.protocolentity import ProtocolEntityTest import unittest entity = CreateGroupsIqProtocolEntity("group subject") class CreateGroupsIqProtocolEntityTest(ProtocolEntityTest, unittest.TestCase): def setUp(self): self.ProtocolEntity = CreateGroupsIqProtocolEntity self.node = entity.toProtocolTreeNode() yowsup-2.4.48/yowsup/layers/protocol_groups/protocolentities/test_iq_groups_create_success.py000066400000000000000000000007161263346463600334070ustar00rootroot00000000000000from yowsup.structs.protocolentity import ProtocolEntityTest from yowsup.layers.protocol_groups.protocolentities import SuccessCreateGroupsIqProtocolEntity import unittest entity = SuccessCreateGroupsIqProtocolEntity("123-456", "431-123") class SuccessCreateGroupsIqProtocolEntityTest(ProtocolEntityTest, unittest.TestCase): def setUp(self): self.ProtocolEntity = SuccessCreateGroupsIqProtocolEntity self.node = entity.toProtocolTreeNode() yowsup-2.4.48/yowsup/layers/protocol_groups/protocolentities/test_iq_groups_list.py000066400000000000000000000006451263346463600313700ustar00rootroot00000000000000from yowsup.layers.protocol_groups.protocolentities.iq_groups_list import ListGroupsIqProtocolEntity from yowsup.structs.protocolentity import ProtocolEntityTest import unittest entity = ListGroupsIqProtocolEntity() class ListGroupsIqProtocolEntityTest(ProtocolEntityTest, unittest.TestCase): def setUp(self): self.ProtocolEntity = ListGroupsIqProtocolEntity self.node = entity.toProtocolTreeNode() yowsup-2.4.48/yowsup/layers/protocol_groups/protocolentities/test_iq_result_groups.py000066400000000000000000000002561263346463600317310ustar00rootroot00000000000000from yowsup.layers.protocol_iq.protocolentities.test_iq_result import ResultIqProtocolEntityTest class GroupsResultIqProtocolEntityTest(ResultIqProtocolEntityTest): passyowsup-2.4.48/yowsup/layers/protocol_groups/protocolentities/test_iq_result_groups_list.py000066400000000000000000000014201263346463600327560ustar00rootroot00000000000000from yowsup.layers.protocol_groups.protocolentities.iq_result_groups_list import ListGroupsResultIqProtocolEntity from yowsup.structs.protocolentity import ProtocolEntityTest from yowsup.layers.protocol_groups.structs import Group import unittest import time entity = ListGroupsResultIqProtocolEntity( [ Group("1234-456", "owner@s.whatsapp.net", "subject", "sOwnerJid@s.whatsapp.net", int(time.time()), int(time.time())), Group("4321-456", "owner@s.whatsapp.net", "subject", "sOwnerJid@s.whatsapp.net", int(time.time()), int(time.time())) ] ) class ListGroupsResultIqProtocolEntityTest(ProtocolEntityTest, unittest.TestCase): def setUp(self): self.ProtocolEntity = ListGroupsResultIqProtocolEntity self.node = entity.toProtocolTreeNode() yowsup-2.4.48/yowsup/layers/protocol_groups/structs/000077500000000000000000000000001263346463600230105ustar00rootroot00000000000000yowsup-2.4.48/yowsup/layers/protocol_groups/structs/__init__.py000066400000000000000000000000301263346463600251120ustar00rootroot00000000000000from .group import Groupyowsup-2.4.48/yowsup/layers/protocol_groups/structs/group.py000066400000000000000000000024071263346463600245210ustar00rootroot00000000000000class Group(object): def __init__(self, groupId, creatorJid, subject, subjectOwnerJid, subjectTime, creationTime, participants=None): self._groupId = groupId self._creatorJid = creatorJid self._subject = subject self._subjectOwnerJid = subjectOwnerJid self._subjectTime = int(subjectTime) self._creationTime = int(creationTime) self._participants = participants or {} def getId(self): return self._groupId def getCreator(self): return self._creatorJid def getOwner(self): return self.getCreator() def getSubject(self): return self._subject def getSubjectOwner(self): return self._subjectOwnerJid def getSubjectTime(self): return self._subjectTime def getCreationTime(self): return self._creationTime def __str__(self): return "ID: %s, Subject: %s, Creation: %s, Creator: %s, Subject Owner: %s, Subject Time: %s\nParticipants: %s" %\ (self.getId(), self.getSubject(), self.getCreationTime(), self.getCreator(), self.getSubjectOwner(), self.getSubjectTime(), ", ".join(self._participants.keys())) def getParticipants(self): return self._participants yowsup-2.4.48/yowsup/layers/protocol_ib/000077500000000000000000000000001263346463600203545ustar00rootroot00000000000000yowsup-2.4.48/yowsup/layers/protocol_ib/__init__.py000066400000000000000000000000471263346463600224660ustar00rootroot00000000000000from .layer import YowIbProtocolLayer yowsup-2.4.48/yowsup/layers/protocol_ib/layer.py000066400000000000000000000017211263346463600220430ustar00rootroot00000000000000from yowsup.layers import YowLayer, YowLayerEvent, YowProtocolLayer from .protocolentities import * class YowIbProtocolLayer(YowProtocolLayer): def __init__(self): handleMap = { "ib": (self.recvIb, self.sendIb), "iq": (None, self.sendIb) } super(YowIbProtocolLayer, self).__init__(handleMap) def __str__(self): return "Ib Layer" def sendIb(self, entity): if entity.__class__ == CleanIqProtocolEntity: self.toLower(entity.toProtocolTreeNode()) def recvIb(self, node): if node.getChild("dirty"): self.toUpper(DirtyIbProtocolEntity.fromProtocolTreeNode(node)) elif node.getChild("offline"): self.toUpper(OfflineIbProtocolEntity.fromProtocolTreeNode(node)) elif node.getChild("account"): self.toUpper(AccountIbProtocolEntity.fromProtocolTreeNode(node)) else: raise ValueError("Unkown ib node %s" % node) yowsup-2.4.48/yowsup/layers/protocol_ib/protocolentities/000077500000000000000000000000001263346463600237625ustar00rootroot00000000000000yowsup-2.4.48/yowsup/layers/protocol_ib/protocolentities/__init__.py000066400000000000000000000002671263346463600261000ustar00rootroot00000000000000from .clean_iq import CleanIqProtocolEntity from .dirty_ib import DirtyIbProtocolEntity from .offline_ib import OfflineIbProtocolEntity from .account_ib import AccountIbProtocolEntityyowsup-2.4.48/yowsup/layers/protocol_ib/protocolentities/account_ib.py000066400000000000000000000037141263346463600264470ustar00rootroot00000000000000from yowsup.structs import ProtocolEntity, ProtocolTreeNode from .ib import IbProtocolEntity class AccountIbProtocolEntity(IbProtocolEntity): ''' ''' STATUS_ACTIVE = "active" KIND_PAD = "paid" def __init__(self, status, kind, creation, expiration): super(AccountIbProtocolEntity, self).__init__() self.setProps(status, kind, creation, expiration) def setProps(self, status, kind, creation, expiration): self.status = status self.creation = int(creation) self.kind = kind self.expiration= int(expiration) def toProtocolTreeNode(self): node = super(AccountIbProtocolEntity, self).toProtocolTreeNode() accountChild = ProtocolTreeNode("account", { "status": self.status, "kind": self.kind, "creation": int(self.creation), "expiration": int(self.expiration) }) node.addChild(accountChild) return node def __str__(self): out = super(AccountIbProtocolEntity, self).__str__() out += "Status: %s\n" % self.status out += "Kind: %s\n" % self.kind out += "Creation: %s\n" % self.creation out += "Expiration: %s\n" % self.expiration return out @staticmethod def fromProtocolTreeNode(node): entity = IbProtocolEntity.fromProtocolTreeNode(node) entity.__class__ = AccountIbProtocolEntity accountNode = node.getChild("account") entity.setProps( accountNode["status"], accountNode["kind"], accountNode["creation"], accountNode["expiration"] )yowsup-2.4.48/yowsup/layers/protocol_ib/protocolentities/clean_iq.py000066400000000000000000000024211263346463600261060ustar00rootroot00000000000000from yowsup.structs import ProtocolEntity, ProtocolTreeNode from yowsup.layers.protocol_iq.protocolentities import IqProtocolEntity class CleanIqProtocolEntity(IqProtocolEntity): ''' ''' def __init__(self, cleanType, to, _id = None): super(CleanIqProtocolEntity, self).__init__( "urn:xmpp:whatsapp:dirty", _id = _id, _type = "set", to = to ) self.setProps(cleanType) def setProps(self, cleanType): self.cleanType = cleanType def __str__(self): out = super(CleanIqProtocolEntity, self).__str__() out += "Clean Type: %s\n" % self.cleanType return out def toProtocolTreeNode(self): node = super(CleanIqProtocolEntity, self).toProtocolTreeNode() cleanNode = ProtocolTreeNode("clean", {"type": self.cleanType}) node.addChild(cleanNode) return node @staticmethod def fromProtocolTreeNode(node): entity = IqProtocolEntity.fromProtocolTreeNode(node) entity.__class__ = CleanIqProtocolEntity entity.setProps(node.getChild("clean").getAttributeValue("type")) return entityyowsup-2.4.48/yowsup/layers/protocol_ib/protocolentities/dirty_ib.py000066400000000000000000000024011263346463600261360ustar00rootroot00000000000000from yowsup.structs import ProtocolEntity, ProtocolTreeNode from .ib import IbProtocolEntity class DirtyIbProtocolEntity(IbProtocolEntity): ''' ''' def __init__(self, timestamp, _type): super(DirtyIbProtocolEntity, self).__init__() self.setProps(timestamp, _type) def setProps(self, timestamp, _type): self.timestamp = int(timestamp) self._type = _type def toProtocolTreeNode(self): node = super(DirtyIbProtocolEntity, self).toProtocolTreeNode() dirtyNode = ProtocolTreeNode("dirty") dirtyNode["timestamp"] = str(self.timestamp) dirtyNode["type"] = self._type node.addChild(dirtyNode) return node def __str__(self): out = super(DirtyIbProtocolEntity, self).__str__() out += "Type: %s\n" % self._type out += "Timestamp: %s\n" % self.timestamp return out @staticmethod def fromProtocolTreeNode(node): entity = IbProtocolEntity.fromProtocolTreeNode(node) entity.__class__ = DirtyIbProtocolEntity dirtyChild = node.getChild("dirty") entity.setProps(dirtyChild["timestamp"], dirtyChild["type"]) return entity yowsup-2.4.48/yowsup/layers/protocol_ib/protocolentities/ib.py000066400000000000000000000007151263346463600247310ustar00rootroot00000000000000from yowsup.structs import ProtocolEntity, ProtocolTreeNode class IbProtocolEntity(ProtocolEntity): ''' ''' def __init__(self): super(IbProtocolEntity, self).__init__("ib") def toProtocolTreeNode(self): return self._createProtocolTreeNode({}, None, None) def __str__(self): out = "Ib:\n" return out @staticmethod def fromProtocolTreeNode(node): return IbProtocolEntity() yowsup-2.4.48/yowsup/layers/protocol_ib/protocolentities/offline_ib.py000066400000000000000000000020501263346463600264250ustar00rootroot00000000000000from yowsup.structs import ProtocolEntity, ProtocolTreeNode from .ib import IbProtocolEntity class OfflineIbProtocolEntity(IbProtocolEntity): ''' ''' def __init__(self, count): super(IbProtocolEntity, self).__init__() self.setProps(count) def setProps(self, count): self.count = int(count) def toProtocolTreeNode(self): node = super(OfflineIbProtocolEntity, self).toProtocolTreeNode() offlineChild = ProtocolTreeNode("offline", {"count": str(self.count)}) node.addChild(offlineChild) return node def __str__(self): out = super(OfflineIbProtocolEntity, self).__str__() out += "Offline count: %s\n" % self.count return out @staticmethod def fromProtocolTreeNode(node): entity = IbProtocolEntity.fromProtocolTreeNode(node) entity.__class__ = OfflineIbProtocolEntity entity.setProps(node.getChild("offline")["count"]) return entity yowsup-2.4.48/yowsup/layers/protocol_ib/protocolentities/test_clean_iq.py000066400000000000000000000007651263346463600271560ustar00rootroot00000000000000from yowsup.structs import ProtocolTreeNode from yowsup.layers.protocol_ib.protocolentities.clean_iq import CleanIqProtocolEntity from yowsup.layers.protocol_iq.protocolentities.test_iq import IqProtocolEntityTest class CleanIqProtocolEntityTest(IqProtocolEntityTest): def setUp(self): super(CleanIqProtocolEntityTest, self).setUp() self.ProtocolEntity = CleanIqProtocolEntity cleanNode = ProtocolTreeNode("clean", {"type": "groups"}) self.node.addChild(cleanNode)yowsup-2.4.48/yowsup/layers/protocol_ib/protocolentities/test_dirty_ib.py000066400000000000000000000010571263346463600272030ustar00rootroot00000000000000from yowsup.layers.protocol_ib.protocolentities.test_ib import IbProtocolEntityTest from yowsup.layers.protocol_ib.protocolentities.dirty_ib import DirtyIbProtocolEntity from yowsup.structs import ProtocolTreeNode class DirtyIbProtocolEntityTest(IbProtocolEntityTest): def setUp(self): super(DirtyIbProtocolEntityTest, self).setUp() self.ProtocolEntity = DirtyIbProtocolEntity dirtyNode = ProtocolTreeNode("dirty") dirtyNode["timestamp"] = "123456" dirtyNode["type"] = "groups" self.node.addChild(dirtyNode)yowsup-2.4.48/yowsup/layers/protocol_ib/protocolentities/test_ib.py000066400000000000000000000005671263346463600257750ustar00rootroot00000000000000from yowsup.layers.protocol_ib.protocolentities.ib import IbProtocolEntity from yowsup.structs import ProtocolTreeNode from yowsup.structs.protocolentity import ProtocolEntityTest import unittest class IbProtocolEntityTest(ProtocolEntityTest, unittest.TestCase): def setUp(self): self.ProtocolEntity = IbProtocolEntity self.node = ProtocolTreeNode("ib") yowsup-2.4.48/yowsup/layers/protocol_ib/protocolentities/test_offline_iq.py000066400000000000000000000007361263346463600275140ustar00rootroot00000000000000from yowsup.layers.protocol_ib.protocolentities.test_ib import IbProtocolEntityTest from yowsup.layers.protocol_ib.protocolentities.offline_ib import OfflineIbProtocolEntity from yowsup.structs import ProtocolTreeNode class OfflineIbProtocolEntityTest(IbProtocolEntityTest): def setUp(self): super(OfflineIbProtocolEntityTest, self).setUp() self.ProtocolEntity = OfflineIbProtocolEntity self.node.addChild(ProtocolTreeNode("offline", {"count": "5"}))yowsup-2.4.48/yowsup/layers/protocol_iq/000077500000000000000000000000001263346463600203735ustar00rootroot00000000000000yowsup-2.4.48/yowsup/layers/protocol_iq/__init__.py000066400000000000000000000000451263346463600225030ustar00rootroot00000000000000from .layer import YowIqProtocolLayeryowsup-2.4.48/yowsup/layers/protocol_iq/layer.py000066400000000000000000000073271263346463600220720ustar00rootroot00000000000000import time import logging from threading import Thread, Lock from yowsup.layers import YowProtocolLayer, YowLayerEvent from yowsup.common import YowConstants from yowsup.layers.network import YowNetworkLayer from yowsup.layers.auth import YowAuthenticationProtocolLayer from .protocolentities import * class YowIqProtocolLayer(YowProtocolLayer): PROP_PING_INTERVAL = "org.openwhatsapp.yowsup.prop.pinginterval" def __init__(self): handleMap = { "iq": (self.recvIq, self.sendIq) } self._pingThread = None self._pingQueue = {} self._pingQueueLock = Lock() self.__logger = logging.getLogger(__name__) super(YowIqProtocolLayer, self).__init__(handleMap) def __str__(self): return "Iq Layer" def onPong(self, protocolTreeNode, pingEntity): self.gotPong(pingEntity.getId()) self.toUpper(ResultIqProtocolEntity.fromProtocolTreeNode(protocolTreeNode)) def sendIq(self, entity): if entity.getXmlns() == "w:p": self._sendIq(entity, self.onPong) elif entity.getXmlns() in ("urn:xmpp:whatsapp:push", "w", "urn:xmpp:whatsapp:account", "encrypt"): self.toLower(entity.toProtocolTreeNode()) def recvIq(self, node): if node["xmlns"] == "urn:xmpp:ping": entity = PongResultIqProtocolEntity(YowConstants.DOMAIN, node["id"]) self.toLower(entity.toProtocolTreeNode()) def gotPong(self, pingId): self._pingQueueLock.acquire() if pingId in self._pingQueue: self._pingQueue = {} self._pingQueueLock.release() def waitPong(self, id): self._pingQueueLock.acquire() self._pingQueue[id] = None pingQueueSize = len(self._pingQueue) self._pingQueueLock.release() self.__logger.debug("ping queue size: %d" % pingQueueSize) if pingQueueSize >= 2: self.getStack().broadcastEvent(YowLayerEvent(YowNetworkLayer.EVENT_STATE_DISCONNECT, reason = "Ping Timeout")) def onEvent(self, event): name = event.getName() if name == YowAuthenticationProtocolLayer.EVENT_AUTHED: interval = self.getProp(self.__class__.PROP_PING_INTERVAL, 50) if not self._pingThread and interval > 0: self._pingQueue = {} self._pingThread = YowPingThread(self, interval) self.__logger.debug("starting ping thread.") self._pingThread.start() elif name == YowNetworkLayer.EVENT_STATE_DISCONNECT or name == YowNetworkLayer.EVENT_STATE_DISCONNECTED: if self._pingThread: self.__logger.debug("stopping ping thread") if self._pingThread: self._pingThread.stop() self._pingThread = None self._pingQueue = {} class YowPingThread(Thread): def __init__(self, layer, interval): assert type(layer) is YowIqProtocolLayer, "layer must be a YowIqProtocolLayer, got %s instead." % type(layer) self._layer = layer self._interval = interval self._stop = False self.__logger = logging.getLogger(__name__) super(YowPingThread, self).__init__() self.daemon = True self.name = "YowPing%s" % self.name def run(self): while not self._stop: for i in range(0, self._interval): time.sleep(1) if self._stop: self.__logger.debug("%s - ping thread stopped" % self.name) return ping = PingIqProtocolEntity() self._layer.waitPong(ping.getId()) if not self._stop: self._layer.sendIq(ping) def stop(self): self._stop = True yowsup-2.4.48/yowsup/layers/protocol_iq/protocolentities/000077500000000000000000000000001263346463600240015ustar00rootroot00000000000000yowsup-2.4.48/yowsup/layers/protocol_iq/protocolentities/__init__.py000066400000000000000000000005401263346463600261110ustar00rootroot00000000000000from .iq import IqProtocolEntity from .iq_result import ResultIqProtocolEntity from .iq_ping import PingIqProtocolEntity from .iq_result_pong import PongResultIqProtocolEntity from .iq_error import ErrorIqProtocolEntity from .iq_push import PushIqProtocolEntity from .iq_props import PropsIqProtocolEntity from .iq_crypto import CryptoIqProtocolEntity yowsup-2.4.48/yowsup/layers/protocol_iq/protocolentities/iq.py000066400000000000000000000043311263346463600247650ustar00rootroot00000000000000from yowsup.structs import ProtocolEntity, ProtocolTreeNode class IqProtocolEntity(ProtocolEntity): ''' ''' TYPE_SET = "set" TYPE_GET = "get" TYPE_ERROR = "error" TYPE_RESULT = "result" TYPES = (TYPE_SET, TYPE_GET, TYPE_RESULT, TYPE_ERROR) def __init__(self, xmlns = None, _id = None, _type = None, to = None, _from = None): super(IqProtocolEntity, self).__init__("iq") assert _type in self.__class__.TYPES, "Iq of type %s is not implemented, can accept only (%s)" % (_type," | ".join(self.__class__.TYPES)) assert not to or not _from, "Can't set from and to at the same time" self._id = self._generateId(True) if _id is None else _id self._from = _from self._type = _type self.xmlns = xmlns self.to = to def getId(self): return self._id def getType(self): return self._type def getXmlns(self): return self.xmlns def getFrom(self, full = True): return self._from if full else self._from.split('@')[0] def getTo(self): return self.to def toProtocolTreeNode(self): attribs = { "id" : self._id, "type" : self._type } if self.xmlns: attribs["xmlns"] = self.xmlns if self.to: attribs["to"] = self.to elif self._from: attribs["from"] = self._from return self._createProtocolTreeNode(attribs, None, data = None) def __str__(self): out = "Iq:\n" out += "ID: %s\n" % self._id out += "Type: %s\n" % self._type if self.xmlns: out += "xmlns: %s\n" % self.xmlns if self.to: out += "to: %s\n" % self.to elif self._from: out += "from: %s\n" % self._from return out @staticmethod def fromProtocolTreeNode(node): return IqProtocolEntity( node.getAttributeValue("xmlns"), node.getAttributeValue("id"), node.getAttributeValue("type"), node.getAttributeValue("to"), node.getAttributeValue("from") ) yowsup-2.4.48/yowsup/layers/protocol_iq/protocolentities/iq_crypto.py000066400000000000000000000012131263346463600263610ustar00rootroot00000000000000from .iq import IqProtocolEntity from yowsup.structs import ProtocolTreeNode class CryptoIqProtocolEntity(IqProtocolEntity): def __init__(self): super(CryptoIqProtocolEntity, self).__init__("urn:xmpp:whatsapp:account", _type="get") def toProtocolTreeNode(self): node = super(CryptoIqProtocolEntity, self).toProtocolTreeNode() cryptoNode = ProtocolTreeNode("crypto", {"action": "create"}) googleNode = ProtocolTreeNode("google", data = "fe5cf90c511fb899781bbed754577098e460d048312c8b36c11c91ca4b49ca34".decode('hex')) cryptoNode.addChild(googleNode) node.addChild(cryptoNode) return nodeyowsup-2.4.48/yowsup/layers/protocol_iq/protocolentities/iq_error.py000066400000000000000000000031551263346463600262010ustar00rootroot00000000000000from yowsup.structs import ProtocolTreeNode from .iq import IqProtocolEntity class ErrorIqProtocolEntity(IqProtocolEntity): ''' ''' def __init__(self, _id, _from, code, text, backoff= 0 ): super(ErrorIqProtocolEntity, self).__init__(xmlns = None, _id = _id, _type = "error", _from = _from) self.setErrorProps(code, text, backoff) def setErrorProps(self, code, text, backoff): self.code = code self.text = text self.backoff = int(backoff) if backoff else 0 def toProtocolTreeNode(self): node = super(ErrorIqProtocolEntity, self).toProtocolTreeNode() errorNode = ProtocolTreeNode("error", {"text": self.text, "code": self.code}) if self.backoff: errorNode.setAttribute("backoff", str(self.backoff)) node.addChild(errorNode) return node def __str__(self): out = super(ErrorIqProtocolEntity, self).__str__() out += "Code: %s\n" % self.code out += "Text: %s\n" % self.text out += "Backoff: %s\n" % self.backoff return out @staticmethod def fromProtocolTreeNode(node): entity = IqProtocolEntity.fromProtocolTreeNode(node) entity.__class__ = ErrorIqProtocolEntity errorNode = node.getChild("error") entity.setErrorProps(errorNode.getAttributeValue("code"), errorNode.getAttributeValue("text"), errorNode.getAttributeValue("backoff")) return entity yowsup-2.4.48/yowsup/layers/protocol_iq/protocolentities/iq_ping.py000066400000000000000000000010531263346463600260000ustar00rootroot00000000000000from yowsup.structs import ProtocolEntity, ProtocolTreeNode from .iq import IqProtocolEntity class PingIqProtocolEntity(IqProtocolEntity): ''' Receive Send ''' def __init__(self, _from = None, to = None, _id = None): super(PingIqProtocolEntity, self).__init__("urn:xmpp:ping" if _from else "w:p", _id = _id, _type = "get", _from = _from, to = to) yowsup-2.4.48/yowsup/layers/protocol_iq/protocolentities/iq_props.py000066400000000000000000000006101263346463600262040ustar00rootroot00000000000000from .iq import IqProtocolEntity from yowsup.structs import ProtocolTreeNode class PropsIqProtocolEntity(IqProtocolEntity): def __init__(self): super(PropsIqProtocolEntity, self).__init__("w", _type="get") def toProtocolTreeNode(self): node = super(PropsIqProtocolEntity, self).toProtocolTreeNode() node.addChild(ProtocolTreeNode("props")) return nodeyowsup-2.4.48/yowsup/layers/protocol_iq/protocolentities/iq_push.py000066400000000000000000000006331263346463600260250ustar00rootroot00000000000000from .iq import IqProtocolEntity from yowsup.structs import ProtocolTreeNode class PushIqProtocolEntity(IqProtocolEntity): def __init__(self): super(PushIqProtocolEntity, self).__init__("urn:xmpp:whatsapp:push", _type="get") def toProtocolTreeNode(self): node = super(PushIqProtocolEntity, self).toProtocolTreeNode() node.addChild(ProtocolTreeNode("config")) return nodeyowsup-2.4.48/yowsup/layers/protocol_iq/protocolentities/iq_result.py000066400000000000000000000006411263346463600263630ustar00rootroot00000000000000from yowsup.structs import ProtocolEntity, ProtocolTreeNode from .iq import IqProtocolEntity class ResultIqProtocolEntity(IqProtocolEntity): ''' ''' def __init__(self, xmlns = None, _id = None, to = None, _from = None): super(ResultIqProtocolEntity, self).__init__(xmlns = xmlns, _id = _id, _type = "result", to = to, _from = _from) yowsup-2.4.48/yowsup/layers/protocol_iq/protocolentities/iq_result_pong.py000066400000000000000000000006041263346463600274050ustar00rootroot00000000000000from yowsup.structs import ProtocolEntity, ProtocolTreeNode from .iq_result import ResultIqProtocolEntity class PongResultIqProtocolEntity(ResultIqProtocolEntity): ''' ''' def __init__(self, to, _id = None): super(PongResultIqProtocolEntity, self).__init__("w:p", _id = _id, to = to) yowsup-2.4.48/yowsup/layers/protocol_iq/protocolentities/test_iq.py000066400000000000000000000006711263346463600260270ustar00rootroot00000000000000from yowsup.layers.protocol_iq.protocolentities.iq import IqProtocolEntity from yowsup.structs import ProtocolTreeNode from yowsup.structs.protocolentity import ProtocolEntityTest import unittest class IqProtocolEntityTest(unittest.TestCase, ProtocolEntityTest): def setUp(self): self.ProtocolEntity = IqProtocolEntity self.node = ProtocolTreeNode("iq", {"id": "test_id", "type": "get", "xmlns": "iq_xmlns"}, None, None)yowsup-2.4.48/yowsup/layers/protocol_iq/protocolentities/test_iq_error.py000066400000000000000000000007711263346463600272410ustar00rootroot00000000000000from yowsup.layers.protocol_iq.protocolentities.test_iq import IqProtocolEntityTest from yowsup.layers.protocol_iq.protocolentities import ErrorIqProtocolEntity from yowsup.structs import ProtocolTreeNode class ErrorIqProtocolEntityTest(IqProtocolEntityTest): def setUp(self): super(ErrorIqProtocolEntityTest, self).setUp() self.ProtocolEntity = ErrorIqProtocolEntity errorNode = ProtocolTreeNode("error", {"code": "123", "text": "abc"}) self.node.addChild(errorNode) yowsup-2.4.48/yowsup/layers/protocol_iq/protocolentities/test_iq_result.py000066400000000000000000000004111263346463600274150ustar00rootroot00000000000000from yowsup.layers.protocol_iq.protocolentities.test_iq import IqProtocolEntityTest class ResultIqProtocolEntityTest(IqProtocolEntityTest): def setUp(self): super(ResultIqProtocolEntityTest, self).setUp() self.node.setAttribute("type", "result")yowsup-2.4.48/yowsup/layers/protocol_media/000077500000000000000000000000001263346463600210415ustar00rootroot00000000000000yowsup-2.4.48/yowsup/layers/protocol_media/__init__.py000066400000000000000000000000521263346463600231470ustar00rootroot00000000000000from .layer import YowMediaProtocolLayer yowsup-2.4.48/yowsup/layers/protocol_media/layer.py000066400000000000000000000066001263346463600225310ustar00rootroot00000000000000from yowsup.layers import YowLayer, YowLayerEvent, YowProtocolLayer from .protocolentities import ImageDownloadableMediaMessageProtocolEntity from .protocolentities import AudioDownloadableMediaMessageProtocolEntity from .protocolentities import VideoDownloadableMediaMessageProtocolEntity from .protocolentities import LocationMediaMessageProtocolEntity from .protocolentities import VCardMediaMessageProtocolEntity from .protocolentities import RequestUploadIqProtocolEntity, ResultRequestUploadIqProtocolEntity from yowsup.layers.protocol_iq.protocolentities import IqProtocolEntity, ErrorIqProtocolEntity class YowMediaProtocolLayer(YowProtocolLayer): # EVENT_REQUEST_UPLOAD = "org.openwhatsapp.org.yowsup.event.protocol_media.request_upload" def __init__(self): handleMap = { "message": (self.recvMessageStanza, self.sendMessageEntity), "iq": (self.recvIq, self.sendIq) } super(YowMediaProtocolLayer, self).__init__(handleMap) def __str__(self): return "Media Layer" # def onEvent(self, yowLayerEvent): # if yowLayerEvent.getArg(self.__class__.EVENT_REQUEST_UPLOAD): # fpath = yowLayerEvent.getArg("file") # _type = yowLayerEvent.getArg("type") # assert fpath and _type, "Must specify 'file' and 'type' in EVENT_REQUEST_UPLOAD args" # entity = RequestUploadIqProtocolEntity(_type, filePath=fpath) # self._sendIq(entity, self.onRequestUploadSuccess, self.onRequestUploadError) def sendMessageEntity(self, entity): if entity.getType() == "media": self.entityToLower(entity) def recvMessageStanza(self, node): if node.getAttributeValue("type") == "media": mediaNode = node.getChild("media") if mediaNode.getAttributeValue("type") == "image": entity = ImageDownloadableMediaMessageProtocolEntity.fromProtocolTreeNode(node) self.toUpper(entity) elif mediaNode.getAttributeValue("type") == "audio": entity = AudioDownloadableMediaMessageProtocolEntity.fromProtocolTreeNode(node) self.toUpper(entity) elif mediaNode.getAttributeValue("type") == "video": entity = VideoDownloadableMediaMessageProtocolEntity.fromProtocolTreeNode(node) self.toUpper(entity) elif mediaNode.getAttributeValue("type") == "location": entity = LocationMediaMessageProtocolEntity.fromProtocolTreeNode(node) self.toUpper(entity) elif mediaNode.getAttributeValue("type") == "vcard": entity = VCardMediaMessageProtocolEntity.fromProtocolTreeNode(node) self.toUpper(entity) def sendIq(self, entity): """ :type entity: IqProtocolEntity """ if entity.getType() == IqProtocolEntity.TYPE_SET and entity.getXmlns() == "w:m": #media upload! self._sendIq(entity, self.onRequestUploadSuccess, self.onRequestUploadError) def recvIq(self, node): """ :type node: ProtocolTreeNode """ def onRequestUploadSuccess(self, resultNode, requestUploadEntity): self.toUpper(ResultRequestUploadIqProtocolEntity.fromProtocolTreeNode(resultNode)) def onRequestUploadError(self, errorNode, requestUploadEntity): self.toUpper(ErrorIqProtocolEntity.fromProtocolTreeNode(errorNode)) yowsup-2.4.48/yowsup/layers/protocol_media/mediadownloader.py000066400000000000000000000040131263346463600245470ustar00rootroot00000000000000import sys, tempfile, logging logger = logging.getLogger(__name__) if sys.version_info >= (3, 0): from urllib.request import urlopen from urllib.parse import urlencode else: from urllib2 import urlopen from urllib import urlencode class MediaDownloader: def __init__(self, successClbk = None, errorClbk = None, progressCallback = None): self.successCallback = successClbk self.errorCallback = errorClbk self.progressCallback = progressCallback def download(self, url = ""): try: if not url: if self.url: url = "https://" if self.port == 443 else "http://" url = url + self.url url = url + "?" + urlencode(self.params) logger.debug("URL is %s" % url) else: raise Exception("No url specified for fetching") u = urlopen(url) path = tempfile.mkstemp()[1] with open(path, "wb") as f: meta = u.info() if sys.version_info >= (3, 0): fileSize = int(u.getheader("Content-Length")) else: fileSize = int(meta.getheaders("Content-Length")[0]) fileSizeDl = 0 blockSz = 8192 lastEmit = 0 while True: buf = u.read(blockSz) if not buf: break fileSizeDl += len(buf) f.write(buf) status = (fileSizeDl * 100 / fileSize) if self.progressCallback and lastEmit != status: self.progressCallback(int(status)) lastEmit = status; if self.successCallback: self.successCallback(path) except: logger.exception("Error occured at transfer") if self.errorCallback: self.errorCallback();yowsup-2.4.48/yowsup/layers/protocol_media/mediauploader.py000066400000000000000000000120101263346463600242200ustar00rootroot00000000000000from yowsup.common.http.warequest import WARequest from yowsup.common.http.waresponseparser import JSONResponseParser import socket, ssl, mimetypes, os, hashlib, sys from time import sleep import threading import logging logger = logging.getLogger(__name__) class MediaUploader(WARequest, threading.Thread): def __init__(self, jid, accountJid, sourcePath, uploadUrl, resumeOffset = 0, successClbk = None, errorClbk = None, progressCallback = None, async = True): WARequest.__init__(self) self.async = async self.jid = jid self.accountJid = accountJid self.sourcePath = sourcePath self.uploadUrl = uploadUrl self.resumeOffset = resumeOffset self.successCallback = successClbk self.errorCallback = errorClbk self.progressCallback = progressCallback self.pvars = ["name", "type", "size", "url", "error", "mimetype", "filehash", "width", "height"] self.setParser(JSONResponseParser()) self.sock = socket.socket() def start(self): if self.async: threading.Thread.__init__(self) super(MediaUploader, self).start() else: self.run() def run(self): sourcePath = self.sourcePath uploadUrl = self.uploadUrl _host = uploadUrl.replace("https://","") self.url = _host[:_host.index('/')] try: filename = os.path.basename(sourcePath) filetype = mimetypes.guess_type(filename)[0] filesize = os.path.getsize(sourcePath) self.sock.connect((self.url, self.port)) ssl_sock = ssl.wrap_socket(self.sock) m = hashlib.md5() m.update(filename.encode()) crypto = m.hexdigest() + os.path.splitext(filename)[1] boundary = "zzXXzzYYzzXXzzQQ"#"-------" + m.hexdigest() #"zzXXzzYYzzXXzzQQ" contentLength = 0 hBAOS = "--" + boundary + "\r\n" hBAOS += "Content-Disposition: form-data; name=\"to\"\r\n\r\n" hBAOS += self.jid + "\r\n" hBAOS += "--" + boundary + "\r\n" hBAOS += "Content-Disposition: form-data; name=\"from\"\r\n\r\n" hBAOS += self.accountJid.replace("@whatsapp.net","") + "\r\n" hBAOS += "--" + boundary + "\r\n" hBAOS += "Content-Disposition: form-data; name=\"file\"; filename=\"" + crypto + "\"\r\n" hBAOS += "Content-Type: " + filetype + "\r\n\r\n" fBAOS = "\r\n--" + boundary + "--\r\n" contentLength += len(hBAOS) contentLength += len(fBAOS) contentLength += filesize POST = "POST %s\r\n" % uploadUrl POST += "Content-Type: multipart/form-data; boundary=" + boundary + "\r\n" POST += "Host: %s\r\n" % self.url POST += "User-Agent: %s\r\n" % self.getUserAgent() POST += "Content-Length: " + str(contentLength) + "\r\n\r\n" ssl_sock.write(bytearray(POST.encode())) ssl_sock.write(bytearray(hBAOS.encode())) totalsent = 0 buf = 1024 f = open(sourcePath, 'rb') stream = f.read() f.close() status = 0 lastEmit = 0 while totalsent < int(filesize): ssl_sock.write(stream[:buf]) status = totalsent * 100 / filesize if lastEmit!=status and status!=100 and filesize>12288: if self.progressCallback: self.progressCallback(self.sourcePath, self.jid, uploadUrl, int(status)) lastEmit = status stream = stream[buf:] totalsent = totalsent + buf ssl_sock.write(bytearray(fBAOS.encode())) sleep(1) data = ssl_sock.recv(8192) data += ssl_sock.recv(8192) data += ssl_sock.recv(8192) data += ssl_sock.recv(8192) data += ssl_sock.recv(8192) data += ssl_sock.recv(8192) data += ssl_sock.recv(8192) if self.progressCallback: self.progressCallback(self.sourcePath, self.jid, uploadUrl, 100) lines = data.decode().splitlines() result = None for l in lines: if l.startswith("{"): result = self.parser.parse(l, self.pvars) break if not result: raise Exception("json data not found") if result["url"] is not None: if self.successCallback: self.successCallback(sourcePath, self.jid, result["url"]) else: logger.exception("uploadUrl: %s, result of uploading media has no url" % uploadUrl) if self.errorCallback: self.errorCallback(sourcePath, self.jid, uploadUrl) except: logger.exception("Error occured at transfer %s"%sys.exc_info()[1]) if self.errorCallback: self.errorCallback(sourcePath, self.jid, uploadUrl) yowsup-2.4.48/yowsup/layers/protocol_media/picture.py000066400000000000000000000020731263346463600230700ustar00rootroot00000000000000from yowsup.layers import YowLayer from yowsup import ProtocolTreeNode from .mediadownloader import MediaDownloader import shutil, os, logging logger = logging.getLogger(__name__) class YowMediaPictureLayer(YowLayer): def send(self, data): self.toLower(data) def receive(self, node): if ProtocolTreeNode.tagEquals(node, "message") and node.getAttributeValue("type") == "media": self.downloadMedia(node.getChild("media").getAttributeValue("url")) else: self.toUpper(node) def downloadMedia(self, url): logger.debug("Downloading %s" % url) downloader = MediaDownloader(self.onSuccess, self.onError, self.onProgress) downloader.download(url) def onError(self): logger.error("Error download file") def onSuccess(self, path): outPath = "/tmp/yowfiles/%s.jpg" % os.path.basename(path) shutil.copyfile(path, outPath) logger.debug("Picture downloaded to %s" % outPath) def onProgress(self, progress): logger.debug("Download progress %s" % progress) yowsup-2.4.48/yowsup/layers/protocol_media/protocolentities/000077500000000000000000000000001263346463600244475ustar00rootroot00000000000000yowsup-2.4.48/yowsup/layers/protocol_media/protocolentities/__init__.py000066400000000000000000000012401263346463600265550ustar00rootroot00000000000000from .message_media import MediaMessageProtocolEntity from .message_media_downloadable import DownloadableMediaMessageProtocolEntity from .message_media_downloadable_image import ImageDownloadableMediaMessageProtocolEntity from .message_media_downloadable_audio import AudioDownloadableMediaMessageProtocolEntity from .message_media_downloadable_video import VideoDownloadableMediaMessageProtocolEntity from .message_media_location import LocationMediaMessageProtocolEntity from .message_media_vcard import VCardMediaMessageProtocolEntity from .iq_requestupload import RequestUploadIqProtocolEntity from .iq_requestupload_result import ResultRequestUploadIqProtocolEntity yowsup-2.4.48/yowsup/layers/protocol_media/protocolentities/iq_requestupload.py000066400000000000000000000061121263346463600304070ustar00rootroot00000000000000from yowsup.layers.protocol_iq.protocolentities import IqProtocolEntity from yowsup.structs import ProtocolTreeNode import hashlib import base64 import os from yowsup.common.tools import WATools class RequestUploadIqProtocolEntity(IqProtocolEntity): ''' ''' MEDIA_TYPE_IMAGE = "image" MEDIA_TYPE_VIDEO = "video" MEDIA_TYPE_AUDIO = "audio" XMLNS = "w:m" TYPES_MEDIA = (MEDIA_TYPE_AUDIO, MEDIA_TYPE_IMAGE, MEDIA_TYPE_VIDEO) def __init__(self, mediaType, b64Hash = None, size = None, origHash = None, filePath = None ): super(RequestUploadIqProtocolEntity, self).__init__("w:m", _type = "set", to = "s.whatsapp.net") assert (b64Hash and size) or filePath, "Either specify hash and size, or specify filepath and let me generate the rest" if filePath: assert os.path.exists(filePath), "Either specified path does not exist, or yowsup doesn't have permission to read: %s" % filePath b64Hash = self.__class__.getFileHashForUpload(filePath) size = os.path.getsize(filePath) self.setRequestArguments(mediaType, b64Hash, size, origHash) def setRequestArguments(self, mediaType, b64Hash, size, origHash = None): assert mediaType in self.__class__.TYPES_MEDIA, "Expected media type to be in %s, got %s" % (self.__class__.TYPES_MEDIA, mediaType) self.mediaType = mediaType self.b64Hash = b64Hash self.size = int(size) self.origHash = origHash @staticmethod def getFileHashForUpload(filePath): return WATools.getFileHashForUpload(filePath) def __str__(self): out = super(RequestUploadIqProtocolEntity, self).__str__() out += "Media Type: %s\n" % self.mediaType out += "B64Hash: %s\n" % self.b64Hash out += "Size: %s\n" % self.size if self.origHash: out += "OrigHash: %s\n" % self.origHash return out def toProtocolTreeNode(self): node = super(RequestUploadIqProtocolEntity, self).toProtocolTreeNode() attribs = { "hash": self.b64Hash, "type": self.mediaType, "size": str(self.size) } if self.origHash: attribs["orighash"] = self.origHash mediaNode = ProtocolTreeNode("media", attribs) node.addChild(mediaNode) return node @staticmethod def fromProtocolTreeNode(node): assert node.getAttributeValue("type") == "set", "Expected set as iq type in request upload, got %s" % node.getAttributeValue("type") entity = IqProtocolEntity.fromProtocolTreeNode(node) entity.__class__ = RequestUploadIqProtocolEntity mediaNode = node.getChild("media") entity.setRequestArguments( mediaNode.getAttributeValue("type"), mediaNode.getAttributeValue("hash"), mediaNode.getAttributeValue("size"), mediaNode.getAttributeValue("orighash") ) return entityyowsup-2.4.48/yowsup/layers/protocol_media/protocolentities/iq_requestupload_result.py000066400000000000000000000041611263346463600320070ustar00rootroot00000000000000from yowsup.layers.protocol_iq.protocolentities import ResultIqProtocolEntity from yowsup.structs import ProtocolTreeNode class ResultRequestUploadIqProtocolEntity(ResultIqProtocolEntity): def __init__(self, _id, url, ip = None, resumeOffset = 0, duplicate = False): super(ResultRequestUploadIqProtocolEntity, self).__init__(_id = _id, _from = "s.whatsapp.net") self.setUploadProps(url, ip, resumeOffset, duplicate) def setUploadProps(self, url ,ip = None, resumeOffset = 0, duplicate = False): self.url = url self.ip = ip self.resumeOffset = resumeOffset or 0 self.duplicate = duplicate def isDuplicate(self): return self.duplicate def getUrl(self): return self.url def getResumeOffset(self): return self.resumeOffset def getIp(self): return self.ip def __str__(self): out = super(ResultRequestUploadIqProtocolEntity, self).__str__() out += "URL: %s\n" % self.url if self.ip: out += "IP: %s\n" % self.ip return out def toProtocolTreeNode(self): node = super(ResultRequestUploadIqProtocolEntity, self).toProtocolTreeNode() if not self.isDuplicate(): mediaNode = ProtocolTreeNode("media", {"url": self.url}) if self.ip: mediaNode["ip"] = self.ip if self.resumeOffset: mediaNode["resume"] = str(self.resumeOffset) else: mediaNode = ProtocolTreeNode("duplicate", {"url": self.url}) node.addChild(mediaNode) return node @staticmethod def fromProtocolTreeNode(node): entity= ResultIqProtocolEntity.fromProtocolTreeNode(node) entity.__class__ = ResultRequestUploadIqProtocolEntity mediaNode = node.getChild("media") if mediaNode: entity.setUploadProps(mediaNode["url"], mediaNode["ip"], mediaNode["resume"]) else: duplicateNode = node.getChild("duplicate") if duplicateNode: entity.setUploadProps(duplicateNode["url"], duplicateNode["ip"], duplicate = True) return entity yowsup-2.4.48/yowsup/layers/protocol_media/protocolentities/message_media.py000066400000000000000000000163501263346463600276110ustar00rootroot00000000000000from yowsup.structs import ProtocolEntity, ProtocolTreeNode from yowsup.layers.protocol_messages.protocolentities import MessageProtocolEntity class MediaMessageProtocolEntity(MessageProtocolEntity): ''' {{THUMBNAIL_RAWDATA (JPEG?)}} ''' ''' {{THUMBNAIL_RAWDATA}} {{THUMBNAIL_RAWDATA}} BEGIN:VCARD VERSION:3.0 N:Yasser;Hany;;; FN:Hany Yasser PHOTO;BASE64:/9j/4AAQSkZJRgABAQEASABIAAD/4QBYRXhpZgAATU0AKgAAAAgAAgESAAMAAAABAAEAAIdpAAQAAAABAAAAJgAAAAAAA6ABAAMAAAABAAEAAKACAAQAAAABAAAAQKADAAQAAAABAAAAQAAAAAD/7QA4UGhvdG9zaG9wIDMuMAA4QklNBAQAAAAAAAA4QklNBCUAAAAAABDUHYzZjwCyBOmACZjs+EJ+/8AAEQgAQABAAwEiAAIRAQMRAf/EAB8AAAEFAQEBAQEBAAAAAAAAAAABAgMEBQYHCAkKC//EALUQAAIBAwMCBAMFBQQEAAABfQECAwAEEQUSITFBBhNRYQcicRQygZGhCCNCscEVUtHwJDNicoIJChYXGBkaJSYnKCkqNDU2Nzg5OkNERUZHSElKU1RVVldYWVpjZGVmZ2hpanN0dXZ3eHl6g4SFhoeIiYqSk5SVlpeYmZqio6Slpqeoqaqys7S1tre4ubrCw8TFxsfIycrS09TV1tfY2drh4uPk5ebn6Onq8fLz9PX29/j5+v/EAB8BAAMBAQEBAQEBAQEAAAAAAAABAgMEBQYHCAkKC//EALURAAIBAgQEAwQHBQQEAAECdwABAgMRBAUhMQYSQVEHYXETIjKBCBRCkaGxwQkjM1LwFWJy0QoWJDThJfEXGBkaJicoKSo1Njc4OTpDREVGR0hJSlNUVVZXWFlaY2RlZmdoaWpzdHV2d3h5eoKDhIWGh4iJipKTlJWWl5iZmqKjpKWmp6ipqrKztLW2t7i5usLDxMXGx8jJytLT1NXW19jZ2uLj5OXm5+jp6vLz9PX29/j5+v/bAEMABgYGBgYGCgYGCg4KCgoOEg4ODg4SFxISEhISFxwXFxcXFxccHBwcHBwcHCIiIiIiIicnJycnLCwsLCwsLCwsLP/bAEMBBwcHCwoLEwoKEy4fGh8uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLv/dAAQABP/aAAwDAQACEQMRAD8A83lPGaqzn/iXgnqZB/WpWbKjNV7kgWC5/wCen9DXix3PoGtCreFJG3OcbVFZmx2XL8A9PoOa9u0b4TDVLH+0tavDZMyBkiUDKqRkGQsQBkc49O9ebeJ9Am8PXX2bzkuYJAWhmjOVcA4Pc4I7jNelCm1BOx5M6kXNpM5VnX77EEn17D6Vt6aVaNtnABxitnwn4DvPEUS3lxIIoH5HG5yPUL059zVTxLoUPhDUYGs7gzRO+yXOCB6A7eOlTUSa5U9SqbcXzNaGdenbYxhevymsPc0rGVyDg9O1a96d9uPT5RWK/C/d6ck0qK0HXd5H/9Dy2U9B2rpPCNgmp6xp9vKgeNJWmdSMgrGN3P44qponhvVvE9ybLSYw8iKXYs21VHTk+56V7B4T8F3nhSKS91gx/anHlxqjbgqty2TgcnA/KvNo0m2n0PYr1oxi431F8R3d7Jef6MbaZ964huDhSCBlsZ5OfXp2rwzxZdyS6rLC0C26xuRhCNrkHbvAHTpivUvEdrdiaWZ4DIXXarrwVJ/oQce9eZXfg3WLgNc22ySNSIzufawc9Bz6116uTucbUYwSRreFb23sLCG6v72RraFjGbVOQwOeo78HjvTtavfDdvpyRWNo4LyIx3sSTg5xz3Hfr9a4n7Bd6bfW9orxSSSyBAqncpYnGDxx161614T8JXet3/8AbXidRHZaVuxDu3FmXLMWPp+XtxQqTk9Be2UYnj94ymFB64zWSxDnJ5UenGas3bmaWRkG1Gdii+iknA/AVQKsoyRwO1ONJxVmTKrGTuj/0e3+D9iLfR5tRZcSXUu0H/ZjxjH4k165fQG4tXRADJ/Dnpn3ri/BVt9h8OaXCMf6lSw772BY/wDoVdm90qSCPHJ6VUI2gkE581RyPNdQQJKVkj3smCpYZYY6Ae+elcT43e78M+F43twI57u4+Y4B25BYgA8cYHNe3ytbtK7lFLttwcc8nHX8K8V+OF5EdK0+BOrXJP4BD/jQkrlTk7aHjPgmztp/E8FxetsgtUluZH7hYULZ+oOK7XQEsNN+G2ra/bNMLu8mNmC8hI2uwwMdCdpJJOTnPSvOdNuPI0/V5lOG+wOg/wC2ksSH9Ca7DXwNH8A6Fpak7rxpL6X6kAL+QJrVLTQwe5545Qc9u1Z104cbe1Pkl3fSqW4szj8qzbLSP//S+ghGIfJjAA2gDHpgY49qZIxN2T2Rf1NULK5XVL66u4+YLaQ20ZH8Tp/rD+BO38DUyzlndWHclT6r2rVkR3KV7eLb3cELIx8zI3DGAM/mcdT6DmvBPjZdfvNLj6bvMfHoOAP0r6JMqujxnoyH9P8A9dfK/wAZrozeILeFOTHbDA9NzMSfyAqLblyZ57arv0vUmzjbbZ/8ixj+ddd8QbxpW0W0PHk6ZASB0G8Fq86ecx2c8Y6SIqn6bg39K6TxS0pv7dpTnNjabfZREuBWqfumdtTmpG2rmqUT/vDnvU07YGKpx4EoySvuKyZZ/9k= BDAY;value=date:1989-01-05 ORG:Vodafone Egypt; item1.EMAIL;type=INTERNET:hanyyasser@hotmail.com item1.X-ABLabel:INTERNET item2.EMAIL;type=INTERNET:hanybotbot@hotmail.com item2.X-ABLabel:INTERNET item3.ADR;type=HOME:;;Heliopolis;Cairo;Al Qahirah;;Egypt item4.ADR;type=HOME:;;;cairo;;;Egypt item5.URL:http://www.facebook.com/profile.php?id=626850952 item5.X-ABLabel:_$!!$_ X-FACEBOOK:hany.yasser1 END:VCARD ''' MEDIA_TYPE_IMAGE = "image" MEDIA_TYPE_VIDEO = "video" MEDIA_TYPE_AUDIO = "audio" MEDIA_TYPE_VCARD = "vcard" MEDIA_TYPE_LOCATION = "location" TYPES_MEDIA = (MEDIA_TYPE_AUDIO, MEDIA_TYPE_IMAGE, MEDIA_TYPE_VIDEO, MEDIA_TYPE_VCARD, MEDIA_TYPE_LOCATION) def __init__(self, mediaType, _id = None, _from = None, to = None, notify = None, timestamp = None, participant = None, preview = None, offline = None, retry = None): super(MediaMessageProtocolEntity, self).__init__("media", _id, _from, to, notify, timestamp, participant, offline, retry) self.setMediaType(mediaType) self.setPreview(preview) def __str__(self): out = super(MediaMessageProtocolEntity, self).__str__() out += "Media Type: %s\n" % self.mediaType out += "Has Preview: %s\n" % (self.preview is not None) return out def setPreview(self, preview): self.preview = preview def getPreview(self): return self.preview def setMediaType(self, mediaType): self.mediaType = mediaType def getMediaType(self): return self.mediaType def toProtocolTreeNode(self): node = super(MediaMessageProtocolEntity, self).toProtocolTreeNode() mediaNode = ProtocolTreeNode("media", {"type": self.mediaType}, None, None) node.addChild(mediaNode) if self.preview: mediaNode.setData(self.preview) return node @staticmethod def fromProtocolTreeNode(node): entity = MessageProtocolEntity.fromProtocolTreeNode(node) entity.__class__ = MediaMessageProtocolEntity entity.setMediaType(node.getChild("media").getAttributeValue("type")) preview = node.getChild("media").getData() entity.setPreview(preview) return entity yowsup-2.4.48/yowsup/layers/protocol_media/protocolentities/message_media_downloadable.py000066400000000000000000000071701263346463600323240ustar00rootroot00000000000000from .message_media import MediaMessageProtocolEntity from yowsup.common.tools import WATools import mimetypes import os class DownloadableMediaMessageProtocolEntity(MediaMessageProtocolEntity): ''' {{THUMBNAIL_RAWDATA (JPEG?)}} ''' def __init__(self, mediaType, mimeType, fileHash, url, ip, size, fileName, _id = None, _from = None, to = None, notify = None, timestamp = None, participant = None, preview = None, offline = None, retry = None): super(DownloadableMediaMessageProtocolEntity, self).__init__(mediaType, _id, _from, to, notify, timestamp, participant, preview, offline, retry) self.setDownloadableMediaProps(mimeType, fileHash, url, ip, size, fileName) def __str__(self): out = super(DownloadableMediaMessageProtocolEntity, self).__str__() out += "MimeType: %s\n" % self.mimeType out += "File Hash: %s\n" % self.fileHash out += "URL: %s\n" % self.url out += "IP: %s\n" % self.ip out += "File Size: %s\n" % self.size out += "File name: %s\n" % self.fileName return out def getMediaSize(self): return self.size def getMediaUrl(self): return self.url def getMimeType(self): return self.mimeType def setDownloadableMediaProps(self, mimeType, fileHash, url, ip, size, fileName): self.mimeType = mimeType self.fileHash = fileHash self.url = url self.ip = ip self.size = int(size) self.fileName = fileName def toProtocolTreeNode(self): node = super(DownloadableMediaMessageProtocolEntity, self).toProtocolTreeNode() mediaNode = node.getChild("media") mediaNode.setAttribute("mimetype", self.mimeType) mediaNode.setAttribute("filehash", self.fileHash) mediaNode.setAttribute("url", self.url) if self.ip: mediaNode.setAttribute("ip", self.ip) mediaNode.setAttribute("size", str(self.size)) mediaNode.setAttribute("file", self.fileName) return node @staticmethod def fromProtocolTreeNode(node): entity = MediaMessageProtocolEntity.fromProtocolTreeNode(node) entity.__class__ = DownloadableMediaMessageProtocolEntity mediaNode = node.getChild("media") entity.setDownloadableMediaProps( mediaNode.getAttributeValue("mimetype"), mediaNode.getAttributeValue("filehash"), mediaNode.getAttributeValue("url"), mediaNode.getAttributeValue("ip"), mediaNode.getAttributeValue("size"), mediaNode.getAttributeValue("file") ) return entity @staticmethod def fromFilePath(fpath, url, mediaType, ip, to, mimeType = None, preview = None, filehash = None, filesize = None): mimeType = mimeType or mimetypes.guess_type(fpath)[0] filehash = filehash or WATools.getFileHashForUpload(fpath) size = filesize or os.path.getsize(fpath) fileName = os.path.basename(fpath) return DownloadableMediaMessageProtocolEntity(mediaType, mimeType, filehash, url, ip, size, fileName, to = to, preview = preview) yowsup-2.4.48/yowsup/layers/protocol_media/protocolentities/message_media_downloadable_audio.py000066400000000000000000000102051263346463600334760ustar00rootroot00000000000000from yowsup.structs import ProtocolEntity, ProtocolTreeNode from .message_media_downloadable import DownloadableMediaMessageProtocolEntity class AudioDownloadableMediaMessageProtocolEntity(DownloadableMediaMessageProtocolEntity): ''' {{THUMBNAIL_RAWDATA (JPEG?)}} ''' def __init__(self, mimeType, fileHash, url, ip, size, fileName, abitrate, acodec, asampfreq, duration, encoding, origin, seconds, _id = None, _from = None, to = None, notify = None, timestamp = None, participant = None, preview = None, offline = None, retry = None): super(AudioDownloadableMediaMessageProtocolEntity, self).__init__("audio", mimeType, fileHash, url, ip, size, fileName, _id, _from, to, notify, timestamp, participant, preview, offline, retry) self.setAudioProps(abitrate, acodec, asampfreq, duration, encoding, origin, seconds) def __str__(self): out = super(AudioDownloadableMediaMessageProtocolEntity, self).__str__() out += "Bitrate: %s\n" % self.abitrate out += "Codec: %s\n" % self.acodec out += "Duration: %s\n" % self.duration out += "Encoding: %s\n" % self.encoding out += "Origin: %s\n" % self.origin out += "Sampling freq.: %s\n" % self.asampfreq return out def setAudioProps(self, abitrate = None, acodec = None, asampfreq = None, duration = None, encoding = None, origin = None, seconds = None): self.abitrate = abitrate self.acodec = acodec self.asampfreq = asampfreq self.duration = duration self.encoding = encoding self.origin = origin self.seconds = seconds def toProtocolTreeNode(self): node = super(AudioDownloadableMediaMessageProtocolEntity, self).toProtocolTreeNode() mediaNode = node.getChild("media") if self.abitrate: mediaNode.setAttribute("abitrate", self.abitrate) if self.acodec: mediaNode.setAttribute("acodec", self.acodec) if self.asampfreq: mediaNode.setAttribute("asampfreq", self.asampfreq) if self.duration: mediaNode.setAttribute("duration", self.duration) if self.encoding: mediaNode.setAttribute("encoding", self.encoding) if self.origin: mediaNode.setAttribute("origin", self.origin) if self.seconds: mediaNode.setAttribute("seconds", self.seconds) return node @staticmethod def fromProtocolTreeNode(node): entity = DownloadableMediaMessageProtocolEntity.fromProtocolTreeNode(node) entity.__class__ = AudioDownloadableMediaMessageProtocolEntity mediaNode = node.getChild("media") entity.setAudioProps( mediaNode.getAttributeValue("abitrate"), mediaNode.getAttributeValue("acodec"), mediaNode.getAttributeValue("asampfreq"), mediaNode.getAttributeValue("duration"), mediaNode.getAttributeValue("encoding"), mediaNode.getAttributeValue("origin"), mediaNode.getAttributeValue("seconds"), ) return entity @staticmethod def fromFilePath(fpath, url, ip, to, mimeType = None, preview = None, filehash = None, filesize = None): entity = DownloadableMediaMessageProtocolEntity.fromFilePath(fpath, url, DownloadableMediaMessageProtocolEntity.MEDIA_TYPE_AUDIO, ip, to, mimeType, preview) entity.__class__ = AudioDownloadableMediaMessageProtocolEntity entity.setAudioProps() return entity yowsup-2.4.48/yowsup/layers/protocol_media/protocolentities/message_media_downloadable_image.py000066400000000000000000000072641263346463600334720ustar00rootroot00000000000000from yowsup.structs import ProtocolEntity, ProtocolTreeNode from .message_media_downloadable import DownloadableMediaMessageProtocolEntity from yowsup.common.tools import ImageTools class ImageDownloadableMediaMessageProtocolEntity(DownloadableMediaMessageProtocolEntity): ''' {{THUMBNAIL_RAWDATA (JPEG?)}} ''' def __init__(self, mimeType, fileHash, url, ip, size, fileName, encoding, width, height, caption = None, _id = None, _from = None, to = None, notify = None, timestamp = None, participant = None, preview = None, offline = None, retry = None): super(ImageDownloadableMediaMessageProtocolEntity, self).__init__("image", mimeType, fileHash, url, ip, size, fileName, _id, _from, to, notify, timestamp, participant, preview, offline, retry) self.setImageProps(encoding, width, height, caption) def __str__(self): out = super(ImageDownloadableMediaMessageProtocolEntity, self).__str__() out += "Encoding: %s\n" % self.encoding out += "Width: %s\n" % self.width out += "Height: %s\n" % self.height if self.caption: out += "Caption: %s\n" % self.caption return out def setImageProps(self, encoding, width, height, caption): self.encoding = encoding self.width = int(width) self.height = int(height) self.caption = caption def getCaption(self): return self.caption def toProtocolTreeNode(self): node = super(ImageDownloadableMediaMessageProtocolEntity, self).toProtocolTreeNode() mediaNode = node.getChild("media") mediaNode.setAttribute("encoding", self.encoding) mediaNode.setAttribute("width", str(self.width)) mediaNode.setAttribute("height", str(self.height)) if self.caption: mediaNode.setAttribute("caption", self.caption) return node @staticmethod def fromProtocolTreeNode(node): entity = DownloadableMediaMessageProtocolEntity.fromProtocolTreeNode(node) entity.__class__ = ImageDownloadableMediaMessageProtocolEntity mediaNode = node.getChild("media") entity.setImageProps( mediaNode.getAttributeValue("encoding"), mediaNode.getAttributeValue("width"), mediaNode.getAttributeValue("height"), mediaNode.getAttributeValue("caption"), ) return entity @staticmethod def fromFilePath(path, url, ip, to, mimeType = None, caption = None, dimensions = None): preview = ImageTools.generatePreviewFromImage(path) entity = DownloadableMediaMessageProtocolEntity.fromFilePath(path, url, DownloadableMediaMessageProtocolEntity.MEDIA_TYPE_IMAGE, ip, to, mimeType, preview) entity.__class__ = ImageDownloadableMediaMessageProtocolEntity if not dimensions: dimensions = ImageTools.getImageDimensions(path) assert dimensions, "Could not determine image dimensions" width, height = dimensions entity.setImageProps("raw", width, height, caption) return entity yowsup-2.4.48/yowsup/layers/protocol_media/protocolentities/message_media_downloadable_video.py000066400000000000000000000117511263346463600335120ustar00rootroot00000000000000from yowsup.structs import ProtocolEntity, ProtocolTreeNode from .message_media_downloadable import DownloadableMediaMessageProtocolEntity class VideoDownloadableMediaMessageProtocolEntity(DownloadableMediaMessageProtocolEntity): ''' {{THUMBNAIL_RAWDATA (JPEG?)}} ''' def __init__(self, mimeType, fileHash, url, ip, size, fileName, abitrate, acodec, asampfmt, asampfreq, duration, encoding, fps, width, height, seconds, vbitrate, vcodec, caption = None, _id = None, _from = None, to = None, notify = None, timestamp = None, participant = None, preview = None, offline = None, retry = None): super(VideoDownloadableMediaMessageProtocolEntity, self).__init__("video", mimeType, fileHash, url, ip, size, fileName, _id, _from, to, notify, timestamp, participant, preview, offline, retry) self.setVideoProps(abitrate, acodec, asampfmt, asampfreq, duration, encoding, fps, width, height, seconds, vbitrate, vcodec, caption) def __str__(self): out = super(VideoDownloadableMediaMessageProtocolEntity, self).__str__() out += "Audio bitrate: %s\n" % self.abitrate out += "Audio codec: %s\n" % self.acodec out += "Audio sampling fmt.: %s\n" % self.asampfmt out += "Audio sampling freq.: %s\n" % self.asampfreq out += "Duration: %s\n" % self.duration out += "Encoding: %s\n" % self.encoding out += "Fps: %s\n" % self.fps out += "Width: %s\n" % self.width out += "Height: %s\n" % self.height out += "Video bitrate: %s\n" % self.vbitrate out += "Video codec: %s\n" % self.vcodec if self.caption is not None: out += "Caption: %s\n" % self.caption return out def setVideoProps(self, abitrate, acodec, asampfmt, asampfreq, duration, encoding, fps, width, height, seconds, vbitrate, vcodec, caption = None): self.abitrate = abitrate self.acodec = acodec self.asampfmt = asampfmt self.asampfreq = asampfreq self.duration = duration self.encoding = encoding self.fps = fps self.height = height self.seconds = seconds self.vbitrate = vbitrate self.vcodec = vcodec self.width = width self.caption = caption def getCaption(self): return self.caption def toProtocolTreeNode(self): node = super(VideoDownloadableMediaMessageProtocolEntity, self).toProtocolTreeNode() mediaNode = node.getChild("media") mediaNode.setAttribute("abitrate", self.abitrate) mediaNode.setAttribute("acodec", self.acodec) mediaNode.setAttribute("asampfmt", self.asampfmt) mediaNode.setAttribute("asampfreq", self.asampfreq) mediaNode.setAttribute("duration", self.duration) mediaNode.setAttribute("encoding", self.encoding) mediaNode.setAttribute("fps", self.fps) mediaNode.setAttribute("height", self.height) if self.seconds is not None: mediaNode.setAttribute("seconds", self.seconds) if self.vbitrate is not None: mediaNode.setAttribute("vbitrate", self.vbitrate) mediaNode.setAttribute("vcodec", self.vcodec) mediaNode.setAttribute("width", self.width) if self.caption is not None: mediaNode.setAttribute("caption", self.caption) return node @staticmethod def fromProtocolTreeNode(node): entity = DownloadableMediaMessageProtocolEntity.fromProtocolTreeNode(node) entity.__class__ = VideoDownloadableMediaMessageProtocolEntity mediaNode = node.getChild("media") entity.setVideoProps( mediaNode.getAttributeValue("abitrate"), mediaNode.getAttributeValue("acodec"), mediaNode.getAttributeValue("asampfmt"), mediaNode.getAttributeValue("asampfreq"), mediaNode.getAttributeValue("duration"), mediaNode.getAttributeValue("encoding"), mediaNode.getAttributeValue("fps"), mediaNode.getAttributeValue("width"), mediaNode.getAttributeValue("height"), mediaNode.getAttributeValue("seconds"), mediaNode.getAttributeValue("vbitrate"), mediaNode.getAttributeValue("vcodec"), mediaNode.getAttributeValue("caption") ) return entity yowsup-2.4.48/yowsup/layers/protocol_media/protocolentities/message_media_location.py000066400000000000000000000056111263346463600314770ustar00rootroot00000000000000from yowsup.structs import ProtocolEntity, ProtocolTreeNode from .message_media import MediaMessageProtocolEntity class LocationMediaMessageProtocolEntity(MediaMessageProtocolEntity): ''' {{THUMBNAIL_RAWDATA}} ''' def __init__(self, latitude, longitude, name, url, encoding, _id = None, _from = None, to = None, notify = None, timestamp = None, participant = None, preview = None, offline = None, retry = None): super(LocationMediaMessageProtocolEntity, self).__init__("location", _id, _from, to, notify, timestamp, participant, preview, offline, retry) self.setLocationMediaProps(latitude,longitude,name,url,encoding) def __str__(self): out = super(MediaMessageProtocolEntity, self).__str__() out += "Latitude: %s\n" % self.latitude out += "Longitude: %s\n" % self.longitude out += "Name: %s\n" % self.name out += "URL: %s\n" % self.url out += "Encoding: %s\n" % self.encoding return out def getLatitude(self): return self.latitude def getLongitude(self): return self.longitude def getLocationName(self): return self.name def getLocationURL(self): return self.url def setLocationMediaProps(self, latitude, longitude, locationName, url, encoding): self.latitude = str(latitude) self.longitude = str(longitude) self.name = locationName self.url = url self.encoding= encoding def toProtocolTreeNode(self): node = super(LocationMediaMessageProtocolEntity, self).toProtocolTreeNode() mediaNode = node.getChild("media") mediaNode.setAttribute("latitude", self.latitude) mediaNode.setAttribute("longitude", self.longitude) mediaNode.setAttribute("encoding", self.encoding) if self.name: mediaNode.setAttribute("name", self.name) if self.url: mediaNode.setAttribute("url", self.url) return node @staticmethod def fromProtocolTreeNode(node): entity = MediaMessageProtocolEntity.fromProtocolTreeNode(node) entity.__class__ = LocationMediaMessageProtocolEntity mediaNode = node.getChild("media") entity.setLocationMediaProps( mediaNode.getAttributeValue("latitude"), mediaNode.getAttributeValue("longitude"), mediaNode.getAttributeValue("name"), mediaNode.getAttributeValue("url"), mediaNode.getAttributeValue("encoding") ) return entity yowsup-2.4.48/yowsup/layers/protocol_media/protocolentities/message_media_vcard.py000066400000000000000000000122711263346463600307660ustar00rootroot00000000000000from yowsup.structs import ProtocolEntity, ProtocolTreeNode from .message_media import MediaMessageProtocolEntity class VCardMediaMessageProtocolEntity(MediaMessageProtocolEntity): ''' BEGIN:VCARD VERSION:3.0 N:Yasser;Hany;;; FN:Hany Yasser PHOTO;BASE64:/9j/4AAQSkZJRgABAQEASABIAAD/4QBYRXhpZgAATU0AKgAAAAgAAgESAAMAAAABAAEAAIdpAAQAAAABAAAAJgAAAAAAA6ABAAMAAAABAAEAAKACAAQAAAABAAAAQKADAAQAAAABAAAAQAAAAAD/7QA4UGhvdG9zaG9wIDMuMAA4QklNBAQAAAAAAAA4QklNBCUAAAAAABDUHYzZjwCyBOmACZjs+EJ+/8AAEQgAQABAAwEiAAIRAQMRAf/EAB8AAAEFAQEBAQEBAAAAAAAAAAABAgMEBQYHCAkKC//EALUQAAIBAwMCBAMFBQQEAAABfQECAwAEEQUSITFBBhNRYQcicRQygZGhCCNCscEVUtHwJDNicoIJChYXGBkaJSYnKCkqNDU2Nzg5OkNERUZHSElKU1RVVldYWVpjZGVmZ2hpanN0dXZ3eHl6g4SFhoeIiYqSk5SVlpeYmZqio6Slpqeoqaqys7S1tre4ubrCw8TFxsfIycrS09TV1tfY2drh4uPk5ebn6Onq8fLz9PX29/j5+v/EAB8BAAMBAQEBAQEBAQEAAAAAAAABAgMEBQYHCAkKC//EALURAAIBAgQEAwQHBQQEAAECdwABAgMRBAUhMQYSQVEHYXETIjKBCBRCkaGxwQkjM1LwFWJy0QoWJDThJfEXGBkaJicoKSo1Njc4OTpDREVGR0hJSlNUVVZXWFlaY2RlZmdoaWpzdHV2d3h5eoKDhIWGh4iJipKTlJWWl5iZmqKjpKWmp6ipqrKztLW2t7i5usLDxMXGx8jJytLT1NXW19jZ2uLj5OXm5+jp6vLz9PX29/j5+v/bAEMABgYGBgYGCgYGCg4KCgoOEg4ODg4SFxISEhISFxwXFxcXFxccHBwcHBwcHCIiIiIiIicnJycnLCwsLCwsLCwsLP/bAEMBBwcHCwoLEwoKEy4fGh8uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLv/dAAQABP/aAAwDAQACEQMRAD8A83lPGaqzn/iXgnqZB/WpWbKjNV7kgWC5/wCen9DXix3PoGtCreFJG3OcbVFZmx2XL8A9PoOa9u0b4TDVLH+0tavDZMyBkiUDKqRkGQsQBkc49O9ebeJ9Am8PXX2bzkuYJAWhmjOVcA4Pc4I7jNelCm1BOx5M6kXNpM5VnX77EEn17D6Vt6aVaNtnABxitnwn4DvPEUS3lxIIoH5HG5yPUL059zVTxLoUPhDUYGs7gzRO+yXOCB6A7eOlTUSa5U9SqbcXzNaGdenbYxhevymsPc0rGVyDg9O1a96d9uPT5RWK/C/d6ck0qK0HXd5H/9Dy2U9B2rpPCNgmp6xp9vKgeNJWmdSMgrGN3P44qponhvVvE9ybLSYw8iKXYs21VHTk+56V7B4T8F3nhSKS91gx/anHlxqjbgqty2TgcnA/KvNo0m2n0PYr1oxi431F8R3d7Jef6MbaZ964huDhSCBlsZ5OfXp2rwzxZdyS6rLC0C26xuRhCNrkHbvAHTpivUvEdrdiaWZ4DIXXarrwVJ/oQce9eZXfg3WLgNc22ySNSIzufawc9Bz6116uTucbUYwSRreFb23sLCG6v72RraFjGbVOQwOeo78HjvTtavfDdvpyRWNo4LyIx3sSTg5xz3Hfr9a4n7Bd6bfW9orxSSSyBAqncpYnGDxx161614T8JXet3/8AbXidRHZaVuxDu3FmXLMWPp+XtxQqTk9Be2UYnj94ymFB64zWSxDnJ5UenGas3bmaWRkG1Gdii+iknA/AVQKsoyRwO1ONJxVmTKrGTuj/0e3+D9iLfR5tRZcSXUu0H/ZjxjH4k165fQG4tXRADJ/Dnpn3ri/BVt9h8OaXCMf6lSw772BY/wDoVdm90qSCPHJ6VUI2gkE581RyPNdQQJKVkj3smCpYZYY6Ae+elcT43e78M+F43twI57u4+Y4B25BYgA8cYHNe3ytbtK7lFLttwcc8nHX8K8V+OF5EdK0+BOrXJP4BD/jQkrlTk7aHjPgmztp/E8FxetsgtUluZH7hYULZ+oOK7XQEsNN+G2ra/bNMLu8mNmC8hI2uwwMdCdpJJOTnPSvOdNuPI0/V5lOG+wOg/wC2ksSH9Ca7DXwNH8A6Fpak7rxpL6X6kAL+QJrVLTQwe5545Qc9u1Z104cbe1Pkl3fSqW4szj8qzbLSP//S+ghGIfJjAA2gDHpgY49qZIxN2T2Rf1NULK5XVL66u4+YLaQ20ZH8Tp/rD+BO38DUyzlndWHclT6r2rVkR3KV7eLb3cELIx8zI3DGAM/mcdT6DmvBPjZdfvNLj6bvMfHoOAP0r6JMqujxnoyH9P8A9dfK/wAZrozeILeFOTHbDA9NzMSfyAqLblyZ57arv0vUmzjbbZ/8ixj+ddd8QbxpW0W0PHk6ZASB0G8Fq86ecx2c8Y6SIqn6bg39K6TxS0pv7dpTnNjabfZREuBWqfumdtTmpG2rmqUT/vDnvU07YGKpx4EoySvuKyZZ/9k= BDAY;value=date:1989-01-05 ORG:Vodafone Egypt; item1.EMAIL;type=INTERNET:hanyyasser@hotmail.com item1.X-ABLabel:INTERNET item2.EMAIL;type=INTERNET:hanybotbot@hotmail.com item2.X-ABLabel:INTERNET item3.ADR;type=HOME:;;Heliopolis;Cairo;Al Qahirah;;Egypt item4.ADR;type=HOME:;;;cairo;;;Egypt item5.URL:http://www.facebook.com/profile.php?id=626850952 item5.X-ABLabel:_$!!$_ X-FACEBOOK:hany.yasser1 END:VCARD ''' def __init__(self, name, card_data, _id = None, _from = None, to = None, notify = None, timestamp = None, participant = None, preview = None, offline = None, retry = None): super(VCardMediaMessageProtocolEntity, self).__init__("vcard", _id, _from, to, notify, timestamp, participant, preview, offline, retry) self.setVcardMediaProps(name,card_data) def __str__(self): out = super(MediaMessageProtocolEntity, self).__str__() out += "Name: %s\n" % self.name out += "Card Data: %s\n" % self.card_data return out def getName(self): return self.name def getCardData(self): return self.card_data def setVcardMediaProps(self, name, card_data): self.name = name self.card_data = card_data def toProtocolTreeNode(self): node = super(VCardMediaMessageProtocolEntity, self).toProtocolTreeNode() mediaNode = node.getChild("media") mediaNode["type"] = "vcard" vcardNode = ProtocolTreeNode("vcard", {"name":self.name}, None,self.card_data) mediaNode.addChild(vcardNode) return node @staticmethod def fromProtocolTreeNode(node): entity = MediaMessageProtocolEntity.fromProtocolTreeNode(node) entity.__class__ = VCardMediaMessageProtocolEntity mediaNode = node.getChild("media") entity.setVcardMediaProps( mediaNode.getAllChildren()[0].getAttributeValue('name'), mediaNode.getChild("vcard").getData() ) return entityyowsup-2.4.48/yowsup/layers/protocol_media/protocolentities/test_iq_requestupload.py000066400000000000000000000011631263346463600314470ustar00rootroot00000000000000from yowsup.layers.protocol_iq.protocolentities.test_iq import IqProtocolEntityTest from yowsup.layers.protocol_media.protocolentities import RequestUploadIqProtocolEntity from yowsup.structs import ProtocolTreeNode class RequestUploadIqProtocolEntityTest(IqProtocolEntityTest): def setUp(self): super(RequestUploadIqProtocolEntityTest, self).setUp() mediaNode = ProtocolTreeNode("media", {"hash": "hash", "size": "1234", "orighash": "orighash", "type": "image"}) self.ProtocolEntity = RequestUploadIqProtocolEntity self.node.setAttribute("type", "set") self.node.addChild(mediaNode)yowsup-2.4.48/yowsup/layers/protocol_media/protocolentities/test_iq_requestupload_result.py000066400000000000000000000011061263346463600330420ustar00rootroot00000000000000from yowsup.layers.protocol_iq.protocolentities.test_iq_result import ResultIqProtocolEntityTest from yowsup.layers.protocol_media.protocolentities import ResultRequestUploadIqProtocolEntity from yowsup.structs import ProtocolTreeNode class ResultRequestUploadIqProtocolEntityTest(ResultIqProtocolEntityTest): def setUp(self): super(ResultRequestUploadIqProtocolEntityTest, self).setUp() mediaNode = ProtocolTreeNode("media", {"url": "url", "ip": "1.2.3.4"}) self.ProtocolEntity = ResultRequestUploadIqProtocolEntity self.node.addChild(mediaNode)yowsup-2.4.48/yowsup/layers/protocol_media/protocolentities/test_message_media.py000066400000000000000000000010661263346463600306460ustar00rootroot00000000000000from yowsup.layers.protocol_media.protocolentities.message_media import MediaMessageProtocolEntity from yowsup.layers.protocol_messages.protocolentities.test_message import MessageProtocolEntityTest from yowsup.structs import ProtocolTreeNode class MediaMessageProtocolEntityTest(MessageProtocolEntityTest): def setUp(self): super(MediaMessageProtocolEntityTest, self).setUp() self.ProtocolEntity = MediaMessageProtocolEntity mediaNode = ProtocolTreeNode("media", {"type":"MEDIA_TYPE"}, None, None) self.node.addChild(mediaNode) yowsup-2.4.48/yowsup/layers/protocol_media/protocolentities/test_message_media_downloadable.py000066400000000000000000000015111263346463600333540ustar00rootroot00000000000000from yowsup.layers.protocol_media.protocolentities.message_media_downloadable import DownloadableMediaMessageProtocolEntity from yowsup.layers.protocol_media.protocolentities.test_message_media import MediaMessageProtocolEntityTest class DownloadableMediaMessageProtocolEntityTest(MediaMessageProtocolEntityTest): def setUp(self): super(DownloadableMediaMessageProtocolEntityTest, self).setUp() self.ProtocolEntity = DownloadableMediaMessageProtocolEntity mediaNode = self.node.getChild("media") mediaNode.setAttribute("mimetype", "MIMETYPE") mediaNode.setAttribute("filehash", "FILEHASH") mediaNode.setAttribute("url", "URL") mediaNode.setAttribute("ip", "IP") mediaNode.setAttribute("size", "123") mediaNode.setAttribute("file", "FILE") yowsup-2.4.48/yowsup/layers/protocol_media/protocolentities/test_message_media_downloadable_audio.py000066400000000000000000000016441263346463600345440ustar00rootroot00000000000000from yowsup.layers.protocol_media.protocolentities.message_media_downloadable_audio import AudioDownloadableMediaMessageProtocolEntity from yowsup.layers.protocol_media.protocolentities.test_message_media_downloadable import DownloadableMediaMessageProtocolEntityTest class AudioDownloadableMediaMessageProtocolEntityTest(DownloadableMediaMessageProtocolEntityTest): def setUp(self): super(AudioDownloadableMediaMessageProtocolEntityTest, self).setUp() self.ProtocolEntity = AudioDownloadableMediaMessageProtocolEntity mediaNode = self.node.getChild("media") mediaNode.setAttribute("abitrate", "31") mediaNode.setAttribute("acodec", "aac") mediaNode.setAttribute("asampfreq", "22050") mediaNode.setAttribute("duration", "3") mediaNode.setAttribute("encoding", "raw") mediaNode.setAttribute("origin", "live") mediaNode.setAttribute("seconds", "3") yowsup-2.4.48/yowsup/layers/protocol_media/protocolentities/test_message_media_downloadable_image.py000066400000000000000000000014411263346463600345200ustar00rootroot00000000000000from yowsup.layers.protocol_media.protocolentities.message_media_downloadable_image import ImageDownloadableMediaMessageProtocolEntity from yowsup.layers.protocol_media.protocolentities.test_message_media_downloadable import DownloadableMediaMessageProtocolEntityTest class ImageDownloadableMediaMessageProtocolEntityTest(DownloadableMediaMessageProtocolEntityTest): def setUp(self): super(ImageDownloadableMediaMessageProtocolEntityTest, self).setUp() self.ProtocolEntity = ImageDownloadableMediaMessageProtocolEntity mediaNode = self.node.getChild("media") mediaNode.setAttribute("encoding", "ENCODING") mediaNode.setAttribute("width", "1024") mediaNode.setAttribute("height", "768") mediaNode.setAttribute("caption", "caption") yowsup-2.4.48/yowsup/layers/protocol_media/protocolentities/test_message_media_downloadable_video.py000066400000000000000000000022611263346463600345450ustar00rootroot00000000000000from yowsup.layers.protocol_media.protocolentities.message_media_downloadable_video import VideoDownloadableMediaMessageProtocolEntity from yowsup.layers.protocol_media.protocolentities.test_message_media_downloadable import DownloadableMediaMessageProtocolEntityTest class VideoDownloadableMediaMessageProtocolEntityTest(DownloadableMediaMessageProtocolEntityTest): def setUp(self): super(VideoDownloadableMediaMessageProtocolEntityTest, self).setUp() self.ProtocolEntity = VideoDownloadableMediaMessageProtocolEntity mediaNode = self.node.getChild("media") mediaNode.setAttribute("abitrate", "165") mediaNode.setAttribute("acodec", "aac") mediaNode.setAttribute("asampfmt", "flt") mediaNode.setAttribute("asampfreq", "48000") mediaNode.setAttribute("duration", "61") mediaNode.setAttribute("encoding", "raw") mediaNode.setAttribute("fps", "24") mediaNode.setAttribute("height", "452") mediaNode.setAttribute("seconds", "61") mediaNode.setAttribute("vbitrate", "1862") mediaNode.setAttribute("vcodec", "h264") mediaNode.setAttribute("width", "800") yowsup-2.4.48/yowsup/layers/protocol_media/protocolentities/test_message_media_location.py000066400000000000000000000012611263346463600325330ustar00rootroot00000000000000from yowsup.layers.protocol_media.protocolentities.test_message_media import MediaMessageProtocolEntityTest from yowsup.layers.protocol_media.protocolentities import LocationMediaMessageProtocolEntity from yowsup.structs import ProtocolTreeNode class LocationMediaMessageProtocolEntityTest(MediaMessageProtocolEntityTest): def setUp(self): super(LocationMediaMessageProtocolEntityTest, self).setUp() self.ProtocolEntity = LocationMediaMessageProtocolEntity mediaNode = self.node.getChild("media") mediaNode["type"] = "location" mediaNode["latitude"] = "52.52393" mediaNode["longitude"] = "13.41747" mediaNode["encoding"] = "raw" yowsup-2.4.48/yowsup/layers/protocol_media/protocolentities/test_message_media_vcard.py000066400000000000000000000012351263346463600320230ustar00rootroot00000000000000from yowsup.layers.protocol_media.protocolentities.test_message_media import MediaMessageProtocolEntityTest from yowsup.layers.protocol_media.protocolentities import VCardMediaMessageProtocolEntity from yowsup.structs import ProtocolTreeNode class VCardMediaMessageProtocolEntityTest(MediaMessageProtocolEntityTest): def setUp(self): super(VCardMediaMessageProtocolEntityTest, self).setUp() self.ProtocolEntity = VCardMediaMessageProtocolEntity vcardNode = ProtocolTreeNode("vcard", {"name":"abc"}, None, "VCARD_DATA") mediaNode = self.node.getChild("media") mediaNode["type"] = "vcard" mediaNode.addChild(vcardNode) yowsup-2.4.48/yowsup/layers/protocol_messages/000077500000000000000000000000001263346463600215715ustar00rootroot00000000000000yowsup-2.4.48/yowsup/layers/protocol_messages/__init__.py000066400000000000000000000000541263346463600237010ustar00rootroot00000000000000from .layer import YowMessagesProtocolLayer yowsup-2.4.48/yowsup/layers/protocol_messages/layer.py000066400000000000000000000014211263346463600232550ustar00rootroot00000000000000from yowsup.layers import YowLayer, YowLayerEvent, YowProtocolLayer from .protocolentities import TextMessageProtocolEntity class YowMessagesProtocolLayer(YowProtocolLayer): def __init__(self): handleMap = { "message": (self.recvMessageStanza, self.sendMessageEntity) } super(YowMessagesProtocolLayer, self).__init__(handleMap) def __str__(self): return "Messages Layer" def sendMessageEntity(self, entity): if entity.getType() == "text": self.entityToLower(entity) ###recieved node handlers handlers def recvMessageStanza(self, node): if node.getAttributeValue("type") == "text": entity = TextMessageProtocolEntity.fromProtocolTreeNode(node) self.toUpper(entity) yowsup-2.4.48/yowsup/layers/protocol_messages/protocolentities/000077500000000000000000000000001263346463600251775ustar00rootroot00000000000000yowsup-2.4.48/yowsup/layers/protocol_messages/protocolentities/__init__.py000066400000000000000000000002301263346463600273030ustar00rootroot00000000000000from .message_text import TextMessageProtocolEntity from .message import MessageProtocolEntity from .message_text_broadcast import BroadcastTextMessage yowsup-2.4.48/yowsup/layers/protocol_messages/protocolentities/message.py000066400000000000000000000101731263346463600271770ustar00rootroot00000000000000from yowsup.structs import ProtocolEntity, ProtocolTreeNode from yowsup.layers.protocol_receipts.protocolentities import OutgoingReceiptProtocolEntity from copy import deepcopy class MessageProtocolEntity(ProtocolEntity): MESSAGE_TYPE_TEXT = "text" MESSAGE_TYPE_MEDIA = "media" def __init__(self, _type, _id = None, _from = None, to = None, notify = None, timestamp = None, participant = None, offline = None, retry = None): assert (to or _from), "Must specify either to or _from jids to create the message" assert not(to and _from), "Can't set both attributes to message at same time (to, _from)" super(MessageProtocolEntity, self).__init__("message") self._type = _type self._id = self._generateId() if _id is None else _id self._from =_from self.to = to self.timestamp = int(timestamp) if timestamp else self._getCurrentTimestamp() self.notify = notify self.offline = offline == "1" if offline is not None else offline self.retry = int(retry) if retry else None self.participant = participant def getType(self): return self._type def getId(self): return self._id def getTimestamp(self): return self.timestamp def getFrom(self, full = True): return self._from if full else self._from.split('@')[0] def isBroadcast(self): return False def getTo(self, full = True): return self.to if full else self.to.split('@')[0] def getParticipant(self, full = True): return self.participant if full else self.participant.split('@')[0] def getNotify(self): return self.notify def toProtocolTreeNode(self): attribs = { "type" : self._type, "id" : self._id, } if self.isOutgoing(): attribs["to"] = self.to else: attribs["from"] = self._from attribs["t"] = str(self.timestamp) if self.offline is not None: attribs["offline"] = "1" if self.offline else "0" if self.notify: attribs["notify"] = self.notify if self.retry: attribs["retry"] = str(self.retry) if self.participant: attribs["participant"] = self.participant xNode = None #if self.isOutgoing(): # serverNode = ProtocolTreeNode("server", {}) # xNode = ProtocolTreeNode("x", {"xmlns": "jabber:x:event"}, [serverNode]) return self._createProtocolTreeNode(attribs, children = [xNode] if xNode else None, data = None) def isOutgoing(self): return self._from is None def isGroupMessage(self): if self.isOutgoing(): return "-" in self.to return self.participant != None def __str__(self): out = "Message:\n" out += "ID: %s\n" % self._id out += "To: %s\n" % self.to if self.isOutgoing() else "From: %s\n" % self._from out += "Type: %s\n" % self._type out += "Timestamp: %s\n" % self.timestamp if self.participant: out += "Participant: %s\n" % self.participant return out def ack(self, read=False): return OutgoingReceiptProtocolEntity(self.getId(), self.getFrom(), read, participant=self.getParticipant()) def forward(self, to, _id = None): OutgoingMessage = deepcopy(self) OutgoingMessage.to = to OutgoingMessage._from = None OutgoingMessage._id = self._generateId() if _id is None else _id return OutgoingMessage @staticmethod def fromProtocolTreeNode(node): return MessageProtocolEntity( node.getAttributeValue("type"), node.getAttributeValue("id"), node.getAttributeValue("from"), node.getAttributeValue("to"), node.getAttributeValue("notify"), node.getAttributeValue("t"), node.getAttributeValue("participant"), node.getAttributeValue("offline"), node.getAttributeValue("retry") ) yowsup-2.4.48/yowsup/layers/protocol_messages/protocolentities/message_text.py000066400000000000000000000026521263346463600302460ustar00rootroot00000000000000from yowsup.structs import ProtocolEntity, ProtocolTreeNode from .message import MessageProtocolEntity class TextMessageProtocolEntity(MessageProtocolEntity): ''' {{MESSAGE_DATA}} ''' def __init__(self, body, _id = None, _from = None, to = None, notify = None, timestamp = None, participant = None, offline = None, retry = None): super(TextMessageProtocolEntity, self).__init__("text",_id, _from, to, notify, timestamp, participant, offline, retry) self.setBody(body) def __str__(self): out = super(TextMessageProtocolEntity, self).__str__() out += "Body: %s\n" % self.body return out def setBody(self, body): self.body = body def getBody(self): return self.body def toProtocolTreeNode(self): node = super(TextMessageProtocolEntity, self).toProtocolTreeNode() bodyNode = ProtocolTreeNode("body", {}, None, self.body) node.addChild(bodyNode) return node @staticmethod def fromProtocolTreeNode(node): entity = MessageProtocolEntity.fromProtocolTreeNode(node) entity.__class__ = TextMessageProtocolEntity entity.setBody(node.getChild("body").getData()) return entity yowsup-2.4.48/yowsup/layers/protocol_messages/protocolentities/message_text_broadcast.py000066400000000000000000000022411263346463600322620ustar00rootroot00000000000000from .message_text import TextMessageProtocolEntity from yowsup.structs import ProtocolTreeNode import time class BroadcastTextMessage(TextMessageProtocolEntity): def __init__(self, jids, body): broadcastTime = int(time.time() * 1000) super(BroadcastTextMessage, self).__init__(body, to = "%s@broadcast" % broadcastTime) self.setBroadcastProps(jids) def setBroadcastProps(self, jids): assert type(jids) is list, "jids must be a list, got %s instead." % type(jids) self.jids = jids def toProtocolTreeNode(self): node = super(BroadcastTextMessage, self).toProtocolTreeNode() toNodes = [ProtocolTreeNode("to", {"jid": jid}) for jid in self.jids] broadcastNode = ProtocolTreeNode("broadcast", children = toNodes) node.addChild(broadcastNode) return node @staticmethod def fromProtocolTreeNode(node): entity = TextMessageProtocolEntity.fromProtocolTreeNode(node) entity.__class__ = BroadcastTextMessage jids = [toNode.getAttributeValue("jid") for toNode in node.getChild("broadcast").getAllChildren()] entity.setBroadcastProps(jids) return entity yowsup-2.4.48/yowsup/layers/protocol_messages/protocolentities/test_message.py000066400000000000000000000013171263346463600302360ustar00rootroot00000000000000from yowsup.layers.protocol_messages.protocolentities.message import MessageProtocolEntity from yowsup.structs import ProtocolTreeNode from yowsup.structs.protocolentity import ProtocolEntityTest import unittest class MessageProtocolEntityTest(ProtocolEntityTest, unittest.TestCase): def setUp(self): self.ProtocolEntity = MessageProtocolEntity # ORDER_MATTERS for node.toString() to output return attribs in same order attribs = { "type": "message_type", "id": "message-id", "t": "12345", "offline": "0", "from": "from_jid", "notify": "notify_name" } self.node = ProtocolTreeNode("message", attribs) yowsup-2.4.48/yowsup/layers/protocol_messages/protocolentities/test_message_text.py000066400000000000000000000010451263346463600313000ustar00rootroot00000000000000from yowsup.layers.protocol_messages.protocolentities.message_text import TextMessageProtocolEntity from yowsup.structs import ProtocolTreeNode from yowsup.layers.protocol_messages.protocolentities.test_message import MessageProtocolEntityTest class TextMessageProtocolEntityTest(MessageProtocolEntityTest): def setUp(self): super(TextMessageProtocolEntityTest, self).setUp() self.ProtocolEntity = TextMessageProtocolEntity bodyNode = ProtocolTreeNode("body", {}, None, "body_data") self.node.addChild(bodyNode) yowsup-2.4.48/yowsup/layers/protocol_messages/protocolentities/test_message_text_broadcast.py000066400000000000000000000012641263346463600333250ustar00rootroot00000000000000from yowsup.layers.protocol_messages.protocolentities.test_message_text import TextMessageProtocolEntityTest from yowsup.layers.protocol_messages.protocolentities.message_text_broadcast import BroadcastTextMessage from yowsup.structs import ProtocolTreeNode class BroadcastTextMessageTest(TextMessageProtocolEntityTest): def setUp(self): super(BroadcastTextMessageTest, self).setUp() self.ProtocolEntity = BroadcastTextMessage broadcastNode = ProtocolTreeNode("broadcast") jids = ["jid1", "jid2"] toNodes = [ProtocolTreeNode("to", {"jid" : jid}) for jid in jids] broadcastNode.addChildren(toNodes) self.node.addChild(broadcastNode) yowsup-2.4.48/yowsup/layers/protocol_notifications/000077500000000000000000000000001263346463600226335ustar00rootroot00000000000000yowsup-2.4.48/yowsup/layers/protocol_notifications/__init__.py000066400000000000000000000000601263346463600247400ustar00rootroot00000000000000from .layer import YowNotificationsProtocolLayeryowsup-2.4.48/yowsup/layers/protocol_notifications/layer.py000066400000000000000000000033721263346463600243260ustar00rootroot00000000000000from yowsup.layers import YowLayer, YowLayerEvent, YowProtocolLayer from .protocolentities import * from yowsup.layers.protocol_acks.protocolentities import OutgoingAckProtocolEntity class YowNotificationsProtocolLayer(YowProtocolLayer): def __init__(self): handleMap = { "notification": (self.recvNotification, self.sendNotification) } super(YowNotificationsProtocolLayer, self).__init__(handleMap) def __str__(self): return "notification Ib Layer" def sendNotification(self, entity): if entity.getTag() == "notification": self.toLower(entity.toProtocolTreeNode()) def recvNotification(self, node): if node["type"] == "picture": if node.getChild("set"): self.toUpper(SetPictureNotificationProtocolEntity.fromProtocolTreeNode(node)) elif node.getChild("delete"): self.toUpper(DeletePictureNotificationProtocolEntity.fromProtocolTreeNode(node)) else: self.raiseErrorForNode(node) elif node["type"] == "status": self.toUpper(StatusNotificationProtocolEntity.fromProtocolTreeNode(node)) elif node["type"] == "features": # Not implemented pass elif node["type"] in [ "contacts", "subject", "w:gp2" ]: # Implemented in respectively the protocol_contacts and protocol_groups layer pass elif node["type"] == "contacts": pass elif node["type"] == "web": # Not implemented pass else: self.raiseErrorForNode(node) ack = OutgoingAckProtocolEntity(node["id"], "notification", node["type"], node["from"]) self.toLower(ack.toProtocolTreeNode()) yowsup-2.4.48/yowsup/layers/protocol_notifications/protocolentities/000077500000000000000000000000001263346463600262415ustar00rootroot00000000000000yowsup-2.4.48/yowsup/layers/protocol_notifications/protocolentities/__init__.py000066400000000000000000000006051263346463600303530ustar00rootroot00000000000000from .notification import NotificationProtocolEntity from .notification_picture import PictureNotificationProtocolEntity from .notification_picture_set import SetPictureNotificationProtocolEntity from .notification_picture_delete import DeletePictureNotificationProtocolEntity from .notification_status import StatusNotificationProtocolEntity yowsup-2.4.48/yowsup/layers/protocol_notifications/protocolentities/notification.py000066400000000000000000000040201263346463600312750ustar00rootroot00000000000000from yowsup.structs import ProtocolEntity, ProtocolTreeNode from yowsup.layers.protocol_receipts.protocolentities import OutgoingReceiptProtocolEntity class NotificationProtocolEntity(ProtocolEntity): ''' ''' def __init__(self, _type, _id, _from, timestamp, notify, offline): super(NotificationProtocolEntity, self).__init__("notification") self._type = _type self._id = _id self._from =_from self.timestamp = int(timestamp) self.notify = notify self.offline = offline == "1" def __str__(self): out = "Notification\n" out += "From: %s\n" % self.getFrom() out += "Type: %s\n" % self.getType() return out def getFrom(self, full = True): return self._from if full else self._from.split('@')[0] def getType(self): return self._type def getId(self): return self._id def getTimestamp(self): return self.timestamp def toProtocolTreeNode(self): attribs = { "t" : str(self.timestamp), "from" : self._from, "offline" : "1" if self.offline else "0", "type" : self._type, "id" : self._id, "notify" : self.notify } return self._createProtocolTreeNode(attribs, children = None, data = None) def ack(self): return OutgoingReceiptProtocolEntity(self.getId(), self.getFrom()) @staticmethod def fromProtocolTreeNode(node): return NotificationProtocolEntity( node.getAttributeValue("type"), node.getAttributeValue("id"), node.getAttributeValue("from"), node.getAttributeValue("t"), node.getAttributeValue("notify"), node.getAttributeValue("offline") ) yowsup-2.4.48/yowsup/layers/protocol_notifications/protocolentities/notification_picture.py000066400000000000000000000014571263346463600330430ustar00rootroot00000000000000from yowsup.structs import ProtocolEntity, ProtocolTreeNode from .notification import NotificationProtocolEntity class PictureNotificationProtocolEntity(NotificationProtocolEntity): ''' ''' def __init__(self, _id, _from, status, timestamp, notify, offline, setJid, setId): super(PictureNotificationProtocolEntity, self).__init__("picture", _id, _from, timestamp, notify, offline) self.setData(setJid, setId) @staticmethod def fromProtocolTreeNode(node): entity = NotificationProtocolEntity.fromProtocolTreeNode(node) entity.__class__ = PictureNotificationProtocolEntity return entityyowsup-2.4.48/yowsup/layers/protocol_notifications/protocolentities/notification_picture_delete.py000066400000000000000000000027261263346463600343650ustar00rootroot00000000000000from yowsup.structs import ProtocolEntity, ProtocolTreeNode from .notification_picture import PictureNotificationProtocolEntity class DeletePictureNotificationProtocolEntity(PictureNotificationProtocolEntity): ''' ''' def __init__(self, _id, _from, status, timestamp, notify, offline, deleteJid): super(DeletePictureNotificationProtocolEntity, self).__init__(_id, _from, timestamp, notify, offline) self.setData(deleteJid) def setData(self, deleteJid): self.deleteJid = deleteJid def __str__(self): out = super(DeletePictureNotificationProtocolEntity, self).__str__() out += "Type: Delete" return out def toProtocolTreeNode(self): node = super(DeletePictureNotificationProtocolEntity, self).toProtocolTreeNode() deleteNode = ProtocolTreeNode("delete", {"jid": self.deleteJid}, None, None) node.addChild(deleteNode) return node @staticmethod def fromProtocolTreeNode(node): entity = PictureNotificationProtocolEntity.fromProtocolTreeNode(node) entity.__class__ = DeletePictureNotificationProtocolEntity deleteNode = node.getChild("delete") entity.setData(deleteNode.getAttributeValue("jid")) return entity yowsup-2.4.48/yowsup/layers/protocol_notifications/protocolentities/notification_picture_set.py000066400000000000000000000025751263346463600337200ustar00rootroot00000000000000from yowsup.structs import ProtocolEntity, ProtocolTreeNode from .notification_picture import PictureNotificationProtocolEntity class SetPictureNotificationProtocolEntity(PictureNotificationProtocolEntity): ''' ''' def __init__(self, _id, _from, status, timestamp, notify, offline, setJid, setId): super(SetPictureNotificationProtocolEntity, self).__init__(_id, _from, timestamp, notify, offline) self.setData(setJid, setId) def setData(self, setJid, setId): self.setId = setId self.setJid = setJid def toProtocolTreeNode(self): node = super(SetPictureNotificationProtocolEntity, self).toProtocolTreeNode() setNode = ProtocolTreeNode("set", {"jid": self.setJid, "id": self.setId}, None, None) node.addChild(setNode) return node @staticmethod def fromProtocolTreeNode(node): entity = PictureNotificationProtocolEntity.fromProtocolTreeNode(node) entity.__class__ = SetPictureNotificationProtocolEntity setNode = node.getChild("set") entity.setData(setNode.getAttributeValue("jid"), setNode.getAttributeValue("id")) return entityyowsup-2.4.48/yowsup/layers/protocol_notifications/protocolentities/notification_status.py000066400000000000000000000023031263346463600327020ustar00rootroot00000000000000from yowsup.structs import ProtocolEntity, ProtocolTreeNode from .notification import NotificationProtocolEntity class StatusNotificationProtocolEntity(NotificationProtocolEntity): ''' {{STATUS}} ''' def __init__(self, _type, _id, _from, status, timestamp, notify, offline = False): super(StatusNotificationProtocolEntity, self).__init__("status", _id, _from, timestamp, notify, offline) self.setStatus(status) def setStatus(self, status): self.status = status def toProtocolTreeNode(self): node = super(StatusNotificationProtocolEntity, self).toProtocolTreeNode() setNode = ProtocolTreeNode("set", {}, None, self.status) node.addChild(setNode) return node @staticmethod def fromProtocolTreeNode(node): entity = NotificationProtocolEntity.fromProtocolTreeNode(node) entity.__class__ = StatusNotificationProtocolEntity entity.setStatus(node.getChild("set").getData()) return entityyowsup-2.4.48/yowsup/layers/protocol_notifications/protocolentities/test_notification.py000066400000000000000000000012261263346463600323410ustar00rootroot00000000000000from yowsup.layers.protocol_notifications.protocolentities.notification import NotificationProtocolEntity from yowsup.structs import ProtocolTreeNode from yowsup.structs.protocolentity import ProtocolEntityTest import unittest class NotificationProtocolEntityTest(ProtocolEntityTest, unittest.TestCase): def setUp(self): self.ProtocolEntity = NotificationProtocolEntity attribs = { "t": "12345", "from": "from_jid", "offline": "0", "type": "notif_type", "id": "message-id", "notify": "notify_name" } self.node = ProtocolTreeNode("notification", attribs)yowsup-2.4.48/yowsup/layers/protocol_notifications/protocolentities/test_notification_picture.py000066400000000000000000000007221263346463600340740ustar00rootroot00000000000000from yowsup.layers.protocol_notifications.protocolentities.notification_picture import PictureNotificationProtocolEntity from yowsup.layers.protocol_notifications.protocolentities.test_notification import NotificationProtocolEntityTest class PictureNotificationProtocolEntityTest(NotificationProtocolEntityTest): def setUp(self): super(PictureNotificationProtocolEntityTest, self).setUp() self.ProtocolEntity = PictureNotificationProtocolEntity test_notification_picture_delete.py000066400000000000000000000012551263346463600353410ustar00rootroot00000000000000yowsup-2.4.48/yowsup/layers/protocol_notifications/protocolentitiesfrom yowsup.layers.protocol_notifications.protocolentities.notification_picture_delete import DeletePictureNotificationProtocolEntity from yowsup.structs import ProtocolTreeNode from yowsup.layers.protocol_notifications.protocolentities.test_notification_picture import PictureNotificationProtocolEntityTest class DeletePictureNotificationProtocolEntityTest(PictureNotificationProtocolEntityTest): def setUp(self): super(DeletePictureNotificationProtocolEntityTest, self).setUp() self.ProtocolEntity = DeletePictureNotificationProtocolEntity deleteNode = ProtocolTreeNode("delete", {"jid": "DELETE_JID"}, None, None) self.node.addChild(deleteNode) yowsup-2.4.48/yowsup/layers/protocol_notifications/protocolentities/test_notification_picture_set.py000066400000000000000000000012371263346463600347510ustar00rootroot00000000000000from yowsup.layers.protocol_notifications.protocolentities.notification_picture_set import SetPictureNotificationProtocolEntity from yowsup.structs import ProtocolTreeNode from yowsup.layers.protocol_notifications.protocolentities.test_notification_picture import PictureNotificationProtocolEntityTest class SetPictureNotificationProtocolEntityTest(PictureNotificationProtocolEntityTest): def setUp(self): super(SetPictureNotificationProtocolEntityTest, self).setUp() self.ProtocolEntity = SetPictureNotificationProtocolEntity setNode = ProtocolTreeNode("set", {"jid": "SET_JID", "id": "123"}, None, None) self.node.addChild(setNode) yowsup-2.4.48/yowsup/layers/protocol_notifications/protocolentities/test_notification_status.py000066400000000000000000000011361263346463600337440ustar00rootroot00000000000000from yowsup.layers.protocol_notifications.protocolentities.notification_status import StatusNotificationProtocolEntity from yowsup.structs import ProtocolTreeNode from yowsup.layers.protocol_notifications.protocolentities.test_notification import NotificationProtocolEntityTest class StatusNotificationProtocolEntityTest(NotificationProtocolEntityTest): def setUp(self): super(StatusNotificationProtocolEntityTest, self).setUp() self.ProtocolEntity = StatusNotificationProtocolEntity setNode = ProtocolTreeNode("set", {}, [], "status_data") self.node.addChild(setNode) yowsup-2.4.48/yowsup/layers/protocol_presence/000077500000000000000000000000001263346463600215665ustar00rootroot00000000000000yowsup-2.4.48/yowsup/layers/protocol_presence/__init__.py000066400000000000000000000000541263346463600236760ustar00rootroot00000000000000from .layer import YowPresenceProtocolLayer yowsup-2.4.48/yowsup/layers/protocol_presence/layer.py000066400000000000000000000022271263346463600232570ustar00rootroot00000000000000from yowsup.layers import YowLayer, YowLayerEvent, YowProtocolLayer from .protocolentities import * from yowsup.layers.protocol_iq.protocolentities import ErrorIqProtocolEntity class YowPresenceProtocolLayer(YowProtocolLayer): def __init__(self): handleMap = { "presence": (self.recvPresence, self.sendPresence), "iq": (None, self.sendIq) } super(YowPresenceProtocolLayer, self).__init__(handleMap) def __str__(self): return "Presence Layer" def sendPresence(self, entity): self.entityToLower(entity) def recvPresence(self, node): self.toUpper(PresenceProtocolEntity.fromProtocolTreeNode(node)) def sendIq(self, entity): if entity.getXmlns() == LastseenIqProtocolEntity.XMLNS: self._sendIq(entity, self.onLastSeenSuccess, self.onLastSeenError) def onLastSeenSuccess(self, protocolTreeNode, lastSeenEntity): self.toUpper(ResultLastseenIqProtocolEntity.fromProtocolTreeNode(protocolTreeNode)) def onLastSeenError(self, protocolTreeNode, lastSeenEntity): self.toUpper(ErrorIqProtocolEntity.fromProtocolTreeNode(protocolTreeNode)) yowsup-2.4.48/yowsup/layers/protocol_presence/protocolentities/000077500000000000000000000000001263346463600251745ustar00rootroot00000000000000yowsup-2.4.48/yowsup/layers/protocol_presence/protocolentities/__init__.py000066400000000000000000000007101263346463600273030ustar00rootroot00000000000000from .presence import PresenceProtocolEntity from .presence_available import AvailablePresenceProtocolEntity from .presence_unavailable import UnavailablePresenceProtocolEntity from .presence_subscribe import SubscribePresenceProtocolEntity from .presence_unsubscribe import UnsubscribePresenceProtocolEntity from .iq_lastseen import LastseenIqProtocolEntity from .iq_lastseen_result import ResultLastseenIqProtocolEntity yowsup-2.4.48/yowsup/layers/protocol_presence/protocolentities/iq_lastseen.py000066400000000000000000000013071263346463600300560ustar00rootroot00000000000000from yowsup.layers.protocol_iq.protocolentities.iq import IqProtocolEntity from yowsup.structs.protocoltreenode import ProtocolTreeNode class LastseenIqProtocolEntity(IqProtocolEntity): XMLNS = "jabber:iq:last" def __init__(self, jid, _id = None): super(LastseenIqProtocolEntity, self).__init__(self.__class__.XMLNS, _type = "get", to = jid, _id = _id) @staticmethod def fromProtocolTreeNode(node): return LastseenIqProtocolEntity(node["to"]) def toProtocolTreeNode(self): node = super(LastseenIqProtocolEntity, self).toProtocolTreeNode() node.setAttribute("xmlns", self.__class__.XMLNS) node.addChild(ProtocolTreeNode("query")) return node yowsup-2.4.48/yowsup/layers/protocol_presence/protocolentities/iq_lastseen_result.py000066400000000000000000000020041263346463600314470ustar00rootroot00000000000000from yowsup.layers.protocol_iq.protocolentities.iq_result import ResultIqProtocolEntity from yowsup.structs.protocoltreenode import ProtocolTreeNode class ResultLastseenIqProtocolEntity(ResultIqProtocolEntity): def __init__(self, jid, seconds, _id = None): super(ResultLastseenIqProtocolEntity, self).__init__(_from=jid, _id=_id) self.setSeconds(seconds) def setSeconds(self, seconds): self.seconds = int(seconds) def getSeconds(self): return self.seconds def __str__(self): out = super(ResultIqProtocolEntity, self).__str__() out += "Seconds: %s\n" % self.seconds return out def toProtocolTreeNode(self): node = super(ResultLastseenIqProtocolEntity, self).toProtocolTreeNode() node.addChild(ProtocolTreeNode("query", {"seconds": str(self.seconds)})) return node @staticmethod def fromProtocolTreeNode(node): return ResultLastseenIqProtocolEntity(node["from"], node.getChild("query")["seconds"], node["id"])yowsup-2.4.48/yowsup/layers/protocol_presence/protocolentities/presence.py000066400000000000000000000036111263346463600273530ustar00rootroot00000000000000from yowsup.structs import ProtocolEntity, ProtocolTreeNode class PresenceProtocolEntity(ProtocolEntity): ''' Should normally be either type or name when contact goes offline: when contact goes online: ''' def __init__(self, _type = None, name = None, _from = None, last = None): super(PresenceProtocolEntity, self).__init__("presence") self._type = _type self.name = name self._from = _from self.last = last def getType(self): return self._type def getName(self): return self.name def getFrom(self, full = True): return self._from if full else self._from.split('@')[0] def getLast(self): return self.last def toProtocolTreeNode(self): attribs = {} if self._type: attribs["type"] = self._type if self.name: attribs["name"] = self.name if self._from: attribs["from"] = self._from if self.last: attribs["last"] = self.last return self._createProtocolTreeNode(attribs, None, None) def __str__(self): out = "Presence:\n" if self._type: out += "Type: %s\n" % self._type if self.name: out += "Name: %s\n" % self.name if self._from: out += "From: %s\n" % self._from if self.last: out += "Last seen: %s\n" % self.last return out @staticmethod def fromProtocolTreeNode(node): return PresenceProtocolEntity( node.getAttributeValue("type"), node.getAttributeValue("name"), node.getAttributeValue("from"), node.getAttributeValue("last") ) yowsup-2.4.48/yowsup/layers/protocol_presence/protocolentities/presence_available.py000066400000000000000000000006031263346463600313510ustar00rootroot00000000000000from yowsup.structs import ProtocolEntity, ProtocolTreeNode from .presence import PresenceProtocolEntity class AvailablePresenceProtocolEntity(PresenceProtocolEntity): ''' response: ''' def __init__(self): super(AvailablePresenceProtocolEntity, self).__init__("available")yowsup-2.4.48/yowsup/layers/protocol_presence/protocolentities/presence_subscribe.py000066400000000000000000000020111263346463600314050ustar00rootroot00000000000000from yowsup.structs import ProtocolEntity, ProtocolTreeNode from .presence import PresenceProtocolEntity class SubscribePresenceProtocolEntity(PresenceProtocolEntity): ''' ''' def __init__(self, jid): super(SubscribePresenceProtocolEntity, self).__init__("subscribe") self.setProps(jid) def setProps(self, jid): self.jid = jid def toProtocolTreeNode(self): node = super(SubscribePresenceProtocolEntity, self).toProtocolTreeNode() node.setAttribute("to", self.jid) return node def __str__(self): out = super(SubscribePresenceProtocolEntity, self).__str__() out += "To: %s\n" % self.jid return out @staticmethod def fromProtocolTreeNode(node): entity = PresenceProtocolEntity.fromProtocolTreeNode(node) entity.__class__ = SubscribePresenceProtocolEntity entity.setProps( node.getAttributeValue("to") ) return entity yowsup-2.4.48/yowsup/layers/protocol_presence/protocolentities/presence_unavailable.py000066400000000000000000000006351263346463600317210ustar00rootroot00000000000000from yowsup.structs import ProtocolEntity, ProtocolTreeNode from .presence import PresenceProtocolEntity class UnavailablePresenceProtocolEntity(PresenceProtocolEntity): ''' response: ''' def __init__(self): super(UnavailablePresenceProtocolEntity, self).__init__("unavailable")yowsup-2.4.48/yowsup/layers/protocol_presence/protocolentities/presence_unsubscribe.py000066400000000000000000000020271263346463600317570ustar00rootroot00000000000000from yowsup.structs import ProtocolEntity, ProtocolTreeNode from .presence import PresenceProtocolEntity class UnsubscribePresenceProtocolEntity(PresenceProtocolEntity): ''' ''' def __init__(self, jid): super(UnsubscribePresenceProtocolEntity, self).__init__("unsubscribe") self.setProps(jid) def setProps(self, jid): self.jid = jid def toProtocolTreeNode(self): node = super(UnsubscribePresenceProtocolEntity, self).toProtocolTreeNode() node.setAttribute("to", self.jid) return node def __str__(self): out = super(UnsubscribePresenceProtocolEntity, self).__str__() out += "To: %s\n" % self.jid return out @staticmethod def fromProtocolTreeNode(node): entity = PresenceProtocolEntity.fromProtocolTreeNode(node) entity.__class__ = UnsubscribePresenceProtocolEntity entity.setProps( node.getAttributeValue("to") ) return entity yowsup-2.4.48/yowsup/layers/protocol_presence/protocolentities/test_presence.py000066400000000000000000000007331263346463600304140ustar00rootroot00000000000000from yowsup.layers.protocol_presence.protocolentities.presence import PresenceProtocolEntity from yowsup.structs import ProtocolTreeNode from yowsup.structs.protocolentity import ProtocolEntityTest import unittest class PresenceProtocolEntityTest(ProtocolEntityTest, unittest.TestCase): def setUp(self): self.ProtocolEntity = PresenceProtocolEntity self.node = ProtocolTreeNode("presence", {"type": "presence_type", "name": "presence_name"}, None, None) yowsup-2.4.48/yowsup/layers/protocol_presence/protocolentities/test_presence_available.py000066400000000000000000000007461263346463600324200ustar00rootroot00000000000000from yowsup.layers.protocol_presence.protocolentities.presence_available import AvailablePresenceProtocolEntity from yowsup.layers.protocol_presence.protocolentities.test_presence import PresenceProtocolEntityTest class AvailablePresenceProtocolEntityTest(PresenceProtocolEntityTest): def setUp(self): super(AvailablePresenceProtocolEntityTest, self).setUp() self.ProtocolEntity = AvailablePresenceProtocolEntity self.node.setAttribute("type", "available") yowsup-2.4.48/yowsup/layers/protocol_presence/protocolentities/test_presence_subscribe.py000066400000000000000000000010331263346463600324470ustar00rootroot00000000000000from yowsup.layers.protocol_presence.protocolentities.presence_subscribe import SubscribePresenceProtocolEntity from yowsup.layers.protocol_presence.protocolentities.test_presence import PresenceProtocolEntityTest class SubscribePresenceProtocolEntityTest(PresenceProtocolEntityTest): def setUp(self): super(SubscribePresenceProtocolEntityTest, self).setUp() self.ProtocolEntity = SubscribePresenceProtocolEntity self.node.setAttribute("type", "subscribe") self.node.setAttribute("to", "subscribe_jid")yowsup-2.4.48/yowsup/layers/protocol_presence/protocolentities/test_presence_unavailable.py000066400000000000000000000007621263346463600327610ustar00rootroot00000000000000from yowsup.layers.protocol_presence.protocolentities.presence_unavailable import UnavailablePresenceProtocolEntity from yowsup.layers.protocol_presence.protocolentities.test_presence import PresenceProtocolEntityTest class UnavailablePresenceProtocolEntityTest(PresenceProtocolEntityTest): def setUp(self): super(UnavailablePresenceProtocolEntityTest, self).setUp() self.ProtocolEntity = UnavailablePresenceProtocolEntity self.node.setAttribute("type", "unavailable") yowsup-2.4.48/yowsup/layers/protocol_presence/protocolentities/test_presence_unsubscribe.py000066400000000000000000000010421263346463600330120ustar00rootroot00000000000000from yowsup.layers.protocol_presence.protocolentities.presence_unsubscribe import UnsubscribePresenceProtocolEntity from yowsup.layers.protocol_presence.protocolentities.test_presence import PresenceProtocolEntityTest class UnsubscribePresenceProtocolEntityTest(PresenceProtocolEntityTest): def setUp(self): super(UnsubscribePresenceProtocolEntityTest, self).setUp() self.ProtocolEntity = UnsubscribePresenceProtocolEntity self.node.setAttribute("type", "unsubscribe") self.node.setAttribute("to", "some_jid")yowsup-2.4.48/yowsup/layers/protocol_privacy/000077500000000000000000000000001263346463600214375ustar00rootroot00000000000000yowsup-2.4.48/yowsup/layers/protocol_privacy/__init__.py000066400000000000000000000000521263346463600235450ustar00rootroot00000000000000from .layer import YowPrivacyProtocolLayeryowsup-2.4.48/yowsup/layers/protocol_privacy/layer.py000066400000000000000000000010271263346463600231250ustar00rootroot00000000000000from yowsup.layers import YowLayer, YowLayerEvent, YowProtocolLayer from .protocolentities import * class YowPrivacyProtocolLayer(YowProtocolLayer): def __init__(self): handleMap = { "iq": (self.recvIq, self.sendIq) } super(YowPrivacyProtocolLayer, self).__init__(handleMap) def __str__(self): return "Privacy Layer" def sendIq(self, entity): if entity.getXmlns() == "jabber:iq:privacy": self.entityToLower(entity) def recvIq(self, node): pass yowsup-2.4.48/yowsup/layers/protocol_privacy/protocolentities/000077500000000000000000000000001263346463600250455ustar00rootroot00000000000000yowsup-2.4.48/yowsup/layers/protocol_privacy/protocolentities/__init__.py000066400000000000000000000000671263346463600271610ustar00rootroot00000000000000from .privacylist_iq import PrivacyListIqProtocolEntityyowsup-2.4.48/yowsup/layers/protocol_privacy/protocolentities/privacylist_iq.py000066400000000000000000000017271263346463600304700ustar00rootroot00000000000000from yowsup.layers.protocol_iq.protocolentities import IqProtocolEntity from yowsup.structs import ProtocolTreeNode class PrivacyListIqProtocolEntity(IqProtocolEntity): def __init__(self, name = "default"): super(PrivacyListIqProtocolEntity, self).__init__("jabber:iq:privacy", _type="get") self.setListName(name) def setListName(self, name): self.listName = name def toProtocolTreeNode(self): node = super(PrivacyListIqProtocolEntity, self).toProtocolTreeNode() queryNode = ProtocolTreeNode("query") listNode = ProtocolTreeNode("list", {"name": self.listName}) queryNode.addChild(listNode) node.addChild(queryNode) return node @staticmethod def fromProtocolTreeNode(node): entity = IqProtocolEntity.fromProtocolTreeNode(node) entity.__class__ = PrivacyListIqProtocolEntity entity.setListName(node.getChild("query").getChild("list")["name"]) return entity yowsup-2.4.48/yowsup/layers/protocol_profiles/000077500000000000000000000000001263346463600216055ustar00rootroot00000000000000yowsup-2.4.48/yowsup/layers/protocol_profiles/__init__.py000066400000000000000000000000531263346463600237140ustar00rootroot00000000000000from .layer import YowProfilesProtocolLayeryowsup-2.4.48/yowsup/layers/protocol_profiles/layer.py000066400000000000000000000052371263346463600233020ustar00rootroot00000000000000from yowsup.layers import YowProtocolLayer from .protocolentities import * from yowsup.layers.protocol_iq.protocolentities import ErrorIqProtocolEntity, ResultIqProtocolEntity class YowProfilesProtocolLayer(YowProtocolLayer): def __init__(self): handleMap = { "iq": (self.recvIq, self.sendIq) } super(YowProfilesProtocolLayer, self).__init__(handleMap) def __str__(self): return "Profiles Layer" def sendIq(self, entity): if entity.getXmlns() == "w:profile:picture": if entity.getType() == "get": self._sendIq(entity, self.onGetPictureResult, self.onGetPictureError) elif entity.getType() == "set": self._sendIq(entity, self.onSetPictureResult, self.onSetPictureError) elif entity.getType() == "delete": self._sendIq(entity, self.onDeletePictureResult, self.onDeletePictureError) elif entity.getXmlns() == "status": self._sendIq(entity, self.onSetStatusResult, self.onSetStatusError) elif entity.getXmlns() == "privacy": self._sendIq(entity, self.onPrivacyResult, self.onPrivacyError) def recvIq(self, node): pass def onPrivacyResult(self, resultNode, originIqRequestEntity): self.toUpper(ResultPrivacyIqProtocolEntity.fromProtocolTreeNode(resultNode)) def onPrivacyError(self, errorNode, originalIqRequestEntity): self.toUpper(ErrorIqProtocolEntity.fromProtocolTreeNode(errorNode)) def onSetStatusResult(self, resultNode, originIqRequestEntity): self.toUpper(ResultIqProtocolEntity.fromProtocolTreeNode(resultNode)) def onSetStatusError(self, errorNode, originalIqRequestEntity): self.toUpper(ErrorIqProtocolEntity.fromProtocolTreeNode(errorNode)) def onGetPictureResult(self, resultNode, originalIqRequestEntity): self.toUpper(ResultGetPictureIqProtocolEntity.fromProtocolTreeNode(resultNode)) def onGetPictureError(self, errorNode, originalIqRequestEntity): self.toUpper(ErrorIqProtocolEntity.fromProtocolTreeNode(errorNode)) def onSetPictureResult(self, resultNode, originalIqRequestEntity): self.toUpper(ResultGetPictureIqProtocolEntity.fromProtocolTreeNode(resultNode)) def onSetPictureError(self, errorNode, originalIqRequestEntity): self.toUpper(ErrorIqProtocolEntity.fromProtocolTreeNode(errorNode)) def onDeletePictureResult(self, resultNode, originalIqRequestEntity): self.toUpper(ResultIqProtocolEntity.fromProtocolTreeNode(resultNode)) def onDeletePictureError(self, errorNode, originalIqRequestEntity): self.toUpper(ErrorIqProtocolEntity.fromProtocolTreeNode(errorNode)) yowsup-2.4.48/yowsup/layers/protocol_profiles/protocolentities/000077500000000000000000000000001263346463600252135ustar00rootroot00000000000000yowsup-2.4.48/yowsup/layers/protocol_profiles/protocolentities/__init__.py000066400000000000000000000010031263346463600273160ustar00rootroot00000000000000from .iq_unregister import UnregisterIqProtocolEntity from .iq_status_set import SetStatusIqProtocolEntity from .iq_picture_get import GetPictureIqProtocolEntity from .iq_picture_get_result import ResultGetPictureIqProtocolEntity from .iq_pictures_list import ListPicturesIqProtocolEntity from .iq_picture_set import SetPictureIqProtocolEntity from .iq_privacy_set import SetPrivacyIqProtocolEntity from .iq_privacy_get import GetPrivacyIqProtocolEntity from .iq_privacy_result import ResultPrivacyIqProtocolEntity yowsup-2.4.48/yowsup/layers/protocol_profiles/protocolentities/iq_picture.py000066400000000000000000000010361263346463600277310ustar00rootroot00000000000000from yowsup.layers.protocol_iq.protocolentities import IqProtocolEntity class PictureIqProtocolEntity(IqProtocolEntity): ''' When receiving a profile picture: {{Binary bytes of the picture.}} ''' XMLNS = "w:profile:picture" def __init__(self, jid, _id = None, type = "get"): super(PictureIqProtocolEntity, self).__init__(self.__class__.XMLNS, _id = _id, _type=type, to = jid)yowsup-2.4.48/yowsup/layers/protocol_profiles/protocolentities/iq_picture_get.py000066400000000000000000000022161263346463600305710ustar00rootroot00000000000000from .iq_picture import PictureIqProtocolEntity from yowsup.structs import ProtocolTreeNode class GetPictureIqProtocolEntity(PictureIqProtocolEntity): ''' ''' def __init__(self, jid, preview = True, _id = None): super(GetPictureIqProtocolEntity, self).__init__(jid, _id, "get") self.setGetPictureProps(preview) def setGetPictureProps(self, preview = True): self.preview = preview def isPreview(self): return self.preview def toProtocolTreeNode(self): node = super(GetPictureIqProtocolEntity, self).toProtocolTreeNode() pictureNode = ProtocolTreeNode("picture", {"type": "preview" if self.isPreview() else "image" }) node.addChild(pictureNode) return node @staticmethod def fromProtocolTreeNode(node): entity = PictureIqProtocolEntity.fromProtocolTreeNode(node) entity.__class__ = GetPictureIqProtocolEntity entity.setGetPictureProps(node.getChild("picture").getAttributeValue("type")) return entityyowsup-2.4.48/yowsup/layers/protocol_profiles/protocolentities/iq_picture_get_result.py000066400000000000000000000033461263346463600321740ustar00rootroot00000000000000from .iq_picture import PictureIqProtocolEntity from yowsup.structs import ProtocolTreeNode class ResultGetPictureIqProtocolEntity(PictureIqProtocolEntity): ''' {{Binary bytes of the picture.}} ''' def __init__(self, jid, pictureData, pictureId, preview = True, _id = None): super(ResultGetPictureIqProtocolEntity, self).__init__(jid, _id, "result") self.setResultPictureProps(pictureData, pictureId, preview) def setResultPictureProps(self, pictureData, pictureId, preview = True): self.preview = preview self.pictureData = pictureData self.pictureId = pictureId def isPreview(self): return self.preview def getPictureData(self): return self.pictureData def getPictureId(self): return self.pictureId def writeToFile(self, path): with open(path, "wb") as outFile: outFile.write(self.getPictureData()) def toProtocolTreeNode(self): node = super(ResultGetPictureIqProtocolEntity, self).toProtocolTreeNode() pictureNode = ProtocolTreeNode({"type": "preview" if self.isPreview() else "image" }, data = self.getPictureData()) node.addChild(pictureNode) return node @staticmethod def fromProtocolTreeNode(node): entity = PictureIqProtocolEntity.fromProtocolTreeNode(node) entity.__class__ = ResultGetPictureIqProtocolEntity pictureNode = node.getChild("picture") entity.setResultPictureProps(pictureNode.getData(), pictureNode.getAttributeValue("id"), pictureNode.getAttributeValue("type") == "preview") return entityyowsup-2.4.48/yowsup/layers/protocol_profiles/protocolentities/iq_picture_set.py000066400000000000000000000044401263346463600306060ustar00rootroot00000000000000from .iq_picture import PictureIqProtocolEntity from yowsup.structs import ProtocolTreeNode import time class SetPictureIqProtocolEntity(PictureIqProtocolEntity): ''' {{Binary bytes of the picture when type is set.}} ''' def __init__(self, jid, previewData, pictureData, pictureId = None, _id = None): super(SetPictureIqProtocolEntity, self).__init__(jid, _id, "set") self.setSetPictureProps(previewData, pictureData, pictureId) def setSetPictureProps(self, previewData, pictureData, pictureId = None): self.setPictureData(pictureData) self.setPictureId(pictureId or str(int(time.time()))) self.setPreviewData(previewData) def setPictureData(self, pictureData): self.pictureData = pictureData def getPictureData(self): return self.pictureData def setPreviewData(self, previewData): self.previewData = previewData def getPreviewData(self): return self.previewData def setPictureId(self, pictureId): self.pictureId = pictureId def getPictureId(self): return self.pictureId def toProtocolTreeNode(self): node = super(PictureIqProtocolEntity, self).toProtocolTreeNode() attribs = {"type": "image", "id": self.pictureId} pictureNode = ProtocolTreeNode("picture", attribs, None, self.getPictureData()) previewNode = ProtocolTreeNode("picture", {"type": "preview"}, None, self.getPreviewData()) node.addChild(pictureNode) node.addChild(previewNode) return node @staticmethod def fromProtocolTreeNode(node): entity = PictureIqProtocolEntity.fromProtocolTreeNode(node) entity.__class__ = SetPictureIqProtocolEntity pictureNode = None previewNode = None for child in node.getAllChildren("picture"): nodeType = child.getAttributeValue("type") if nodeType == "image": pictureNode = child elif nodeType == "preview": previewNode = child entity.setSetPictureProps(previewNode.getData(), pictureNode.getData(), pictureNode.getAttributeValue("id")) return entityyowsup-2.4.48/yowsup/layers/protocol_profiles/protocolentities/iq_pictures_list.py000066400000000000000000000025021263346463600311460ustar00rootroot00000000000000from yowsup.structs import ProtocolEntity, ProtocolTreeNode from .iq_picture import PictureIqProtocolEntity class ListPicturesIqProtocolEntity(PictureIqProtocolEntity): ''' ''' def __init__(self, selfJid, jids): super(ListPicturesIqProtocolEntity, self).__init__(jid = selfJid, type = "get") self.setProps(jids) def setProps(self, jids): assert type(jids) is list and len(jids), "Must specify a list of jids to get the pictures for" self.jids = jids def toProtocolTreeNode(self): node = super(ListPicturesIqProtocolEntity, self).toProtocolTreeNode() userNodes = [ProtocolTreeNode("user", {"jid": jid}) for jid in self.jids] listNode = ProtocolTreeNode("list", {}, userNodes) node.addChild(listNode) return node @staticmethod def fromProtocolTreeNode(node): entity = PictureIqProtocolEntity.fromProtocolTreeNode(node) entity.__class__ = ListPicturesIqProtocolEntity jids = [userNode.getAttributeValue("jid") for userNode in node.getChild("list").getAllChildren()] entity.setProps(jids) return entityyowsup-2.4.48/yowsup/layers/protocol_profiles/protocolentities/iq_privacy_get.py000066400000000000000000000016271263346463600306000ustar00rootroot00000000000000from yowsup.layers.protocol_iq.protocolentities import IqProtocolEntity from yowsup.structs import ProtocolTreeNode ''' ''' class GetPrivacyIqProtocolEntity(IqProtocolEntity): XMLNS = "privacy" def __init__(self): super(GetPrivacyIqProtocolEntity, self).__init__(self.__class__.XMLNS, _type="get") def toProtocolTreeNode(self): node = super(GetPrivacyIqProtocolEntity, self).toProtocolTreeNode() queryNode = ProtocolTreeNode(self.__class__.XMLNS) node.addChild(queryNode) return node @staticmethod def fromProtocolTreeNode(node): assert node.getChild(GetPrivacyIqProtocolEntity.XMLNS) is not None, "Not a get privacy iq node %s" % node entity = IqProtocolEntity.fromProtocolTreeNode(node) entity.__class__ = GetPrivacyIqProtocolEntity return entity yowsup-2.4.48/yowsup/layers/protocol_profiles/protocolentities/iq_privacy_result.py000066400000000000000000000032671263346463600313410ustar00rootroot00000000000000from yowsup.structs import ProtocolTreeNode from yowsup.layers.protocol_iq.protocolentities import ResultIqProtocolEntity ''' ''' class ResultPrivacyIqProtocolEntity(ResultIqProtocolEntity): NODE_PRIVACY="privacy" def __init__(self, privacy): super(ResultPrivacyIqProtocolEntity, self).__init__() self.setProps(privacy) def setProps(self, privacy): assert type(privacy) is dict, "Privacy must be a dict {name => value}" self.privacy = privacy def __str__(self): out = super(ResultPrivacyIqProtocolEntity, self).__str__() out += "Privacy settings\n" for name, value in self.privacy.items(): out += "Category %s --> %s\n" % (name, value) return out def toProtocolTreeNode(self): node = super(ResultPrivacyIqProtocolEntity, self).toProtocolTreeNode() queryNode = ProtocolTreeNode(self.__class__.NODE_PRIVACY) node.addChild(queryNode) return node @staticmethod def fromProtocolTreeNode(node): entity = super(ResultPrivacyIqProtocolEntity, ResultPrivacyIqProtocolEntity).fromProtocolTreeNode(node) entity.__class__ = ResultPrivacyIqProtocolEntity privacyNode = node.getChild(ResultPrivacyIqProtocolEntity.NODE_PRIVACY) privacy = {} for categoryNode in privacyNode.getAllChildren(): privacy[categoryNode["name"]] = categoryNode["value"] entity.setProps(privacy) return entity yowsup-2.4.48/yowsup/layers/protocol_profiles/protocolentities/iq_privacy_set.py000066400000000000000000000050021263346463600306030ustar00rootroot00000000000000from yowsup.layers.protocol_iq.protocolentities import IqProtocolEntity from yowsup.structs import ProtocolTreeNode ''' ''' class SetPrivacyIqProtocolEntity(IqProtocolEntity): NAMES = ["status", "profile", "last"] VALUES = ["all", "contacts", "none"] XMLNS = "privacy" def __init__(self, value="all", names = None): # names can be a string with some element in VALUES or an array with strings with elements in VALUES # by default, all names are used super(SetPrivacyIqProtocolEntity, self).__init__(self.__class__.XMLNS, _type="set") self.setNames(names) self.setValue(value) @staticmethod def checkValidNames(names): names = names if names else SetPrivacyIqProtocolEntity.NAMES if not type(names) is list: names = [names] for name in names: if not name in SetPrivacyIqProtocolEntity.NAMES: raise Exception("Name should be in: '" + "', '".join(SetPrivacyIqProtocolEntity.NAMES) + "' but is '" + name + "'") return names @staticmethod def checkValidValue(value): if not value in SetPrivacyIqProtocolEntity.VALUES: raise Exception("Value should be in: '" + "', '".join(SetPrivacyIqProtocolEntity.VALUES) + "' but is '" + value + "'") return value def setNames(self, names): self.names = SetPrivacyIqProtocolEntity.checkValidNames(names) def setValue(self, value): self.value = SetPrivacyIqProtocolEntity.checkValidValue(value) def toProtocolTreeNode(self): node = super(SetPrivacyIqProtocolEntity, self).toProtocolTreeNode() queryNode = ProtocolTreeNode(self.__class__.XMLNS) for name in self.names: listNode = ProtocolTreeNode("category", {"name": name, "value": self.value}) queryNode.addChild(listNode) node.addChild(queryNode) return node @staticmethod def fromProtocolTreeNode(node): entity = IqProtocolEntity.fromProtocolTreeNode(node) entity.__class__ = SetPrivacyIqProtocolEntity privacyNode = node.getChild(SetPrivacyIqProtocolEntity.XMLNS) names = [] for categoryNode in privacyNode.getAllChildren(): names.append(categoryNode["name"]) entity.setNames(names) entity.setValue("all") return entity yowsup-2.4.48/yowsup/layers/protocol_profiles/protocolentities/iq_status_set.py000066400000000000000000000021141263346463600304520ustar00rootroot00000000000000from yowsup.layers.protocol_iq.protocolentities import IqProtocolEntity from yowsup.structs import ProtocolTreeNode class SetStatusIqProtocolEntity(IqProtocolEntity): ''' {{MSG}} ''' XMLNS = "status" def __init__(self, text = None, _id = None): super(SetStatusIqProtocolEntity, self).__init__(self.__class__.XMLNS, _id, _type = "set", to = "s.whatsapp.net") self.setData(text) def setData(self, text): self.text = text def toProtocolTreeNode(self): node = super(SetStatusIqProtocolEntity, self).toProtocolTreeNode() statusNode = ProtocolTreeNode("status", {}, [], self.text) node.addChild(statusNode) return node @staticmethod def fromProtocolTreeNode(node): entity = IqProtocolEntity.fromProtocolTreeNode(node) entity.__class__ = SetStatusIqProtocolEntity statusNode = node.getChild("status") entity.setData(statusNode.getData()) return entity yowsup-2.4.48/yowsup/layers/protocol_profiles/protocolentities/iq_unregister.py000066400000000000000000000016511263346463600304500ustar00rootroot00000000000000from yowsup.layers.protocol_iq.protocolentities import IqProtocolEntity from yowsup.structs import ProtocolTreeNode class UnregisterIqProtocolEntity(IqProtocolEntity): XMLNS = "urn:xmpp:whatsapp:account" def __init__(self): super(UnregisterIqProtocolEntity, self).__init__(_type = "get", to = "s.whatsapp.net") def toProtocolTreeNode(self): node = super(UnregisterIqProtocolEntity, self).toProtocolTreeNode() rmNode = ProtocolTreeNode("remove", {"xmlns": self.__class__.XMLNS}) node.addChild(rmNode) return node @staticmethod def fromProtocolTreeNode(node): entity = IqProtocolEntity.fromProtocolTreeNode(node) entity.__class__ = UnregisterIqProtocolEntity removeNode = node.getChild("remove") assert removeNode["xmlns"] == UnregisterIqProtocolEntity.XMLNS, "Not an account delete xmlns, got %s" % removeNode["xmlns"] return entityyowsup-2.4.48/yowsup/layers/protocol_profiles/protocolentities/test_iq_privacy_get.py000066400000000000000000000007661263346463600316420ustar00rootroot00000000000000from yowsup.layers.protocol_iq.protocolentities.test_iq import IqProtocolEntityTest from yowsup.layers.protocol_profiles.protocolentities import GetPrivacyIqProtocolEntity from yowsup.structs import ProtocolTreeNode entity = GetPrivacyIqProtocolEntity() class GetPrivacyIqProtocolEntityTest(IqProtocolEntityTest): def setUp(self): super(GetPrivacyIqProtocolEntityTest, self).setUp() self.ProtocolEntity = GetPrivacyIqProtocolEntity self.node = entity.toProtocolTreeNode() yowsup-2.4.48/yowsup/layers/protocol_profiles/protocolentities/test_iq_privacy_result.py000066400000000000000000000010701263346463600323660ustar00rootroot00000000000000from yowsup.layers.protocol_iq.protocolentities.test_iq import IqProtocolEntityTest from yowsup.layers.protocol_profiles.protocolentities import ResultPrivacyIqProtocolEntity from yowsup.structs import ProtocolTreeNode entity = ResultPrivacyIqProtocolEntity({"profile":"all","last":"none","status":"contacts"}) class ResultPrivacyIqProtocolEntityTest(IqProtocolEntityTest): def setUp(self): super(ResultPrivacyIqProtocolEntityTest, self).setUp() self.ProtocolEntity = ResultPrivacyIqProtocolEntity self.node = entity.toProtocolTreeNode() yowsup-2.4.48/yowsup/layers/protocol_profiles/protocolentities/test_iq_privacy_set.py000066400000000000000000000010301263346463600316370ustar00rootroot00000000000000from yowsup.layers.protocol_iq.protocolentities.test_iq import IqProtocolEntityTest from yowsup.layers.protocol_profiles.protocolentities import SetPrivacyIqProtocolEntity from yowsup.structs import ProtocolTreeNode entity = SetPrivacyIqProtocolEntity("all", ["profile","last","status"]) class SetPrivacyIqProtocolEntityTest(IqProtocolEntityTest): def setUp(self): super(SetPrivacyIqProtocolEntityTest, self).setUp() self.ProtocolEntity = SetPrivacyIqProtocolEntity self.node = entity.toProtocolTreeNode() yowsup-2.4.48/yowsup/layers/protocol_profiles/protocolentities/test_iq_status_set.py000066400000000000000000000010331263346463600315100ustar00rootroot00000000000000from yowsup.layers.protocol_iq.protocolentities.test_iq import IqProtocolEntityTest from yowsup.layers.protocol_profiles.protocolentities import SetStatusIqProtocolEntity from yowsup.structs import ProtocolTreeNode class SetStatusIqProtocolEntityTest(IqProtocolEntityTest): def setUp(self): super(SetStatusIqProtocolEntityTest, self).setUp() self.ProtocolEntity = SetStatusIqProtocolEntity statusNode = ProtocolTreeNode("status", {}, [], "Hey there, I'm using WhatsApp") self.node.addChild(statusNode) yowsup-2.4.48/yowsup/layers/protocol_profiles/protocolentities/test_iq_unregister.py000066400000000000000000000007751263346463600315150ustar00rootroot00000000000000from yowsup.layers.protocol_iq.protocolentities.test_iq import IqProtocolEntityTest from yowsup.layers.protocol_profiles.protocolentities import UnregisterIqProtocolEntity from yowsup.structs import ProtocolTreeNode class UnregisterIqProtocolEntityTest(IqProtocolEntityTest): def setUp(self): super(UnregisterIqProtocolEntityTest, self).setUp() self.ProtocolEntity = UnregisterIqProtocolEntity self.node.addChild(ProtocolTreeNode("remove", {"xmlns": "urn:xmpp:whatsapp:account"}))yowsup-2.4.48/yowsup/layers/protocol_receipts/000077500000000000000000000000001263346463600216005ustar00rootroot00000000000000yowsup-2.4.48/yowsup/layers/protocol_receipts/__init__.py000066400000000000000000000000541263346463600237100ustar00rootroot00000000000000from .layer import YowReceiptProtocolLayer yowsup-2.4.48/yowsup/layers/protocol_receipts/layer.py000066400000000000000000000011171263346463600232660ustar00rootroot00000000000000from yowsup.layers import YowLayer, YowLayerEvent, YowProtocolLayer from .protocolentities import * class YowReceiptProtocolLayer(YowProtocolLayer): def __init__(self): handleMap = { "receipt": (self.recvReceiptNode, self.sendReceiptEntity) } super(YowReceiptProtocolLayer, self).__init__(handleMap) def __str__(self): return "Receipt Layer" def sendReceiptEntity(self, entity): self.entityToLower(entity) def recvReceiptNode(self, node): self.toUpper(IncomingReceiptProtocolEntity.fromProtocolTreeNode(node)) yowsup-2.4.48/yowsup/layers/protocol_receipts/protocolentities/000077500000000000000000000000001263346463600252065ustar00rootroot00000000000000yowsup-2.4.48/yowsup/layers/protocol_receipts/protocolentities/__init__.py000066400000000000000000000002421263346463600273150ustar00rootroot00000000000000from .receipt import ReceiptProtocolEntity from .receipt_incoming import IncomingReceiptProtocolEntity from .receipt_outgoing import OutgoingReceiptProtocolEntityyowsup-2.4.48/yowsup/layers/protocol_receipts/protocolentities/receipt.py000066400000000000000000000020331263346463600272110ustar00rootroot00000000000000from yowsup.structs import ProtocolEntity, ProtocolTreeNode class ReceiptProtocolEntity(ProtocolEntity): ''' delivered: read INCOMING ''' def __init__(self, _id): super(ReceiptProtocolEntity, self).__init__("receipt") self._id = _id def getId(self): return self._id def toProtocolTreeNode(self): attribs = { "id" : self._id } return self._createProtocolTreeNode(attribs, None, data = None) def __str__(self): out = "Receipt:\n" out += "ID: %s\n" % self._id return out @staticmethod def fromProtocolTreeNode(node): return ReceiptProtocolEntity( node.getAttributeValue("id") ) yowsup-2.4.48/yowsup/layers/protocol_receipts/protocolentities/receipt_incoming.py000066400000000000000000000107321263346463600311010ustar00rootroot00000000000000from yowsup.structs import ProtocolEntity, ProtocolTreeNode from .receipt import ReceiptProtocolEntity from yowsup.layers.protocol_acks.protocolentities import OutgoingAckProtocolEntity class IncomingReceiptProtocolEntity(ReceiptProtocolEntity): ''' delivered: read delivered to participant in group: read by participant in group: multiple items: multiple items to group: INCOMING ''' def __init__(self, _id, _from, timestamp, offline = None, type = None, participant = None, items = None): super(IncomingReceiptProtocolEntity, self).__init__(_id) self.setIncomingData(_from, timestamp, offline, type, participant, items) def getType(self): return self.type def getParticipant(self): return self.participant def getFrom(self, full = True): return self._from if full else self._from.split('@')[0] def setIncomingData(self, _from, timestamp, offline, type = None, participant = None, items = None): self._from = _from self.timestamp = timestamp self.type = type self.participant = participant if offline is not None: self.offline = True if offline == "1" else False else: self.offline = None self.items = items def toProtocolTreeNode(self): node = super(IncomingReceiptProtocolEntity, self).toProtocolTreeNode() node.setAttribute("from", self._from) node.setAttribute("t", str(self.timestamp)) if self.offline is not None: node.setAttribute("offline", "1" if self.offline else "0") if self.type is not None: node.setAttribute("type", self.type) if self.participant is not None: node.setAttribute("participant", self.participant) if self.items is not None: inodes = [] for item in self.items: inode = ProtocolTreeNode("item", {"id": item}) inodes.append(inode) lnode = ProtocolTreeNode("list") lnode.addChildren(inodes) node.addChild(lnode) return node def __str__(self): out = super(IncomingReceiptProtocolEntity, self).__str__() out += "From: %s\n" % self._from out += "Timestamp: %s\n" % self.timestamp if self.offline is not None: out += "Offline: %s\n" % ("1" if self.offline else "0") if self.type is not None: out += "Type: %s\n" % (self.type) if self.participant is not None: out += "Participant: %s\n" % (self.participant) if self.items is not None: out += "Items: %s\n" % " ".join(self.items) return out def ack(self): return OutgoingAckProtocolEntity(self.getId(), "receipt", self.getType(), self.getFrom()) @staticmethod def fromProtocolTreeNode(node): items = None listNode = node.getChild("list") if listNode is not None: items = [] for inode in listNode.getAllChildren("item"): items.append(inode["id"]) return IncomingReceiptProtocolEntity( node.getAttributeValue("id"), node.getAttributeValue("from"), node.getAttributeValue("t"), node.getAttributeValue("offline"), node.getAttributeValue("type"), node.getAttributeValue("participant"), items ) yowsup-2.4.48/yowsup/layers/protocol_receipts/protocolentities/receipt_outgoing.py000066400000000000000000000055741263346463600311410ustar00rootroot00000000000000import time from yowsup.structs import ProtocolEntity, ProtocolTreeNode from .receipt import ReceiptProtocolEntity class OutgoingReceiptProtocolEntity(ReceiptProtocolEntity): ''' delivered: If we send the following without "to" specified, whatsapp will consider the message delivered, but will not notify the sender. read multiple items: ''' def __init__(self, messageIds, to, read = False, participant = None, callId = None): if type(messageIds) in (list, tuple): if len(messageIds) > 1: receiptId = self._generateId() else: receiptId = messageIds[0] else: receiptId = messageIds messageIds = [messageIds] super(OutgoingReceiptProtocolEntity, self).__init__(receiptId) self.setOutgoingData(messageIds, to, read, participant, callId) def setOutgoingData(self, messageIds, to, read, participant, callId): self.messageIds = messageIds self.to = to self.read = read self.participant = participant self.callId = callId def getMessageIds(self): return self.messageIds def toProtocolTreeNode(self): node = super(OutgoingReceiptProtocolEntity, self).toProtocolTreeNode() if self.read: node.setAttribute("type", "read") if self.participant: node.setAttribute("participant", self.participant) if self.callId: offer = ProtocolTreeNode("offer", {"call-id": self.callId}) node.addChild(offer) node.setAttribute("to", self.to) if len(self.messageIds) > 1: listNode = ProtocolTreeNode("list") listNode.addChildren([ProtocolTreeNode("item", {"id": mId}) for mId in self.messageIds]) node.addChild(listNode) return node def __str__(self): out = super(OutgoingReceiptProtocolEntity, self).__str__() out += "To: \n%s" % self.to if self.read: out += "Type: \n%s" % "read" out += "For: \n%s" % self.messageIds return out @staticmethod def fromProtocolTreeNode(node): listNode = node.getChild("list") messageIds = [] if listNode: messageIds = [child["id"] for child in listNode.getChildren()] else: messageIds = [node["id"]] return OutgoingReceiptProtocolEntity( messageIds, node["to"], node["type"] == "read", node["participant"] ) yowsup-2.4.48/yowsup/layers/protocol_receipts/protocolentities/test_receipt_incoming.py000066400000000000000000000007001263346463600321320ustar00rootroot00000000000000from yowsup.layers.protocol_receipts.protocolentities import IncomingReceiptProtocolEntity from yowsup.structs.protocolentity import ProtocolEntityTest import unittest import time class IncomingReceiptProtocolEntityTest(ProtocolEntityTest, unittest.TestCase): def setUp(self): self.ProtocolEntity = IncomingReceiptProtocolEntity self.node = IncomingReceiptProtocolEntity("123", "sender", int(time.time())).toProtocolTreeNode() yowsup-2.4.48/yowsup/layers/protocol_receipts/protocolentities/test_receipt_outgoing.py000066400000000000000000000006511263346463600321670ustar00rootroot00000000000000from yowsup.layers.protocol_receipts.protocolentities import OutgoingReceiptProtocolEntity from yowsup.structs.protocolentity import ProtocolEntityTest import unittest class OutgoingReceiptProtocolEntityTest(ProtocolEntityTest, unittest.TestCase): def setUp(self): self.ProtocolEntity = OutgoingReceiptProtocolEntity self.node = OutgoingReceiptProtocolEntity("123", "target", "read").toProtocolTreeNode()yowsup-2.4.48/yowsup/layers/stanzaregulator/000077500000000000000000000000001263346463600212665ustar00rootroot00000000000000yowsup-2.4.48/yowsup/layers/stanzaregulator/__init__.py000066400000000000000000000000451263346463600233760ustar00rootroot00000000000000from .layer import YowStanzaRegulatoryowsup-2.4.48/yowsup/layers/stanzaregulator/layer.py000066400000000000000000000030731263346463600227570ustar00rootroot00000000000000from yowsup.layers import YowLayer, YowLayerEvent from yowsup.layers.network import YowNetworkLayer class YowStanzaRegulator(YowLayer): ''' send: bytearray -> bytearray receive: bytearray -> bytearray ''' def __init__(self): super(YowLayer, self).__init__() self.buf = bytearray() self.enabled = False def onEvent(self, yowLayerEvent): if yowLayerEvent.getName() == YowNetworkLayer.EVENT_STATE_CONNECTED: self.enabled = True self.buf = bytearray() elif yowLayerEvent.getName() == YowNetworkLayer.EVENT_STATE_DISCONNECTED: self.enabled = False def send(self, data): self.toLower(data) def receive(self, data): if self.enabled: self.buf.extend(data) self.processReceived() else: self.toLower(data) def processReceived(self): metaData = self.buf[:3] recvData = self.buf[3:] firstByte = metaData[0] stanzaFlag = (firstByte & 0xF0) >> 4 stanzaSize = ((metaData[1] << 8) + metaData[2]) | ((firstByte & 0x0F) << 16) if len(recvData) < stanzaSize: #will in leave in buf till receive remaining data return oneMessageData = metaData + recvData[:stanzaSize] self.buf = self.buf[len(oneMessageData):] self.toUpper(oneMessageData) if len(self.buf) > 3: #min required if has processable data yet self.processReceived() def __str__(self): return "Stanza Regulator Layer" yowsup-2.4.48/yowsup/registration/000077500000000000000000000000001263346463600172545ustar00rootroot00000000000000yowsup-2.4.48/yowsup/registration/__init__.py000066400000000000000000000001661263346463600213700ustar00rootroot00000000000000from .coderequest import WACodeRequest from .existsrequest import WAExistsRequest from .regrequest import WARegRequestyowsup-2.4.48/yowsup/registration/coderequest.py000066400000000000000000000034041263346463600221520ustar00rootroot00000000000000from yowsup.common.http.warequest import WARequest from yowsup.common.http.waresponseparser import JSONResponseParser # from yowsup.env import CURRENT_ENV from yowsup.common.tools import StorageTools, WATools from yowsup.registration.existsrequest import WAExistsRequest from yowsup.env import S40YowsupEnv CURRENT_ENV = S40YowsupEnv() class WACodeRequest(WARequest): def __init__(self,cc, p_in, mcc= "000", mnc = "000", sim_mcc = "000", sim_mnc = "000", method="sms"): super(WACodeRequest,self).__init__() idx = StorageTools.getIdentity(cc + p_in) self.p_in = p_in self.__id = idx self.cc = cc self.addParam("cc", cc) self.addParam("in", p_in) self.addParam("lc", "GB") self.addParam("lg", "en") self.addParam("sim_mcc", sim_mcc.zfill(3)) self.addParam("sim_mnc", sim_mnc.zfill(3)) self.addParam("method", method) self.addParam("token", CURRENT_ENV.getToken(p_in)) self.url = "v.whatsapp.net/v2/code" self.pvars = ["status","reason","length", "method", "retry_after", "code", "param"] +\ ["login", "pw", "type", "expiration", "kind", "price", "cost", "currency", "price_expiration"] self.setParser(JSONResponseParser()) def send(self, parser = None): if self.__id is not None: request = WAExistsRequest(self.cc, self.p_in, self.__id) result = request.send() if result["status"] == "ok": return result self.__id = WATools.generateIdentity() self.addParam("id", self.__id) res = super(WACodeRequest, self).send(parser) if res["status"] == "sent": StorageTools.writeIdentity(self.cc + self.p_in, self.__id) return res yowsup-2.4.48/yowsup/registration/existsrequest.py000066400000000000000000000016451263346463600225640ustar00rootroot00000000000000from yowsup.common.http.warequest import WARequest from yowsup.common.http.waresponseparser import JSONResponseParser from yowsup.env import CURRENT_ENV class WAExistsRequest(WARequest): def __init__(self,cc, p_in, idx): super(WAExistsRequest,self).__init__() self.addParam("cc", cc) self.addParam("in", p_in) self.addParam("id", idx) self.addParam("lg", "en") self.addParam("lc", "GB") self.addParam("token", CURRENT_ENV.getToken(p_in)) self.url = "v.whatsapp.net/v2/exist" self.pvars = ["status", "reason", "sms_length", "voice_length", "result","param", "pw", "login", "type", "expiration", "kind", "price", "cost", "currency", "price_expiration" ] self.setParser(JSONResponseParser()) def send(self, parser = None): res = super(WAExistsRequest, self).send(parser) return resyowsup-2.4.48/yowsup/registration/regrequest.py000066400000000000000000000036761263346463600220300ustar00rootroot00000000000000''' Copyright (c) <2012> Tarek Galal Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ''' from yowsup.common.http.warequest import WARequest from yowsup.common.http.waresponseparser import JSONResponseParser from yowsup.common.tools import StorageTools class WARegRequest(WARequest): def __init__(self,cc, p_in, code): super(WARegRequest,self).__init__() idx = StorageTools.getIdentity(cc + p_in) if idx is None: raise ValueError("You have to request code first") self.addParam("cc", cc) self.addParam("in", p_in) self.addParam("id", idx) self.addParam("code", code) self.url = "v.whatsapp.net/v2/register" self.pvars = ["status", "login", "pw", "type", "expiration", "kind", "price", "cost", "currency", "price_expiration", "reason","retry_after"] self.setParser(JSONResponseParser()) def register(self): return self.send()yowsup-2.4.48/yowsup/stacks/000077500000000000000000000000001263346463600160325ustar00rootroot00000000000000yowsup-2.4.48/yowsup/stacks/__init__.py000066400000000000000000000051141263346463600201440ustar00rootroot00000000000000from .yowstack import YowStack, YowStackBuilder from yowsup.layers.auth import YowCryptLayer, YowAuthenticationProtocolLayer, AuthError from yowsup.layers.coder import YowCoderLayer from yowsup.layers.logger import YowLoggerLayer from yowsup.layers.network import YowNetworkLayer from yowsup.layers.protocol_messages import YowMessagesProtocolLayer from yowsup.layers.stanzaregulator import YowStanzaRegulator from yowsup.layers.protocol_media import YowMediaProtocolLayer from yowsup.layers.protocol_acks import YowAckProtocolLayer from yowsup.layers.protocol_receipts import YowReceiptProtocolLayer from yowsup.layers.protocol_groups import YowGroupsProtocolLayer from yowsup.layers.protocol_presence import YowPresenceProtocolLayer from yowsup.layers.protocol_ib import YowIbProtocolLayer from yowsup.layers.protocol_notifications import YowNotificationsProtocolLayer from yowsup.layers.protocol_iq import YowIqProtocolLayer from yowsup.layers.protocol_contacts import YowContactsIqProtocolLayer from yowsup.layers.protocol_chatstate import YowChatstateProtocolLayer from yowsup.layers.protocol_privacy import YowPrivacyProtocolLayer from yowsup.layers.protocol_profiles import YowProfilesProtocolLayer from yowsup.layers.protocol_calls import YowCallsProtocolLayer YOWSUP_CORE_LAYERS = ( YowLoggerLayer, YowCoderLayer, YowCryptLayer, YowStanzaRegulator, YowNetworkLayer ) YOWSUP_PROTOCOL_LAYERS_BASIC = ( YowAuthenticationProtocolLayer, YowMessagesProtocolLayer, YowReceiptProtocolLayer, YowAckProtocolLayer, YowPresenceProtocolLayer, YowIbProtocolLayer, YowIqProtocolLayer, YowNotificationsProtocolLayer, YowContactsIqProtocolLayer, YowChatstateProtocolLayer ) YOWSUP_PROTOCOL_LAYERS_GROUPS = (YowGroupsProtocolLayer,) + YOWSUP_PROTOCOL_LAYERS_BASIC YOWSUP_PROTOCOL_LAYERS_MEDIA = (YowMediaProtocolLayer,) + YOWSUP_PROTOCOL_LAYERS_BASIC YOWSUP_PROTOCOL_LAYERS_PROFILES = (YowProfilesProtocolLayer,) + YOWSUP_PROTOCOL_LAYERS_BASIC YOWSUP_PROTOCOL_LAYERS_CALLS = (YowCallsProtocolLayer,) + YOWSUP_PROTOCOL_LAYERS_BASIC YOWSUP_PROTOCOL_LAYERS_FULL = (YowGroupsProtocolLayer, YowMediaProtocolLayer, YowPrivacyProtocolLayer, YowProfilesProtocolLayer, YowCallsProtocolLayer)\ + YOWSUP_PROTOCOL_LAYERS_BASIC YOWSUP_FULL_STACK = (YOWSUP_PROTOCOL_LAYERS_FULL,) +\ YOWSUP_CORE_LAYERS yowsup-2.4.48/yowsup/stacks/yowstack.py000066400000000000000000000205401263346463600202510ustar00rootroot00000000000000from yowsup.layers import YowParallelLayer import asyncore, time, logging, random from yowsup.layers import YowLayer from yowsup.layers.auth import YowCryptLayer, YowAuthenticationProtocolLayer from yowsup.layers.coder import YowCoderLayer from yowsup.layers.logger import YowLoggerLayer from yowsup.layers.network import YowNetworkLayer from yowsup.layers.protocol_messages import YowMessagesProtocolLayer from yowsup.layers.stanzaregulator import YowStanzaRegulator from yowsup.layers.protocol_media import YowMediaProtocolLayer from yowsup.layers.protocol_acks import YowAckProtocolLayer from yowsup.layers.protocol_receipts import YowReceiptProtocolLayer from yowsup.layers.protocol_groups import YowGroupsProtocolLayer from yowsup.layers.protocol_presence import YowPresenceProtocolLayer from yowsup.layers.protocol_ib import YowIbProtocolLayer from yowsup.layers.protocol_notifications import YowNotificationsProtocolLayer from yowsup.layers.protocol_iq import YowIqProtocolLayer from yowsup.layers.protocol_contacts import YowContactsIqProtocolLayer from yowsup.layers.protocol_chatstate import YowChatstateProtocolLayer from yowsup.layers.protocol_privacy import YowPrivacyProtocolLayer from yowsup.layers.protocol_profiles import YowProfilesProtocolLayer from yowsup.layers.protocol_calls import YowCallsProtocolLayer from yowsup import env from yowsup.common.constants import YowConstants import inspect try: import Queue except ImportError: import queue as Queue logger = logging.getLogger(__name__) YOWSUP_PROTOCOL_LAYERS_BASIC = ( YowAuthenticationProtocolLayer, YowMessagesProtocolLayer, YowReceiptProtocolLayer, YowAckProtocolLayer, YowPresenceProtocolLayer, YowIbProtocolLayer, YowIqProtocolLayer, YowNotificationsProtocolLayer, YowContactsIqProtocolLayer, YowChatstateProtocolLayer, YowCallsProtocolLayer ) class YowStackBuilder(object): def __init__(self): self.layers = () self._props = {} def setProp(self, key, value): self._props[key] = value def pushDefaultLayers(self, axolotl = False): defaultLayers = YowStackBuilder.getDefaultLayers(axolotl) self.layers += defaultLayers return self def push(self, yowLayer): self.layers += (yowLayer,) return self def pop(self): self.layers = self.layers[:-1] return self def build(self): return YowStack(self.layers, reversed = False, props = self._props) @staticmethod def getDefaultLayers(axolotl = False, groups = True, media = True, privacy = True, profiles = True): coreLayers = YowStackBuilder.getCoreLayers() protocolLayers = YowStackBuilder.getProtocolLayers(groups = groups, media=media, privacy=privacy, profiles=profiles) allLayers = coreLayers if axolotl: from yowsup.layers.axolotl import YowAxolotlLayer allLayers += (YowAxolotlLayer,) allLayers += (YowParallelLayer(protocolLayers),) return allLayers @staticmethod def getDefaultStack(layer = None, axolotl = False, groups = True, media = True, privacy = True, profiles = True): """ :param layer: An optional layer to put on top of default stack :param axolotl: E2E encryption enabled/ disabled :return: YowStack """ allLayers = YowStackBuilder.getDefaultLayers(axolotl, groups = groups, media=media,privacy=privacy, profiles=profiles) if layer: allLayers = allLayers + (layer,) return YowStack(allLayers, reversed = False) @staticmethod def getCoreLayers(): return ( YowLoggerLayer, YowCoderLayer, YowCryptLayer, YowStanzaRegulator, YowNetworkLayer )[::-1] @staticmethod def getProtocolLayers(groups = True, media = True, privacy = True, profiles = True): layers = YOWSUP_PROTOCOL_LAYERS_BASIC if groups: layers += (YowGroupsProtocolLayer,) if media: layers += (YowMediaProtocolLayer, ) if privacy: layers += (YowPrivacyProtocolLayer, ) if profiles: layers += (YowProfilesProtocolLayer, ) return layers class YowStack(object): __stack = [] __stackInstances = [] __detachedQueue = Queue.Queue() def __init__(self, stackClassesArr = None, reversed = True, props = None): stackClassesArr = stackClassesArr or () self.__stack = stackClassesArr[::-1] if reversed else stackClassesArr self.__stackInstances = [] self._props = props or {} self.setProp(YowNetworkLayer.PROP_ENDPOINT, YowConstants.ENDPOINTS[random.randint(0,len(YowConstants.ENDPOINTS)-1)]) self.setProp(YowCoderLayer.PROP_DOMAIN, YowConstants.DOMAIN) self.setProp(YowCoderLayer.PROP_RESOURCE, env.CURRENT_ENV.getResource()) self._construct() def getLayerInterface(self, YowLayerClass): for inst in self.__stackInstances: if inst.__class__ == YowLayerClass: return inst.getLayerInterface() elif inst.__class__ == YowParallelLayer: res = inst.getLayerInterface(YowLayerClass) if res: return res def send(self, data): self.__stackInstances[-1].send(data) def receive(self, data): self.__stackInstances[0].receive(data) def setCredentials(self, credentials): self.getLayerInterface(YowAuthenticationProtocolLayer).setCredentials(*credentials) def addLayer(self, layerClass): self.__stack.push(layerClass) def addPostConstructLayer(self, layer): self.__stackInstances[-1].setLayers(layer, self.__stackInstances[-2]) layer.setLayers(None, self.__stackInstances[-1]) self.__stackInstances.append(layer) def setProp(self, key, value): self._props[key] = value def getProp(self, key, default = None): return self._props[key] if key in self._props else default def emitEvent(self, yowLayerEvent): if not self.__stackInstances[0].onEvent(yowLayerEvent): self.__stackInstances[0].emitEvent(yowLayerEvent) def broadcastEvent(self, yowLayerEvent): if not self.__stackInstances[-1].onEvent(yowLayerEvent): self.__stackInstances[-1].broadcastEvent(yowLayerEvent) def execDetached(self, fn): self.__class__.__detachedQueue.put(fn) def loop(self, *args, **kwargs): if "discrete" in kwargs: discreteVal = kwargs["discrete"] del kwargs["discrete"] while True: asyncore.loop(*args, **kwargs) time.sleep(discreteVal) try: callback = self.__class__.__detachedQueue.get(False) #doesn't block callback() except Queue.Empty: pass else: asyncore.loop(*args, **kwargs) def _construct(self): logger.debug("Initializing stack") for s in self.__stack: if type(s) is tuple: logger.warn("Implicit declaration of parallel layers in a tuple is deprecated, pass a YowParallelLayer instead") inst = YowParallelLayer(s) else: if inspect.isclass(s): if issubclass(s, YowLayer): inst = s() else: raise ValueError("Stack must contain only subclasses of YowLayer") elif issubclass(s.__class__, YowLayer): inst = s else: raise ValueError("Stack must contain only subclasses of YowLayer") #inst = s() logger.debug("Constructed %s" % inst) inst.setStack(self) self.__stackInstances.append(inst) for i in range(0, len(self.__stackInstances)): upperLayer = self.__stackInstances[i + 1] if (i + 1) < len(self.__stackInstances) else None lowerLayer = self.__stackInstances[i - 1] if i > 0 else None self.__stackInstances[i].setLayers(upperLayer, lowerLayer) def getLayer(self, layerIndex): return self.__stackInstances[layerIndex] yowsup-2.4.48/yowsup/structs/000077500000000000000000000000001263346463600162515ustar00rootroot00000000000000yowsup-2.4.48/yowsup/structs/__init__.py000066400000000000000000000001311263346463600203550ustar00rootroot00000000000000from .protocolentity import ProtocolEntity from .protocoltreenode import ProtocolTreeNodeyowsup-2.4.48/yowsup/structs/protocolentity.py000066400000000000000000000027021263346463600217220ustar00rootroot00000000000000from .protocoltreenode import ProtocolTreeNode import unittest, time class ProtocolEntity(object): __ID_GEN = 0 def __init__(self, tag): self.tag = tag def getTag(self): return self.tag def isType(self, typ): return self.tag == typ def _createProtocolTreeNode(self, attributes, children = None, data = None): return ProtocolTreeNode(self.getTag(), attributes, children, data) def _getCurrentTimestamp(self): return int(time.time()) def _generateId(self, short = False): ProtocolEntity.__ID_GEN += 1 return str(ProtocolEntity.__ID_GEN) if short else str(int(time.time())) + "-" + str(ProtocolEntity.__ID_GEN) def toProtocolTreeNode(self): pass @staticmethod def fromProtocolTreeNode(self, protocolTreeNode): pass class ProtocolEntityTest(object): def setUp(self): self.ProtocolEntity = None self.node = None # def assertEqual(self, entity, node): # raise AssertionError("Should never execute that") def test_generation(self): if self.ProtocolEntity is None: raise ValueError("Test case not setup!") entity = self.ProtocolEntity.fromProtocolTreeNode(self.node) try: self.assertEqual(entity.toProtocolTreeNode(), self.node) except: print(entity.toProtocolTreeNode()) print("\nNOTEQ\n") print(self.node) raise yowsup-2.4.48/yowsup/structs/protocoltreenode.py000066400000000000000000000112121263346463600222070ustar00rootroot00000000000000import binascii import sys class ProtocolTreeNode(object): def __init__(self, tag, attributes = None, children = None, data = None): self.tag = tag self.attributes = attributes or {} self.children = children or [] self.data = data assert type(self.children) is list, "Children must be a list, got %s" % type(self.children) def __eq__(self, protocolTreeNode): """ :param protocolTreeNode: ProtocolTreeNode :return: bool """ # if protocolTreeNode.__class__ == ProtocolTreeNode\ and self.tag == protocolTreeNode.tag\ and self.data == protocolTreeNode.data\ and self.attributes == protocolTreeNode.attributes\ and len(self.getAllChildren()) == len(protocolTreeNode.getAllChildren()): found = False for c in self.getAllChildren(): for c2 in protocolTreeNode.getAllChildren(): if c == c2: found = True break if not found: return False found = False for c in protocolTreeNode.getAllChildren(): for c2 in self.getAllChildren(): if c == c2: found = True break if not found: return False return True return False def __hash__(self): return hash(self.tag) ^ hash(tuple(self.attributes.items())) ^ hash(self.data) def toString(self): out = "<"+self.tag if self.attributes is not None: for key,val in self.attributes.items(): out+= " "+key+'="'+val+'"' out+= ">\n" if self.data is not None: if type(self.data) is bytearray: try: out += "%s" % self.data.decode() except UnicodeDecodeError: out += binascii.hexlify(self.data) else: try: out += "%s" % self.data except UnicodeDecodeError: try: out += "%s" % self.data.decode() except UnicodeDecodeError: out += binascii.hexlify(self.data) if type(self.data) is str and sys.version_info >= (3,0): out += "\nHEX3:%s\n" % binascii.hexlify(self.data.encode('latin-1')) else: out += "\nHEX:%s\n" % binascii.hexlify(self.data) for c in self.children: try: out += c.toString() except UnicodeDecodeError: out += "[ENCODED DATA]\n" out+= "\n" return out def __str__(self): return self.toString() def getData(self): return self.data def setData(self, data): self.data = data @staticmethod def tagEquals(node,string): return node is not None and node.tag is not None and node.tag == string @staticmethod def require(node,string): if not ProtocolTreeNode.tagEquals(node,string): raise Exception("failed require. string: "+string); def __getitem__(self, key): return self.getAttributeValue(key) def __setitem__(self, key, val): self.setAttribute(key, val) def __delitem__(self, key): self.removeAttribute(key) def getChild(self,identifier): if type(identifier) == int: if len(self.children) > identifier: return self.children[identifier] else: return None for c in self.children: if identifier == c.tag: return c return None def hasChildren(self): return len(self.children) > 0 def addChild(self, childNode): self.children.append(childNode) def addChildren(self, children): for c in children: self.addChild(c) def getAttributeValue(self,string): try: return self.attributes[string] except KeyError: return None def removeAttribute(self, key): if key in self.attributes: del self.attributes[key] def setAttribute(self, key, value): self.attributes[key] = value def getAllChildren(self,tag = None): ret = [] if tag is None: return self.children for c in self.children: if tag == c.tag: ret.append(c) return ret