pax_global_header 0000666 0000000 0000000 00000000064 13464333726 0014525 g ustar 00root root 0000000 0000000 52 comment=e73432bdfb36ec32bf89d400382f9b152153b9d3
yowsup-3.2.3/ 0000775 0000000 0000000 00000000000 13464333726 0013100 5 ustar 00root root 0000000 0000000 yowsup-3.2.3/.gitignore 0000664 0000000 0000000 00000000075 13464333726 0015072 0 ustar 00root root 0000000 0000000 *.pyc
*.class
todo
*.egg-info
tp
tests
dist
build
.idea
.tox
yowsup-3.2.3/.travis.yml 0000664 0000000 0000000 00000001273 13464333726 0015214 0 ustar 00root root 0000000 0000000 language: python
python: '3.6'
# command to install dependencies
env:
global:
- LD_PRELOAD=/lib/x86_64-linux-gnu/libSegFault.so
- SEGFAULT_SIGNALS=all
matrix:
- TOXENV=py27
- TOXENV=py33
- TOXENV=py34
- TOXENV=py35
- TOXENV=py36
- TOXENV=py37
before_install:
- python --version
- uname -a
- lsb_release -a
install:
- pip install tox
- virtualenv --version
- easy_install --version
- pip --version
- tox --version
# command to run tests
script:
- tox -v
after_failure:
- more .tox/log/* | cat
- more .tox/*/log/* | cat
before_cache:
- rm -rf $HOME/.cache/pip/log
cache:
directories:
- $HOME/.cache/pip
branches:
only:
- master
yowsup-3.2.3/CHANGELOG.md 0000664 0000000 0000000 00000025603 13464333726 0014717 0 ustar 00root root 0000000 0000000 # Changelog
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project (kinda) adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
## [3.2.3] 2019-05-07
### Changed
- Fixed incoming message output format in cli demo
## [3.2.2] 2019-05-07
### Changed
- Updated python-axolotl to 0.2.2, fixes possible variable referenced before assignment error
## [3.2.1] 2019-05-07
### Changed
- Updated python-axolotl to 0.2.1
- Fixed encoding errors when communicating in group
- Fixed messages not delivered to groups, showing a "Waiting for this message, this may take a while"
- Fixed bug where getKeys for multiple jids would invoke the callback multiple times
- Fixes in RequestUpload and media classes in preparation for media sending
### Added
- More log output in AxolotlSendLayer
## [3.2.0] 2019-05-04
### Changed
- Set min protobuf version to fix an error
- Use WhatsApp version set by env in noise layer
- Fixed error when mcc,mnc and fdid were missing from config
- Don't crash when received an unrecognized ib node
- Don't crash when received an unrecognized media type and send receipt
- Don't crash when received an unrecognized notification type and send receipt
- Asyncore is now used as default ConnectionDispatcher
- Received protobuf messages are now handled in upper layers rather than Axolotl
### Added
- MediaCipher for encrypting and decrypting media files
- "media" yowsup-cli action with encrypt and decrypt media commands
- Receive Audio, Video, Image, Document, Contact, Location, GIF, URL message support
- MediaSink demo, access by yowsup-cli demos --mediasink
### Removed
- unused -w flag from yowsup-cli config
## [3.1.0] 2019-04-25
### Changed
- Network layer prevents createConnection if already connected
- Fixed crash when config path does not exist
- yowsup-cli will interpret -c as phone if load_path fails
- Allow keypair in credentials to be bytes
- Noise layer now uses credential's client_static_keypair if set, instead of loading it from stored config
- Improved config type detection logic, refs #2664
- Fixed some python2-related problems (long-type phone numbers, missing list.clear() method), refs #2664
- Updated consonance to fix dissononce's machine.next and enforce cryptography>=0.25
- Fixed some demos not shutting down properly
### Added
- Complete asyncore dispatcher implementation.
- Support for decoding deflate compressed data, fixes #2671
- Specifying a connection dispatcher (asyncore/socket) using YowNetworkLayer.PROP_DISPATCHER
- --layer-network-dispatcher to cli demos
### Removed
- threading from socket dispatcher, connecting application should ensure the connection is not blocking, for
example by triggering connect in a bg thread.
## [3.0.0] 2019-04-23
### Changed
- Changed default env to android
- Updated whatsapp version in env to 2.19.51
- Updated logs formatting to be more compact
- Changed storage dir on linux to ~/.config/yowsup
- yowsup-cli -p is now used for preview requests rather than specifying phone number
- Decoupled Axolotl management from Axolotl layer
- Fixed Python3.7 support
- Updated device details in Env to be of Samsung S9+
- Changed generated signed prekeys ids to be sequential
- Fixed some notifications getting redundant acks
- Fixed outgoing ack in a group now requiring participant to be specified
### Added
- WhatsApp Protocol 2.1 support
- Noise layer
- Login using Consonance; a new dependency
- New Registration parameters
- Encryption of registration parameters
- Auto saving of Config at registration
- Log which endpoint we are connecting to
- Support superadmin and multiple admins in group create notification
- Better Config management and JSON config files support
- AxolotlManager
- Any Config property overriding in yowsup-cli
- yowsup-cli config
- yowsup-cli --log-dissononce
- yowsup-cli --log-dissononce
- Preview only registration and other http requests
### Removed
- Optional axolotl/e2e enc enabling, it's now forced.
- S40 env
- Password from Config
- Outdated http parameters in registration
- TimeTools along with python-dateutil dependency.
## [2.5.7] - 2017-12-30
### Changed
- Changed Token
- Fixed Python2 support
- Fixed #1842: Bug in protocol_groups RemoveGroupsNotificationProtocolEntity
## [2.5.2] - 2017-03-23
### Changed
- Fixed xml-not-well-formed when data is sent from multiple threads simultaneously
- Updated S40 Token
## [2.5.0] - 2016-05-22
### Changed
- Fixed python 2.6 support
- Fixed block detection in exists request, initiated by code request
- Fixed crash when node data is string
- Updated s40 token to 2.16.7
- Fixed timestamp in authentication not being UTC
- Fixed handling variant decrypt/encr fail scenarios
### Added
- Allowing autotrust changed identities via an exposed layer property
- Auto-reconnect on stream:error
- WA1.6 support
- Fully working group encryption support
## [2.4.103] - 2016-04-24
### Changed
- Updated token
## [2.4.102] - 2016-04-01
### Added
- Simpler env select using YowsupEnv.setEnv("env_name"), get using YowsupEnv.getCurrent()
- yowsup-cli allows setting preferred env using -E/--env argument
## [2.4.98] - 2016-03-31
### Changed
- Minor README update
## [2.4.97] - 2016-03-31
### Changed
- pillow, axolotl and ffvideo as optional modules
- Improved mimetypes detection in media sending
- Fixed some group Iqs callbacks getting swallowed and never invoked
- Fixed python3 compat in iq_statuses_result
- Fixed asyncore initialization
- Updated tokens and fixed registration
- Skip encryption of group messages
- Improved video sending support
- Fixed URL to country codes in yowsup-cli help
### Added
- New optional modules interface
- New @EventCallback decoration to replace layer's onEvent method
- echo and send clients now enable encryption by default
- Can now send videos from cli demo
- Added *BSD installation instructions
## [2.4.48] - 2015-12-14
### Changed
- Fixed bug that avoid some acks from being sent
- Check fields in video message before parsing
- Fixed image scaling in Palette mode
- Fixed image preview
- Fixed erroneous method in LiteAxolotlStore
- Fixed YowParallelLayer returning layer instead of the layer's interface
- Fixed login
- Updated registration token
- Updated android env data
- Fixed Warning that demos are not using YowParallelLayer
### Added
- Send read receipts for received messages in cli demo
- Can now get status of users
- new profile privacy options
## [2.4.0] - 2015-09-07
### Changed
- Updated S40 env to 2.12.96
- Fixed message forwarding
- Don't panic on try send something when offline
- Fixed interface not forwarding to upper layers unhandled protocolenties
- Don't crash on UntrustedIdentityException, will silently ignore the message
- E2E enc is now enabled by default, remove -m/--moxie switch
### Added
- Support sending receipt for multiple messages
- Layers can now expose an InterfaceLayer for outside interaction
- YowNetworkLayer and Auth Layer now expose an InterfaceLayer
- Allow setting props on stackbuilder, it passed them to the instantiated stack
- Handle DuplicateMessageException
- Added stack.send/receive
- Opt-out E2E enc using -M/--unmoxie
### Removed
- yowsup-cli's -m/--moxie switch
## [2.3.185] - 2015-08-01
### Changed
- Recover from possible no session/no prekey in a received message
### Added
- Send/receive v2 enc messages
## [2.3.183] - 2015-07-27
### Changed
- Fixed audio send
- improved cli demo usage display
### Added
- random endpoints selection
- Handle account ib
- "/audio send" to cli demo
- support for image caption in cli demo
## [2.3.167] - 2015-07-21
### Changed
- Updated to e16 serv
- Fixed callbacks for group info iq
- Use s40 env by default
- Updated to s40 v2.12.189
- Fixed error in android env with python 2.6
- Deprecated --moxie
- Fixed error when axolotl is not installed
### Added
- Added contact sync notification
- Optional arguments support in yowsup demo
### Removed
- "av" from enc nodes
## [2.3.124] - 2015-07-06
### Changed
- Fixed forward in groups
## [2.3.123] - 2015-06-22
### Changed
- Some code clean ups
- Fixed set status and set picture not triggering callbacks
- Handle multiple items in receipt
### Added
- Create an ack or a forwarded message directly from receipt message
- Allow getting Id of set profile picture
- Get contact's last seen time
- Notifications for participants add,remove in a group
- Receipts from participants in a group
- Promote,demote participants and rest of groups version 2 support
- New contacts sync demo
- New groups commands: /group promote, /group demote
- New contacts commands: /contact lastseen
## [2.3.84] - 2015-05-26
### Changed
- Updated s40 tokens
- Updated android token
- Fixed receive presence
- Fixed ack errors
- Propagate StreamFeaturesProtocolEntity to upper layers
- Fixes to incoming receipt
- Don't stream error on web notifications
- Fixed keys_get in cli demo
- Fixed invite to group in cli demo
### Added
- Allowing to specify ping interval
- Connect behind http proxy support
- Audio and video receive support
- Get contact's profile picture
- Handle calls
- Group info v2
- Kick from group in cli demo
## [2.2.78] - 2015-02-17
### Changed
- Fixed problem reading identity which caused reg error
- Keep connection alive through periodic pinging
- Fixed compatibility with the whole python 2.6-3.4 spectrum
- Distinguish received delivered and read receipt
- Fixed leave groups
- Fixes to registration
- Updated S40 registration token
- Fixed groups jid handling in sendclient
- Fixed readline redundant dependency in linux
### Added
- StackBuilder to make stack construction easier
- Profile Layer
- participants to a group
- Save next challenge and use in next auth
- Get contact profile picture
- group_invite in cli demo to add participants to a group
- leave_group in cli demo
## [2.2.15] - 2015-01-12
### Changed
- As of January 2015, Yowsup is GPLv3 licensed (previouly was MIT)
- Fixed broadcast
- Fixed registration no_routes error
- Updated registration token
### Added
- Experimental Axolotl support (end-to-end encryption)
- Upload and send images
- Initial support for groups v2
- Easy switch/ add new enviornment (S40/Android ..etc)
- _sendIq in YowProtocolLayer and YowInterfaceLayer with callbacks for Iq result and error
- new send and exit demo
- E2E encryption in yowsup and echo client demos
- image_send to yowsup demo
## [2.0.53] - 2014-12-15
### Changed
- Upgraded to WA 1.5
- Fixed previews in images
- Write date to socket as they come
- Fixed readline/pyreadline dependency problem
### Added
- Add chatstate support (typing/ paused)
- support for send/recv location
- support for send/recv vcards
- potential fix for not receiving registration sms
- Pass pongs to upper layers
- Ack notifications
- Parallels layers now get events sent by siblings
- Broadcast event on login
- send typing/paused state to cli demo
- Echo demo now echoes images
- Echo demo now echoes vcards
## [2.0.1] - 2014-12-01
### Changed
- Minor bug fixes
## [2.0] - 2014-11-28
yowsup 2.0 initial release
yowsup-3.2.3/LICENSE 0000664 0000000 0000000 00000104462 13464333726 0014114 0 ustar 00root root 0000000 0000000 GNU 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-3.2.3/MANIFEST.in 0000664 0000000 0000000 00000000041 13464333726 0014631 0 ustar 00root root 0000000 0000000 include yowsup/common/mime.types
yowsup-3.2.3/README.md 0000664 0000000 0000000 00000005645 13464333726 0014371 0 ustar 00root root 0000000 0000000 # yowsup [](https://travis-ci.org/tgalal/yowsup)
yowsup is a python library that enables building applications that can communicate with WhatsApp users.
The project started as the protocol engine behind [Wazapp for Meego](https://wiki.maemo.org/Wazapp) and
[OpenWA for BB10](https://www.lowyat.net/2013/5896/try-this-openwhatsapp-for-blackberry-10/). Now as a standalone
library it can be used to power any custom WhatsApp client.
```
updated: 2019-05-07
yowsup version: 3.2.3
yowsup-cli version: 3.2.0
requires:
- python>=2.7,<=3.7
- consonance==0.1.2
- python-axolotl==0.2.2
- protobuf>=3.6.0
- six==1.10
uses:
- argparse [yowsup-cli]
- readline [yowsup-cli]
- pillow [send images]
- tqdm [mediasink demo]
- requests [mediasink demo]
```
## See also
During maintenance of yowsup, several projects have been spawned out in order to support different features that get
introduced by WhatsApp. Some of those features are not necessarily exclusive to WhatsApp and therefore it only made
sense to maintain some parts as standalone projects:
- [python-axolotl](https://github.com/tgalal/python-axolotl): Python port of
[libsignal-protocol-java](https://github.com/signalapp/libsignal-protocol-java), providing E2E encryption
- [consonance](https://github.com/tgalal/consonance/): WhatsApp's handshake implementation using Noise Protocol
- [dissononce](https://github.com/tgalal/dissononce): A python implementation for
[Noise Protocol Framework](https://noiseprotocol.org/)
## Quickstart
* **[Installation](#installation)**
* **[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)**
## Installation
Install using setup.py to pull all Python dependencies, or pip:
```
pip install yowsup
```
### Linux
You need to have installed Python headers (probably from python-dev package) and ncurses-dev, then run
```
python setup.py install
```
### FreeBSD (*BSD)
You need to have installed: py27-pip-7.1.2(+), py27-sqlite3-2.7.11_7(+), then run
```
pip install yowsup
```
### Mac OS
```
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```
# License:
As of January 1, 2015 yowsup is licensed under the GPLv3+: http://www.gnu.org/licenses/gpl-3.0.html.
yowsup-3.2.3/setup.py 0000775 0000000 0000000 00000003007 13464333726 0014615 0 ustar 00root root 0000000 0000000 #!/usr/bin/env python
from __future__ import print_function
from setuptools import setup, find_packages
import yowsup
import platform
import sys
deps = ['consonance==0.1.2', 'argparse', 'python-axolotl==0.2.2', 'six==1.10', 'appdirs', 'protobuf>=3.6.0']
if sys.version_info < (2, 7):
deps.append('importlib')
if platform.system().lower() == "windows":
deps.append('pyreadline')
else:
try:
import readline
except ImportError:
deps.append('readline')
setup(
name='yowsup',
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='The WhatsApp lib',
#long_description=long_description,
packages= find_packages(),
include_package_data=True,
data_files = [('yowsup/common', ['yowsup/common/mime.types'])],
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-3.2.3/tox.ini 0000664 0000000 0000000 00000001014 13464333726 0014407 0 ustar 00root root 0000000 0000000 # Tox (http://tox.testrun.org/) is a tool for running tests
# in multiple virtualenvs. This configuration file will run the
# test suite on all supported python versions. To use it, "pip install tox"
# and then run "tox" from this directory.
[tox]
skip_missing_interpreters = true
envlist = py27, py32, py33, py34, py35, py36, py37
[testenv]
commands = nosetests --exclude demos yowsup
deps =
py26: importlib
nose
python-dateutil
appdirs
python-axolotl==0.2.2
protobuf>=3.6.0
consonance==0.1.2
yowsup-3.2.3/yowsup-cli 0000775 0000000 0000000 00000065106 13464333726 0015151 0 ustar 00root root 0000000 0000000 #!/usr/bin/env python
__version__ = "3.2.0"
__author__ = "Tarek Galal"
from yowsup.env import YowsupEnv
from yowsup.config.manager import ConfigManager
from yowsup.config.v1.config import Config
from yowsup import logger as yowlogger, formatter
from yowsup.layers.network.layer import YowNetworkLayer
from yowsup.layers.protocol_media.mediacipher import MediaCipher
from consonance.structs.publickey import PublicKey
from consonance.structs.keypair import KeyPair
import sys, argparse, yowsup, logging
import base64
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
#
# Your pushname, this name is displayed to users when they're notified with your messages.
pushname=yowsup
#
# This keypair is generated during registration.
client_static_keypair=YJa8Vd9pG0KV2tDYi5V+DMOtSvCEFzRGCzOlGZkvBHzJvBE5C3oC2Fruniw0GBGo7HHgR4TjvjI3C9AihStsVg=="
#######################################################
For the full list of configuration options run "yowsup-cli config -h"
"""
CR_TEXT = """yowsup-cli v{cliVersion}
yowsup v{yowsupVersion}
Copyright (c) 2012-2019 Tarek Galal
http://www.openwhatsapp.org
This software is provided free of charge. Copying and redistribution is
encouraged.
If you appreciate this software and you would like to support future
development please consider donating:
http://openwhatsapp.org/yowsup/donate
"""
logger = logging.getLogger('yowsup-cli')
ch = logging.StreamHandler()
ch.setLevel(logging.DEBUG)
# add formatter to ch
ch.setFormatter(formatter)
# add ch to logger
logger.addHandler(ch)
class YowArgParser(argparse.ArgumentParser):
def __init__(self, *args, **kwargs):
if "no_config" in kwargs:
self._no_config = kwargs["no_config"] is True
del kwargs["no_config"]
else:
self._no_config = False
super(YowArgParser, self).__init__(*args, **kwargs)
self._config_manager = ConfigManager() if not self._no_config else None
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("-E", "--env",
action="store",
help="Set the environment yowsup simulates",
choices=YowsupEnv.getRegisteredEnvs()
)
self.add_argument("--help-config", help="Prints a config file sample", action="store_true")
if not self._no_config:
config_group = self.add_argument_group(
"Configuration options",
description="Only some of the configuration parameters are required depending on the action being "
"performed using yowsup"
)
config_group.add_argument(
"-c", '--config',
metavar="path",
action="store",
help="(optional) Path to config file. Other configuration arguments have higher priority if given, and "
"will override those specified in the config file."
)
config_group.add_argument(
'--config-phone', '--phone',
action="store",
help="Your full phone number including the country code you defined in 'cc',"
" without preceeding '+' or '00'"
)
config_group.add_argument(
'--config-cc', '--cc',
action="store",
help="Country code. See http://www.ipipi.com/networkList.do."
)
config_group.add_argument(
'--config-pushname',
action="store",
help="Push/Display name to use "
)
config_group.add_argument(
'--config-id',
action="store",
help="Base64 encoded Identity/Recovery token, typically generated and used during registration or account "
"recovery."
)
config_group.add_argument(
'--config-mcc', '--mcc',
action="store",
help="Mobile Country Code. Check your mcc here: https://en.wikipedia.org/wiki/Mobile_country_code"
)
config_group.add_argument(
'--config-mnc', '--mnc',
action="store",
help="Mobile Network Code. Check your mnc from https://en.wikipedia.org/wiki/Mobile_country_code"
)
config_group.add_argument(
'--config-sim_mcc',
action="store",
help="Mobile Country Code. Check your mcc here: https://en.wikipedia.org/wiki/Mobile_country_code"
)
config_group.add_argument(
'--config-sim_mnc',
action="store",
help="Mobile Network Code. Check your mnc from https://en.wikipedia.org/wiki/Mobile_country_code"
)
config_group.add_argument(
'--config-client_static_keypair',
action="store",
help="Base64 encoded concatenation of user keypair's private bytes and public bytes"
)
config_group.add_argument(
'--config-server_static_public',
action="store",
help="Base64 encoded server's public key bytes"
)
config_group.add_argument(
'--config-expid',
action="store",
help="Base64 encoded expid, typically generated and used during registration"
)
config_group.add_argument(
'--config-fdid',
action="store",
help="Device UUID, typically generated for registration and used at login"
)
config_group.add_argument(
'--config-edge_routing_info',
action="store",
help="Base64 encoded edge_routing_info, normally received and persisted right after a successful login"
)
config_group.add_argument(
'--config-chat_dns_domain',
action="store",
help="Chat DNS domain, normally received and persisted right after a successful login"
)
self.args = {}
self._config = None # type: Config
def getArgs(self):
return self.parse_args()
def process(self):
self.args = vars(self.parse_args())
if self.args["debug"]:
logger.setLevel(logging.DEBUG)
yowlogger.setLevel(level=logging.DEBUG)
else:
logger.setLevel(logging.INFO)
yowlogger.setLevel(level=logging.INFO)
if self.args["env"]:
YowsupEnv.setEnv(self.args["env"])
if not self._no_config:
config_phone = self.args["config_phone"]
if self.args["config"]:
self._config = self._config_manager.load_path(self.args["config"])
if self._config is None:
self._config = self._config_manager.load(self.args["config"])
elif config_phone:
self._config = self._config_manager.load(config_phone)
else:
raise ValueError("Must specify either --config or --config-phone")
if self._config is None:
self._config = Config()
if config_phone is not None:
self._config.phone = config_phone
if self.args["config_cc"]:
self._config.cc = self.args["config_cc"]
if self.args["config_pushname"]:
self._config.pushname = self.args["config_pushname"]
if self.args["config_id"]:
self._config.id = base64.b64decode(self.args["config_id"])
if self.args["config_mcc"]:
self._config.mcc = self.args["config_mcc"]
if self.args["config_mnc"]:
self._config.mnc = self.args["config_mnc"]
if self.args["config_sim_mcc"]:
self._config.sim_mcc = self.args["config_sim_mcc"]
if self.args["config_sim_mnc"]:
self._config.sim_mnc = self.args["config_sim_mnc"]
if self.args["config_client_static_keypair"]:
self._config.client_static_keypair = KeyPair.from_bytes(
base64.b64decode(self.args["config_client_static_keypair"])
)
if self.args["config_server_static_public"]:
self._config.server_static_public = PublicKey(
base64.b64decode(self.args["config_server_static_public"])
)
if self.args["config_expid"]:
self._config.expid = base64.b64decode(self.args["config_expid"])
if self.args["config_fdid"]:
self._config.fdid = self.args["config_fdid"]
if self.args["config_edge_routing_info"]:
self._config.edge_routing_info = base64.b64decode(self.args["config_edge_routing_info"])
if self.args["config_chat_dns_domain"]:
self._config.chat_dns_domain = self.args["config_chat_dns_domain"]
if self.args["config"]:
# config file was explicitly specified, load internal config and override values
internal_config = self._config_manager.load(self._config.phone)
if internal_config is not None:
for property in self._config.keys():
if property != "version" and self._config[property] is not None:
internal_config[property] = self._config[property]
self._config = internal_config
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)
def printInfoText(self):
print(CR_TEXT.format(cliVersion=__version__, yowsupVersion=yowsup.__version__))
class ConfigArgParser(YowArgParser):
def __init__(self, *args, **kwargs):
super(ConfigArgParser, self).__init__(*args, **kwargs)
self.description = "Yowsup configuration actions"
gp = self.add_argument_group("Yowsup Config Actions")
exgp = gp.add_mutually_exclusive_group()
exgp.add_argument("-p", '--preview-config', help='Preview yowsup config', action="store",
choices=("json", "keyval"), required=False)
def process(self):
super(ConfigArgParser, self).process()
preview_format = self.args["preview_config"]
if preview_format == "json":
print(self._config_manager.config_to_str(self._config, ConfigManager.TYPE_JSON))
elif preview_format == "keyval":
print(self._config_manager.config_to_str(self._config, ConfigManager.TYPE_KEYVAL))
elif preview_format == None:
pass
return True
class RegistrationArgParser(YowArgParser):
def __init__(self, *args, **kwargs):
super(RegistrationArgParser, self).__init__(*args, **kwargs)
self.description = "WhatsApp Registration options"
self.add_argument('--no-encrypt', action="store_true", help="Don't encrypt request parameters before sending")
self.add_argument('-p', '--preview', action="store_true",
help="Preview requests only, will not attempt to connect and send")
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")
self._encrypt = True
self._preview = False
def process(self):
super(RegistrationArgParser, self).process()
config = self._config
self._encrypt = not self.args["no_encrypt"]
self._preview = self.args["preview"]
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 set --config-cc (country code)"
assert "phone" in config, "Must set --config-phone"
except AssertionError as e:
print(e)
print("\n")
return False
if not str(config.phone).startswith(str(config.cc)):
print("Error, phone number does not start with the specified country code\n")
return False
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
self.printInfoText()
codeReq = WACodeRequest(method, config)
result = codeReq.send(encrypt=self._encrypt, preview=self._preview)
if not self._preview:
if result["status"] in ("sent", "ok"):
if "edge_routing_info" in result:
self._config.edge_routing_info = base64.b64decode(result["edge_routing_info"])
if "chat_dns_domain" in result:
self._config.chat_dns_domain = result["chat_dns_domain"]
self._config_manager.save(self._config)
print(self.resultToString(result))
else:
print(config)
def handleRegister(self, code, config):
from yowsup.registration import WARegRequest
self.printInfoText()
code = code.replace('-', '')
req = WARegRequest(config, code)
result = req.send(preview=self._preview)
print(config)
if not self._preview:
if result["status"] == "ok":
if "edge_routing_info" in result:
self._config.edge_routing_info = base64.b64decode(result["edge_routing_info"])
if "chat_dns_domain" in result:
self._config.chat_dns_domain = result["chat_dns_domain"]
self._config_manager.save(self._config)
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 MediaToolsArgParser(YowArgParser):
MEDIA_INFO = {
"image": MediaCipher.INFO_IMAGE,
"video": MediaCipher.INFO_VIDEO,
"gif": MediaCipher.INFO_VIDEO,
"document": MediaCipher.INFO_DOCUM,
"doc": MediaCipher.INFO_DOCUM
}
def __init__(self, *args, **kwargs):
kwargs["no_config"] = True
super(MediaToolsArgParser, self).__init__(*args, **kwargs)
self.description = "Yowsup tools"
gp = self.add_argument_group("Media Tools")
gp.add_argument(
'--media-type',
choices=('image', 'video', 'gif', 'document', 'doc'),
required=True
)
exgp = gp.add_mutually_exclusive_group()
exgp.add_argument(
'--encrypt',
nargs=3,
metavar=('path', 'b64key', 'output'),
help='Encrypt a media file. Example: yowsup-cli media --media-type image --encrypt /path/to/media.enc '
'AAAA /path/to/out',
action="store",
required=False
)
exgp.add_argument(
'--encrypt2',
metavar='b64key',
help='Encrypt a media file using stdin and stdout for input and output. Example:\nyowsup-cli media '
'--media-type image --encrypt2 AAAA < /path/to/media.enc > /path/to/out',
action="store",
required=False
)
exgp.add_argument(
'--decrypt',
nargs=3,
metavar=('path', 'b64key', 'output'),
help='Decrypt a media file. Example: yowsup-cli media --media-type image --decrypt /path/to/media.enc '
'AAAA /path/to/out',
action="store",
required=False
)
exgp.add_argument(
'--decrypt2',
metavar='b64key',
help='Decrypt a media file using stdin and stdout for input and output. Example:\nyowsup-cli media '
'--media-type image --decrypt2 AAAA < /path/to/media.enc > /path/to/out',
action="store",
required=False
)
def _decrypt_media(self, media_type, b64key, fin, fout):
decrypted = MediaCipher().decrypt(
fin.read(),
base64.b64decode(b64key),
self.MEDIA_INFO[media_type]
)
fout.write(decrypted)
def _encrypt_media(self, media_type, b64key, fin, fout):
encrypted = MediaCipher().encrypt(
fin.read(),
base64.b64decode(b64key),
self.MEDIA_INFO[media_type]
)
fout.write(encrypted)
def process(self):
super(MediaToolsArgParser, self).process()
if self.args["decrypt"]:
path, key, output = self.args["decrypt"]
with open(path, 'rb') as input_media:
with open(output, 'wb') as output_media:
self._decrypt_media(self.args["media_type"], key, input_media, output_media)
elif self.args["decrypt2"]:
fin, fout = sys.stdin, sys.stdout
if sys.version_info >= (3, 0):
fin, fout = fin.buffer, fout.buffer
self._decrypt_media(self.args["media_type"], self.args["decrypt2"], fin, fout)
elif self.args["encrypt"]:
path, key, output = self.args["encrypt"]
with open(path, 'rb') as input_media:
with open(output, 'wb') as output_media:
self._encrypt_media(self.args["media_type"], key, input_media, output_media)
elif self.args["encrypt2"]:
fin, fout = sys.stdin, sys.stdout
if sys.version_info >= (3, 0):
fin, fout = fin.buffer, fout.buffer
self._encrypt_media(self.args["media_type"], self.args["encrypt2"], fin, fout)
return True
class DemosArgParser(YowArgParser):
LAYER_NETWORK_DISPATCHERS_MAP = {
"socket": YowNetworkLayer.DISPATCHER_SOCKET,
"asyncore": YowNetworkLayer.DISPATCHER_ASYNCORE
}
def __init__(self, *args, **kwargs):
super(DemosArgParser, self).__init__(*args, **kwargs)
self.description = "Run a yowsup demo"
net_layer_opts = self.add_argument_group("Network layer props")
net_layer_opts.add_argument(
'--layer-network-dispatcher', action="store", choices=("asyncore", "socket"),
help="Specify which connection dispatcher to use"
)
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"))
mediasinkOpts = self.add_argument_group("Media sink demo")
mediasinkOpts.add_argument('-m', '--mediasink', action="store_true",
help="Start the Media Sink client")
mediasinkOpts.add_argument('--media-store-dir', action="store", required=False,
help="Specify where to download incoming media files, if not set "
"will download to a temporary directory.")
logging = self.add_argument_group("Logging options")
logging.add_argument("--log-dissononce", action="store_true", help="Configure logging for dissononce/noise")
logging.add_argument("--log-consonance", action="store_true", help="Configure logging for consonance")
self._layer_network_dispatcher = None
def process(self):
super(DemosArgParser, self).process()
if self.args["log_dissononce"]:
from dissononce import logger as dissononce_logger, ch as dissononce_ch
dissononce_logger.setLevel(logger.level)
dissononce_ch.setFormatter(formatter)
if self.args["log_consonance"]:
from consonance import logger as consonance_logger, ch as consonance_ch
consonance_logger.setLevel(logger.level)
consonance_ch.setFormatter(formatter)
if self.args["layer_network_dispatcher"] is not None:
self._layer_network_dispatcher = self.LAYER_NETWORK_DISPATCHERS_MAP[
self.args["layer_network_dispatcher"]
]
if self.args["yowsup"]:
self.startCmdline()
elif self.args["echo"]:
self.startEcho()
elif self.args["send"]:
self.startSendClient()
elif self.args["sync"]:
self.startSyncContacts()
elif self.args["mediasink"]:
self.startMediaSink(self.args["media_store_dir"])
else:
return False
return True
def startCmdline(self):
logger.debug("starting cmd")
from yowsup.demos import cli
credentials = self._config.phone, self._config.client_static_keypair
if not credentials:
print("Error: You must specify a configuration method")
sys.exit(1)
self.printInfoText()
stack = cli.YowsupCliStack(credentials)
if self._layer_network_dispatcher is not None:
stack.set_prop(YowNetworkLayer.PROP_DISPATCHER, self._layer_network_dispatcher)
stack.start()
def startEcho(self):
from yowsup.demos import echoclient
credentials = self._config.phone, self._config.client_static_keypair
if not credentials:
print("Error: You must specify a configuration method")
sys.exit(1)
try:
self.printInfoText()
stack = echoclient.YowsupEchoStack(credentials)
if self._layer_network_dispatcher is not None:
stack.set_prop(YowNetworkLayer.PROP_DISPATCHER, self._layer_network_dispatcher)
stack.start()
except KeyboardInterrupt:
print("\nYowsdown")
sys.exit(0)
def startSendClient(self):
from yowsup.demos import sendclient
credentials = self._config.phone, self._config.client_static_keypair
if not credentials:
print("Error: You must specify a configuration method")
sys.exit(1)
try:
self.printInfoText()
stack = sendclient.YowsupSendStack(credentials, [([self.args["send"][0], self.args["send"][1]])])
if self._layer_network_dispatcher is not None:
stack.set_prop(YowNetworkLayer.PROP_DISPATCHER, self._layer_network_dispatcher)
stack.start()
except KeyboardInterrupt:
print("\nYowsdown")
sys.exit(0)
def startSyncContacts(self):
from yowsup.demos import contacts
credentials = self._config.phone, self._config.client_static_keypair
if not credentials:
print("Error: You must specify a configuration method")
sys.exit(1)
try:
self.printInfoText()
stack = contacts.YowsupSyncStack(credentials, self.args["sync"].split(','))
if self._layer_network_dispatcher is not None:
stack.set_prop(YowNetworkLayer.PROP_DISPATCHER, self._layer_network_dispatcher)
stack.start()
except KeyboardInterrupt:
print("\nYowsdown")
sys.exit(0)
def startMediaSink(self, storage_dir):
from yowsup.demos import mediasink
credentials = self._config.phone, self._config.client_static_keypair
if not credentials:
print("Error: You must specify a configuration method")
sys.exit(1)
self.printInfoText()
stack = mediasink.MediaSinkStack(credentials, storage_dir)
if self._layer_network_dispatcher is not None:
stack.set_prop(YowNetworkLayer.PROP_DISPATCHER, self._layer_network_dispatcher)
try:
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,
"config": ConfigArgParser,
"media": MediaToolsArgParser,
"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-3.2.3/yowsup/ 0000775 0000000 0000000 00000000000 13464333726 0014446 5 ustar 00root root 0000000 0000000 yowsup-3.2.3/yowsup/__init__.py 0000664 0000000 0000000 00000000625 13464333726 0016562 0 ustar 00root root 0000000 0000000 import logging
__version__ = "3.2.3"
__author__ = "Tarek Galal"
logger = logging.getLogger(__name__)
# create console handler and set level to debug
ch = logging.StreamHandler()
ch.setLevel(logging.DEBUG)
# create formatter
formatter = logging.Formatter('%(levelname).1s %(asctime)s %(name)s - %(message)s')
# add formatter to ch
ch.setFormatter(formatter)
# add ch to logger
logger.addHandler(ch)
yowsup-3.2.3/yowsup/axolotl/ 0000775 0000000 0000000 00000000000 13464333726 0016130 5 ustar 00root root 0000000 0000000 yowsup-3.2.3/yowsup/axolotl/__init__.py 0000664 0000000 0000000 00000000065 13464333726 0020242 0 ustar 00root root 0000000 0000000 import logging
logger = logging.getLogger(__name__)
yowsup-3.2.3/yowsup/axolotl/exceptions.py 0000664 0000000 0000000 00000000767 13464333726 0020675 0 ustar 00root root 0000000 0000000 class NoSessionException(Exception):
pass
class UntrustedIdentityException(Exception):
def __init__(self, name, identity_key):
self._name = name
self._identity_key = identity_key
@property
def name(self):
return self._name
@property
def identity_key(self):
return self._identity_key
class InvalidMessageException(Exception):
pass
class InvalidKeyIdException(Exception):
pass
class DuplicateMessageException(Exception):
pass
yowsup-3.2.3/yowsup/axolotl/factory.py 0000664 0000000 0000000 00000001024 13464333726 0020146 0 ustar 00root root 0000000 0000000 from yowsup.axolotl.manager import AxolotlManager
from yowsup.common.tools import StorageTools
from yowsup.axolotl.store.sqlite.liteaxolotlstore import LiteAxolotlStore
import logging
logger = logging.getLogger(__name__)
class AxolotlManagerFactory(object):
DB = "axolotl.db"
def get_manager(self, username):
logger.debug("get_manager(username=%s)" % username)
dbpath = StorageTools.constructPath(username, self.DB)
store = LiteAxolotlStore(dbpath)
return AxolotlManager(store, username)
yowsup-3.2.3/yowsup/axolotl/manager.py 0000664 0000000 0000000 00000026717 13464333726 0020131 0 ustar 00root root 0000000 0000000 from axolotl.util.keyhelper import KeyHelper
from axolotl.identitykeypair import IdentityKeyPair
from axolotl.groups.senderkeyname import SenderKeyName
from axolotl.axolotladdress import AxolotlAddress
from axolotl.sessioncipher import SessionCipher
from axolotl.groups.groupcipher import GroupCipher
from axolotl.groups.groupsessionbuilder import GroupSessionBuilder
from axolotl.sessionbuilder import SessionBuilder
from axolotl.protocol.prekeywhispermessage import PreKeyWhisperMessage
from axolotl.protocol.whispermessage import WhisperMessage
from axolotl.state.prekeybundle import PreKeyBundle
from axolotl.untrustedidentityexception import UntrustedIdentityException
from axolotl.invalidmessageexception import InvalidMessageException
from axolotl.duplicatemessagexception import DuplicateMessageException
from axolotl.invalidkeyidexception import InvalidKeyIdException
from axolotl.nosessionexception import NoSessionException
from axolotl.protocol.senderkeydistributionmessage import SenderKeyDistributionMessage
from axolotl.state.axolotlstore import AxolotlStore
from yowsup.axolotl.store.sqlite.liteaxolotlstore import LiteAxolotlStore
from yowsup.axolotl import exceptions
import random
import logging
import sys
logger = logging.getLogger(__name__)
class AxolotlManager(object):
COUNT_GEN_PREKEYS = 812
THRESHOLD_REGEN = 10
MAX_SIGNED_PREKEY_ID = 16777215
def __init__(self, store, username):
"""
:param store:
:type store: AxolotlStore
:param username:
:type username: str
"""
self._username = username # type: str
self._store = store # type: LiteAxolotlStore
self._identity = self._store.getIdentityKeyPair() # type: IdentityKeyPair
self._registration_id = self._store.getLocalRegistrationId() # type: int | None
assert self._registration_id is not None
assert self._identity is not None
self._group_session_builder = GroupSessionBuilder(self._store) # type: GroupSessionBuilder
self._session_ciphers = {} # type: dict[str, SessionCipher]
self._group_ciphers = {} # type: dict[str, GroupCipher]
logger.debug("Initialized AxolotlManager [username=%s, db=%s]" % (self._username, store))
@property
def registration_id(self):
return self._registration_id
@property
def identity(self):
return self._identity
def level_prekeys(self, force=False):
logger.debug("level_prekeys(force=%s)" % force)
pending_prekeys = self._store.loadPreKeys()
logger.debug("len(pending_prekeys) = %d" % len(pending_prekeys))
if force or len(pending_prekeys) < self.THRESHOLD_REGEN:
count_gen = self.COUNT_GEN_PREKEYS - len(pending_prekeys)
logger.info("Generating %d prekeys" % count_gen)
## arbitrary, should keep track of generated prekey ids and create from there
prekeys = KeyHelper.generatePreKeys(KeyHelper.getRandomSequence(2**32 // 2), count_gen)
logger.info("Storing %d prekeys" % len(prekeys))
for i in range(0, len(prekeys)):
key = prekeys[i]
if logger.level <= logging.DEBUG:
sys.stdout.write("Storing prekey %d/%d \r" % (i + 1, len(prekeys)))
sys.stdout.flush()
self._store.storePreKey(key.getId(), key)
return prekeys
return []
def load_unsent_prekeys(self):
logger.debug("load_unsent_prekeys")
unsent = self._store.preKeyStore.loadUnsentPendingPreKeys()
if len(unsent) > 0:
logger.info("Loaded %d unsent prekeys" % len(unsent))
return unsent
def set_prekeys_as_sent(self, prekeyIds):
"""
:param prekeyIds:
:type prekeyIds: list
:return:
:rtype:
"""
logger.debug("set_prekeys_as_sent(prekeyIds=[%d prekeyIds])" % len(prekeyIds))
self._store.preKeyStore.setAsSent([prekey.getId() for prekey in prekeyIds])
def generate_signed_prekey(self):
logger.debug("generate_signed_prekey")
latest_signed_prekey = self.load_latest_signed_prekey(generate=False)
if latest_signed_prekey is not None:
if latest_signed_prekey.getId() == self.MAX_SIGNED_PREKEY_ID:
new_signed_prekey_id = (self.MAX_SIGNED_PREKEY_ID / 2) + 1
else:
new_signed_prekey_id = latest_signed_prekey.getId() + 1
else:
new_signed_prekey_id = 0
signed_prekey = KeyHelper.generateSignedPreKey(self._identity, new_signed_prekey_id)
self._store.storeSignedPreKey(signed_prekey.getId(), signed_prekey)
return signed_prekey
def load_latest_signed_prekey(self, generate=False):
logger.debug("load_latest_signed_prekey")
signed_prekeys = self._store.loadSignedPreKeys()
if len(signed_prekeys):
return signed_prekeys[-1]
return self.generate_signed_prekey() if generate else None
def _get_session_cipher(self, recipientid):
logger.debug("get_session_cipher(recipientid=%s)" % recipientid)
if recipientid in self._session_ciphers:
session_cipher = self._session_ciphers[recipientid]
else:
session_cipher= SessionCipher(self._store, self._store, self._store, self._store, recipientid, 1)
self._session_ciphers[recipientid] = session_cipher
return session_cipher
def _get_group_cipher(self, groupid, username):
logger.debug("get_group_cipher(groupid=%s, username=%s)" % (groupid, username))
senderkeyname = SenderKeyName(groupid, AxolotlAddress(username, 0))
if senderkeyname in self._group_ciphers:
group_cipher = self._group_ciphers[senderkeyname]
else:
group_cipher = GroupCipher(self._store.senderKeyStore, senderkeyname)
self._group_ciphers[senderkeyname] = group_cipher
return group_cipher
def _generate_random_padding(self):
logger.debug("generate_random_padding")
num = random.randint(1,255)
return bytes(bytearray([num] * num))
def _unpad(self, data):
padding_byte = data[-1] if type(data[-1]) is int else ord(data[-1]) # bec inconsistent API?
padding = padding_byte & 0xFF
return data[:-padding]
def encrypt(self, recipient_id, message):
logger.debug("encrypt(recipientid=%s, message=%s)" % (recipient_id, message))
"""
:param recipient_id:
:type recipient_id: str
:param data:
:type data: bytes
:return:
:rtype:
"""
cipher = self._get_session_cipher(recipient_id)
return cipher.encrypt(message + self._generate_random_padding())
def decrypt_pkmsg(self, senderid, data, unpad):
logger.debug("decrypt_pkmsg(senderid=%s, data=(omitted), unpad=%s)" % (senderid, unpad))
pkmsg = PreKeyWhisperMessage(serialized=data)
try:
plaintext = self._get_session_cipher(senderid).decryptPkmsg(pkmsg)
return self._unpad(plaintext) if unpad else plaintext
except NoSessionException:
raise exceptions.NoSessionException()
except InvalidKeyIdException:
raise exceptions.InvalidKeyIdException()
except InvalidMessageException:
raise exceptions.InvalidMessageException()
except DuplicateMessageException:
raise exceptions.DuplicateMessageException()
def decrypt_msg(self, senderid, data, unpad):
logger.debug("decrypt_msg(senderid=%s, data=[omitted], unpad=%s)" % (senderid, unpad))
msg = WhisperMessage(serialized=data)
try:
plaintext = self._get_session_cipher(senderid).decryptMsg(msg)
return self._unpad(plaintext) if unpad else plaintext
except NoSessionException:
raise exceptions.NoSessionException()
except InvalidKeyIdException:
raise exceptions.InvalidKeyIdException()
except InvalidMessageException:
raise exceptions.InvalidMessageException()
except DuplicateMessageException:
raise exceptions.DuplicateMessageException()
def group_encrypt(self, groupid, message):
"""
:param groupid:
:type groupid: str
:param message:
:type message: bytes
:return:
:rtype:
"""
logger.debug("group_encrypt(groupid=%s, message=%s)" % (groupid, message))
group_cipher = self._get_group_cipher(groupid, self._username)
return group_cipher.encrypt(message + self._generate_random_padding())
def group_decrypt(self, groupid, participantid, data):
logger.debug("group_decrypt(groupid=%s, participantid=%s, data=[omitted])" % (groupid, participantid))
group_cipher = self._get_group_cipher(groupid, participantid)
try:
plaintext = group_cipher.decrypt(data)
plaintext = self._unpad(plaintext)
return plaintext
except NoSessionException:
raise exceptions.NoSessionException()
except DuplicateMessageException:
raise exceptions.DuplicateMessageException()
def group_create_skmsg(self, groupid):
logger.debug("group_create_skmsg(groupid=%s)" % groupid)
senderKeyName = SenderKeyName(groupid, AxolotlAddress(self._username, 0))
return self._group_session_builder.create(senderKeyName)
def group_create_session(self, groupid, participantid, skmsgdata):
"""
:param groupid:
:type groupid: str
:param participantid:
:type participantid: str
:param skmsgdata:
:type skmsgdata: bytearray
:return:
:rtype:
"""
logger.debug("group_create_session(groupid=%s, participantid=%s, skmsgdata=[omitted])"
% (groupid, participantid))
senderKeyName = SenderKeyName(groupid, AxolotlAddress(participantid, 0))
senderkeydistributionmessage = SenderKeyDistributionMessage(serialized=skmsgdata)
self._group_session_builder.process(senderKeyName, senderkeydistributionmessage)
def create_session(self, username, prekeybundle, autotrust=False):
"""
:param username:
:type username: str
:param prekeybundle:
:type prekeybundle: PreKeyBundle
:return:
:rtype:
"""
logger.debug("create_session(username=%s, prekeybundle=[omitted], autotrust=%s)" % (username, autotrust))
session_builder = SessionBuilder(self._store, self._store, self._store, self._store, username, 1)
try:
session_builder.processPreKeyBundle(prekeybundle)
except UntrustedIdentityException as ex:
if autotrust:
self.trust_identity(ex.getName(), ex.getIdentityKey())
else:
raise exceptions.UntrustedIdentityException(ex.getName(), ex.getIdentityKey())
def session_exists(self, username):
"""
:param username:
:type username: str
:return:
:rtype:
"""
logger.debug("session_exists(%s)?" % username)
return self._store.containsSession(username, 1)
def load_senderkey(self, groupid):
logger.debug("load_senderkey(groupid=%s)" % groupid)
senderkeyname = SenderKeyName(groupid, AxolotlAddress(self._username, 0))
return self._store.loadSenderKey(senderkeyname)
def trust_identity(self, recipientid, identitykey):
logger.debug("trust_identity(recipientid=%s, identitykey=[omitted])" % recipientid)
self._store.saveIdentity(recipientid, identitykey)
yowsup-3.2.3/yowsup/axolotl/store/ 0000775 0000000 0000000 00000000000 13464333726 0017264 5 ustar 00root root 0000000 0000000 yowsup-3.2.3/yowsup/axolotl/store/__init__.py 0000664 0000000 0000000 00000000000 13464333726 0021363 0 ustar 00root root 0000000 0000000 yowsup-3.2.3/yowsup/axolotl/store/sqlite/ 0000775 0000000 0000000 00000000000 13464333726 0020565 5 ustar 00root root 0000000 0000000 yowsup-3.2.3/yowsup/axolotl/store/sqlite/__init__.py 0000664 0000000 0000000 00000000000 13464333726 0022664 0 ustar 00root root 0000000 0000000 yowsup-3.2.3/yowsup/axolotl/store/sqlite/liteaxolotlstore.py 0000664 0000000 0000000 00000006417 13464333726 0024564 0 ustar 00root root 0000000 0000000 from axolotl.state.axolotlstore import AxolotlStore
from .liteidentitykeystore import LiteIdentityKeyStore
from .liteprekeystore import LitePreKeyStore
from .litesessionstore import LiteSessionStore
from .litesignedprekeystore import LiteSignedPreKeyStore
from .litesenderkeystore import LiteSenderKeyStore
import sqlite3
class LiteAxolotlStore(AxolotlStore):
def __init__(self, db):
conn = sqlite3.connect(db, check_same_thread=False)
conn.text_factory = bytes
self._db = db
self.identityKeyStore = LiteIdentityKeyStore(conn)
self.preKeyStore = LitePreKeyStore(conn)
self.signedPreKeyStore = LiteSignedPreKeyStore(conn)
self.sessionStore = LiteSessionStore(conn)
self.senderKeyStore = LiteSenderKeyStore(conn)
def __str__(self):
return self._db
def getIdentityKeyPair(self):
return self.identityKeyStore.getIdentityKeyPair()
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)
def loadSenderKey(self, senderKeyName):
return self.senderKeyStore.loadSenderKey(senderKeyName)
def storeSenderKey(self, senderKeyName, senderKeyRecord):
self.senderKeyStore.storeSenderKey(senderKeyName, senderKeyRecord)
yowsup-3.2.3/yowsup/axolotl/store/sqlite/liteidentitykeystore.py 0000664 0000000 0000000 00000006133 13464333726 0025437 0 ustar 00root root 0000000 0000000 from axolotl.state.identitykeystore import IdentityKeyStore
from axolotl.identitykey import IdentityKey
from axolotl.identitykeypair import IdentityKeyPair
from axolotl.util.keyhelper import KeyHelper
from axolotl.ecc.djbec import *
import sys
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);")
if self.getLocalRegistrationId() is None or self.getIdentityKeyPair() is None:
identity = KeyHelper.generateIdentityKeyPair()
registration_id = KeyHelper.generateRegistrationId(True)
self._storeLocalData(registration_id, identity)
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()
if result:
publicKey, privateKey = result
return IdentityKeyPair(IdentityKey(DjbECPublicKey(publicKey[1:])), DjbECPrivateKey(privateKey))
return None
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()
pubKey = identityKeyPair.getPublicKey().getPublicKey().serialize()
privKey = identityKeyPair.getPrivateKey().serialize()
if sys.version_info < (2,7):
pubKey = buffer(pubKey)
privKey = buffer(privKey)
c.execute(q, (registrationId,
pubKey,
privKey))
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()
pubKey = identityKey.getPublicKey().serialize()
c.execute(q, (recipientId, buffer(pubKey) if sys.version_info < (2,7) else pubKey))
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
pubKey = identityKey.getPublicKey().serialize()
if sys.version_info < (2, 7):
pubKey = buffer(pubKey)
return result[0] == pubKey yowsup-3.2.3/yowsup/axolotl/store/sqlite/liteprekeystore.py 0000664 0000000 0000000 00000005055 13464333726 0024376 0 ustar 00root root 0000000 0000000 from axolotl.state.prekeystore import PreKeyStore
from axolotl.state.prekeyrecord import PreKeyRecord
from yowsup.axolotl.exceptions import InvalidKeyIdException
import sys
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 InvalidKeyIdException("No such prekeyrecord!")
return PreKeyRecord(serialized = result[0])
def loadUnsentPendingPreKeys(self):
q = "SELECT record FROM prekeys WHERE sent_to_server is NULL or sent_to_server = ?"
cursor = self.dbConn.cursor()
cursor.execute(q, (0,))
result = cursor.fetchall()
return [PreKeyRecord(serialized=result[0]) for result in result]
def setAsSent(self, prekeyIds):
"""
:param preKeyIds:
:type preKeyIds: list
:return:
:rtype:
"""
for prekeyId in prekeyIds:
q = "UPDATE prekeys SET sent_to_server = ? WHERE prekey_id = ?"
cursor = self.dbConn.cursor()
cursor.execute(q, (1, prekeyId))
self.dbConn.commit()
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()
serialized = preKeyRecord.serialize()
cursor.execute(q, (preKeyId, buffer(serialized) if sys.version_info < (2,7) else serialized))
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-3.2.3/yowsup/axolotl/store/sqlite/litesenderkeystore.py 0000664 0000000 0000000 00000003751 13464333726 0025071 0 ustar 00root root 0000000 0000000 from axolotl.groups.state.senderkeystore import SenderKeyStore
from axolotl.groups.state.senderkeyrecord import SenderKeyRecord
import sqlite3
import sys
class LiteSenderKeyStore(SenderKeyStore):
def __init__(self, dbConn):
"""
:type dbConn: Connection
"""
self.dbConn = dbConn
dbConn.execute("CREATE TABLE IF NOT EXISTS sender_keys (_id INTEGER PRIMARY KEY AUTOINCREMENT,"
"group_id TEXT NOT NULL,"
"sender_id INTEGER NOT NULL, record BLOB);")
dbConn.execute("CREATE UNIQUE INDEX IF NOT EXISTS sender_keys_idx ON sender_keys (group_id, sender_id);")
def storeSenderKey(self, senderKeyName, senderKeyRecord):
"""
:type senderKeyName: SenderKeName
:type senderKeyRecord: SenderKeyRecord
"""
q = "INSERT INTO sender_keys (group_id, sender_id, record) VALUES(?,?, ?)"
cursor = self.dbConn.cursor()
serialized = senderKeyRecord.serialize()
if sys.version_info < (2,7):
serialized = buffer(serialized)
try:
cursor.execute(q, (senderKeyName.getGroupId(), senderKeyName.getSender().getName(), serialized))
self.dbConn.commit()
except sqlite3.IntegrityError as e:
q = "UPDATE sender_keys set record = ? WHERE group_id = ? and sender_id = ?"
cursor = self.dbConn.cursor()
cursor.execute(q, (serialized, senderKeyName.getGroupId(), senderKeyName.getSender().getName()))
self.dbConn.commit()
def loadSenderKey(self, senderKeyName):
"""
:type senderKeyName: SenderKeyName
"""
q = "SELECT record FROM sender_keys WHERE group_id = ? and sender_id = ?"
cursor = self.dbConn.cursor()
cursor.execute(q, (senderKeyName.getGroupId(), senderKeyName.getSender().getName()))
result = cursor.fetchone()
if not result:
return SenderKeyRecord()
return SenderKeyRecord(serialized = result[0])
yowsup-3.2.3/yowsup/axolotl/store/sqlite/litesessionstore.py 0000664 0000000 0000000 00000004312 13464333726 0024555 0 ustar 00root root 0000000 0000000 from axolotl.state.sessionstore import SessionStore
from axolotl.state.sessionrecord import SessionRecord
import sys
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()
serialized = sessionRecord.serialize()
c.execute(q, (recipientId, deviceId, buffer(serialized) if sys.version_info < (2,7) else serialized))
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-3.2.3/yowsup/axolotl/store/sqlite/litesignedprekeystore.py 0000664 0000000 0000000 00000004342 13464333726 0025566 0 ustar 00root root 0000000 0000000 from axolotl.state.signedprekeystore import SignedPreKeyStore
from axolotl.state.signedprekeyrecord import SignedPreKeyRecord
from axolotl.invalidkeyidexception import InvalidKeyIdException
import sys
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()
record = signedPreKeyRecord.serialize()
cursor.execute(q, (signedPreKeyId, buffer(record) if sys.version_info < (2,7) else record))
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-3.2.3/yowsup/common/ 0000775 0000000 0000000 00000000000 13464333726 0015736 5 ustar 00root root 0000000 0000000 yowsup-3.2.3/yowsup/common/__init__.py 0000664 0000000 0000000 00000000043 13464333726 0020044 0 ustar 00root root 0000000 0000000 from .constants import YowConstants yowsup-3.2.3/yowsup/common/constants.py 0000664 0000000 0000000 00000001421 13464333726 0020322 0 ustar 00root root 0000000 0000000 class 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),
)
WHATSAPP_SERVER = "s.whatsapp.net"
WHATSAPP_GROUP_SERVER = "g.us"
YOWSUP = "yowsup"
PREVIEW_WIDTH = 64
PREVIEW_HEIGHT = 64
yowsup-3.2.3/yowsup/common/http/ 0000775 0000000 0000000 00000000000 13464333726 0016715 5 ustar 00root root 0000000 0000000 yowsup-3.2.3/yowsup/common/http/__init__.py 0000664 0000000 0000000 00000000162 13464333726 0021025 0 ustar 00root root 0000000 0000000 from .httpproxy import HttpProxy
from .warequest import WARequest
from .waresponseparser import JSONResponseParser yowsup-3.2.3/yowsup/common/http/httpproxy.py 0000664 0000000 0000000 00000006323 13464333726 0021354 0 ustar 00root root 0000000 0000000 '''
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 data yowsup-3.2.3/yowsup/common/http/test_warequest.py 0000664 0000000 0000000 00000000062 13464333726 0022344 0 ustar 00root root 0000000 0000000 from yowsup.common.http.warequest import WARequest yowsup-3.2.3/yowsup/common/http/warequest.py 0000664 0000000 0000000 00000023367 13464333726 0021322 0 ustar 00root root 0000000 0000000 from .waresponseparser import ResponseParser
from yowsup.env import YowsupEnv
import sys
import logging
from axolotl.ecc.curve import Curve
from axolotl.ecc.ec import ECPublicKey
from yowsup.common.tools import WATools
from cryptography.hazmat.primitives.ciphers.aead import AESGCM
from yowsup.axolotl.factory import AxolotlManagerFactory
import struct
import random
import base64
if sys.version_info < (3, 0):
import httplib
from urllib import quote as urllib_quote
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 quote as urllib_quote
logger = logging.getLogger(__name__)
class WARequest(object):
OK = 200
ENC_PUBKEY = Curve.decodePoint(
bytearray([
5, 142, 140, 15, 116, 195, 235, 197, 215, 166, 134, 92, 108,
60, 132, 56, 86, 176, 97, 33, 204, 232, 234, 119, 77, 34, 251,
111, 18, 37, 18, 48, 45
])
)
def __init__(self, config):
"""
:type method: str
:param config:
:type config: yowsup.config.v1.config.Config
"""
self.pvars = []
self.port = 443
self.type = "GET"
self.parser = None
self.params = []
self.headers = {}
self.sent = False
self.response = None
self._config = config
self._p_in = str(config.phone)[len(str(config.cc)):]
self._axolotlmanager = AxolotlManagerFactory() \
.get_manager(self._config.phone) # type: yowsup.axolotl.manager.Axolotlmanager
if config.expid is None:
config.expid = WATools.generateDeviceId()
if config.fdid is None:
config.fdid = WATools.generatePhoneId()
if config.client_static_keypair is None:
config.client_static_keypair = WATools.generateKeyPair()
self.addParam("cc", config.cc)
self.addParam("in", self._p_in)
self.addParam("lg", "en")
self.addParam("lc", "GB")
self.addParam("mistyped", "6")
self.addParam("authkey", self.b64encode(config.client_static_keypair.public.data))
self.addParam("e_regid", self.b64encode(struct.pack('>I', self._axolotlmanager.registration_id)))
self.addParam("e_keytype", self.b64encode(b"\x05"))
self.addParam("e_ident", self.b64encode(self._axolotlmanager.identity.publicKey.serialize()[1:]))
signedprekey = self._axolotlmanager.load_latest_signed_prekey(generate=True)
self.addParam("e_skey_id", self.b64encode(struct.pack('>I', signedprekey.getId())[1:]))
self.addParam("e_skey_val", self.b64encode(signedprekey.getKeyPair().publicKey.serialize()[1:]))
self.addParam("e_skey_sig", self.b64encode(signedprekey.getSignature()))
self.addParam("fdid", config.fdid)
self.addParam("expid", self.b64encode(config.expid))
self.addParam("network_radio_type", "1")
self.addParam("simnum", "1")
self.addParam("hasinrc", "1")
self.addParam("pid", int(random.uniform(100, 9999)))
self.addParam("rc", 0)
if self._config.id:
self.addParam("id", self._config.id)
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 YowsupEnv.getCurrent().getUserAgent()
def send(self, parser=None, encrypt=True, preview=False):
logger.debug("send(parser=%s, encrypt=%s, preview=%s)" % (
None if parser is None else "[omitted]",
encrypt, preview
))
if self.type == "POST":
return self.sendPostRequest(parser)
return self.sendGetRequest(parser, encrypt, preview=preview)
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 encryptParams(self, params, key):
"""
:param params:
:type params: list
:param key:
:type key: ECPublicKey
:return:
:rtype: list
"""
keypair = Curve.generateKeyPair()
encodedparams = self.urlencodeParams(params)
cipher = AESGCM(Curve.calculateAgreement(key, keypair.privateKey))
ciphertext = cipher.encrypt(b'\x00\x00\x00\x00' + struct.pack('>Q', 0), encodedparams.encode(), b'')
payload = base64.b64encode(keypair.publicKey.serialize()[1:] + ciphertext)
return [('ENC', payload)]
def sendGetRequest(self, parser=None, encrypt_params=True, preview=False):
logger.debug("sendGetRequest(parser=%s, encrypt_params=%s, preview=%s)" % (
None if parser is None else "[omitted]",
encrypt_params, preview
))
self.response = None
if encrypt_params:
logger.debug("Encrypting parameters")
if logger.level <= logging.DEBUG:
logger.debug("pre-encrypt (encoded) parameters = \n%s", (self.urlencodeParams(self.params)))
params = self.encryptParams(self.params, self.ENC_PUBKEY)
else:
## params will be logged right before sending
params = 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", preview=preview)
if preview:
logger.info("Preview request, skip response handling and return None")
return None
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)
def b64encode(self, value):
return base64.urlsafe_b64encode(value).replace(b'=', b'')
@classmethod
def urlencode(cls, value):
if type(value) not in (str, bytes):
value = str(value)
out = ""
for char in value:
if type(char) is int:
char = bytearray([char])
quoted = urllib_quote(char, safe='')
out += quoted if quoted[0] != '%' else quoted.lower()
return out \
.replace('-', '%2d') \
.replace('_', '%5f') \
.replace('~', '%7e')
@classmethod
def urlencodeParams(cls, params):
merged = []
for k, v in params:
merged.append(
"%s=%s" % (k, cls.urlencode(v))
)
return "&".join(merged)
@classmethod
def sendRequest(cls, host, port, path, headers, params, reqType="GET", preview=False):
logger.debug("sendRequest(host=%s, port=%s, path=%s, headers=%s, params=%s, reqType=%s, preview=%s)" % (
host, port, path, headers, params, reqType, preview
))
params = cls.urlencodeParams(params)
path = path + "?" + params if reqType == "GET" and params else path
if not preview:
logger.debug("Opening connection to %s" % host)
conn = httplib.HTTPSConnection(host, port) if port == 443 else httplib.HTTPConnection(host, port)
else:
logger.debug("Should open connection to %s, but this is a preview" % host)
conn = None
if not preview:
logger.debug("Sending %s request to %s" % (reqType, path))
conn.request(reqType, path, params, headers)
else:
logger.debug("Should send %s request to %s, but this is a preview" % (reqType, path))
return None
response = conn.getresponse()
return response
yowsup-3.2.3/yowsup/common/http/waresponseparser.py 0000664 0000000 0000000 00000010320 13464333726 0022666 0 ustar 00root root 0000000 0000000 import 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-3.2.3/yowsup/common/mime.types 0000664 0000000 0000000 00000000665 13464333726 0017762 0 ustar 00root root 0000000 0000000 audio/3gpp 3gpp
audio/aac aac
audio/aiff aif
audio/amr amr
audio/mp4 m4a
audio/mpeg mp3 mp2 mpga mpega
audio/ogg oga ogg opus spx
audio/qcelp qcp
audio/wav wav
audio/webm webm
audio/x-caf caf
audio/x-ms-wma wma
audio/ogg ogg
image/gif gif
image/jpeg jpe jpg jpeg
image/png png
video/3gpp 3gp
video/avi avi
video/mp4 mp4
video/mpeg m1v mpeg mpa mpg mpe
video/quicktime mov qt
video/x-flv flv
video/x-ms-asf asf asx
yowsup-3.2.3/yowsup/common/optionalmodules.py 0000664 0000000 0000000 00000002476 13464333726 0021537 0 ustar 00root root 0000000 0000000 import importlib
import logging
logger = logging.getLogger(__name__)
class OptionalModule(object):
def __init__(self, modulename, failMessage = None, require = False):
self.modulename = modulename
self.require = require
self.failMessage = failMessage
def __enter__(self):
return self.importFn
def importFn(self, what = None):
imp = self.modulename if not what else ("%s.%s" % (self.modulename, what))
return importlib.import_module(imp)
def __exit__(self, exc_type, exc_val, exc_tb):
if isinstance(exc_val, ImportError):
failMessage = self.failMessage if self.failMessage is not None else ("%s import failed" % self.modulename)
if failMessage:
logger.error(failMessage)
if self.require:
raise
return True
class PILOptionalModule(OptionalModule):
def __init__(self, failMessage = None, require = False):
super(PILOptionalModule, self).__init__("PIL",
failMessage= failMessage,
require = require)
class FFVideoOptionalModule(OptionalModule):
def __init__(self, failMessage = None, require = False):
super(FFVideoOptionalModule, self).__init__("ffvideo",
failMessage=failMessage,
require=require)
yowsup-3.2.3/yowsup/common/tools.py 0000664 0000000 0000000 00000013765 13464333726 0017464 0 ustar 00root root 0000000 0000000 import os
from .constants import YowConstants
import codecs, sys
import logging
import tempfile
import base64
import hashlib
import os.path, mimetypes
import uuid
from consonance.structs.keypair import KeyPair
from appdirs import user_config_dir
from .optionalmodules import PILOptionalModule, FFVideoOptionalModule
logger = logging.getLogger(__name__)
class Jid:
@staticmethod
def normalize(number):
if '@' in number:
return number
elif "-" in number:
return "%s@%s" % (number, YowConstants.WHATSAPP_GROUP_SERVER)
return "%s@%s" % (number, YowConstants.WHATSAPP_SERVER)
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)
@classmethod
def generatePhoneId(cls):
"""
:return:
:rtype: str
"""
return str(cls.generateUUID())
@classmethod
def generateDeviceId(cls):
"""
:return:
:rtype: bytes
"""
return cls.generateUUID().bytes
@classmethod
def generateUUID(cls):
"""
:return:
:rtype: uuid.UUID
"""
return uuid.uuid4()
@classmethod
def generateKeyPair(cls):
"""
:return:
:rtype: KeyPair
"""
return KeyPair.generate()
@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:
NAME_CONFIG = "config.json"
@staticmethod
def constructPath(*path):
path = os.path.join(*path)
fullPath = os.path.join(user_config_dir(YowConstants.YOWSUP), path)
if not os.path.exists(os.path.dirname(fullPath)):
os.makedirs(os.path.dirname(fullPath))
return fullPath
@staticmethod
def getStorageForPhone(phone):
if type(phone) is not str:
phone = str(phone)
return StorageTools.constructPath(phone + '/')
@staticmethod
def writePhoneData(phone, name, val):
logger.debug("writePhoneData(phone=%s, name=%s, val=[omitted])" % (phone, name))
path = os.path.join(StorageTools.getStorageForPhone(phone), name)
logger.debug("Writing %s" % path)
with open(path, 'w' if type(val) is str else 'wb') as attrFile:
attrFile.write(val)
@staticmethod
def readPhoneData(phone, name, default=None):
logger.debug("readPhoneData(phone=%s, name=%s)" % (phone, name))
path = StorageTools.getStorageForPhone(phone)
dataFilePath = os.path.join(path, name)
if os.path.isfile(dataFilePath):
logger.debug("Reading %s" % dataFilePath)
with open(dataFilePath, 'rb') as attrFile:
return attrFile.read()
else:
logger.debug("%s does not exist" % dataFilePath)
return default
@classmethod
def writeIdentity(cls, phone, identity):
cls.writePhoneData(phone, 'id', identity)
@classmethod
def getIdentity(cls, phone):
return cls.readPhoneData(phone, 'id')
@classmethod
def writePhoneConfig(cls, phone, config):
cls.writePhoneData(phone, cls.NAME_CONFIG, config)
@classmethod
def readPhoneConfig(cls, phone, config):
return cls.readPhoneData(phone, cls.NAME_CONFIG)
class ImageTools:
@staticmethod
def scaleImage(infile, outfile, imageFormat, width, height):
with PILOptionalModule() as imp:
Image = imp("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
return False
@staticmethod
def getImageDimensions(imageFile):
with PILOptionalModule() as imp:
Image = imp("Image")
im = Image.open(imageFile)
return im.size
@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()
os.remove(path)
return preview
class MimeTools:
MIME_FILE = os.path.join(os.path.dirname(__file__), 'mime.types')
mimetypes.init() # Load default mime.types
try:
mimetypes.init([MIME_FILE]) # Append whatsapp mime.types
except exception as e:
logger.warning("Mime types supported can't be read. System mimes will be used. Cause: " + e.message)
@staticmethod
def getMIME(filepath):
mimeType = mimetypes.guess_type(filepath)[0]
if mimeType is None:
raise Exception("Unsupported/unrecognized file type for: "+filepath);
return mimeType
class VideoTools:
@staticmethod
def getVideoProperties(videoFile):
with FFVideoOptionalModule() as imp:
VideoStream = imp("VideoStream")
s = VideoStream(videoFile)
return s.width, s.height, s.bitrate, s.duration #, s.codec_name
@staticmethod
def generatePreviewFromVideo(videoFile):
with FFVideoOptionalModule() as imp:
VideoStream = imp("VideoStream")
fd, path = tempfile.mkstemp('.jpg')
stream = VideoStream(videoFile)
stream.get_frame_at_sec(0).image().save(path)
preview = ImageTools.generatePreviewFromImage(path)
os.remove(path)
return preview
yowsup-3.2.3/yowsup/config/ 0000775 0000000 0000000 00000000000 13464333726 0015713 5 ustar 00root root 0000000 0000000 yowsup-3.2.3/yowsup/config/__init__.py 0000664 0000000 0000000 00000000000 13464333726 0020012 0 ustar 00root root 0000000 0000000 yowsup-3.2.3/yowsup/config/base/ 0000775 0000000 0000000 00000000000 13464333726 0016625 5 ustar 00root root 0000000 0000000 yowsup-3.2.3/yowsup/config/base/__init__.py 0000664 0000000 0000000 00000000000 13464333726 0020724 0 ustar 00root root 0000000 0000000 yowsup-3.2.3/yowsup/config/base/config.py 0000664 0000000 0000000 00000000676 13464333726 0020455 0 ustar 00root root 0000000 0000000 class Config(object):
def __init__(self, version):
self._version = version
def __contains__(self, item):
return self[item] is not None
def __getitem__(self, item):
return getattr(self, "_%s" % item)
def __setitem__(self, key, value):
setattr(self, key, value)
def keys(self):
return [var[1:] for var in vars(self)]
@property
def version(self):
return self._version
yowsup-3.2.3/yowsup/config/base/serialize.py 0000664 0000000 0000000 00000001276 13464333726 0021174 0 ustar 00root root 0000000 0000000 class ConfigSerialize(object):
def __init__(self, transforms):
self._transforms = transforms
def serialize(self, config):
"""
:param config:
:type config: yowsup.config.base.config.Config
:return:
:rtype: bytes
"""
for transform in self._transforms:
config = transform.transform(config)
return config
def deserialize(self, data):
"""
:type cls: type
:param data:
:type data: bytes
:return:
:rtype: yowsup.config.base.config.Config
"""
for transform in self._transforms[::-1]:
data = transform.reverse(data)
return data
yowsup-3.2.3/yowsup/config/base/transform.py 0000664 0000000 0000000 00000000555 13464333726 0021217 0 ustar 00root root 0000000 0000000 class ConfigTransform(object):
def transform(self, config):
"""
:param config:
:type config: yowsup.config.base.config.Config
:return: dict
:rtype:
"""
def reverse(self, data):
"""
:param data:
:type data:
:return:
:rtype: yowsup.config.base.config.Config
"""
yowsup-3.2.3/yowsup/config/manager.py 0000664 0000000 0000000 00000011011 13464333726 0017671 0 ustar 00root root 0000000 0000000 from yowsup.config.v1.config import Config
from yowsup.config.transforms.dict_keyval import DictKeyValTransform
from yowsup.config.transforms.dict_json import DictJsonTransform
from yowsup.config.v1.serialize import ConfigSerialize
from yowsup.common.tools import StorageTools
import logging
import os
logger = logging.getLogger(__name__)
class ConfigManager(object):
NAME_FILE_CONFIG = "config"
TYPE_KEYVAL = 1
TYPE_JSON = 2
TYPE_NAMES = {
TYPE_KEYVAL: "keyval",
TYPE_JSON: "json"
}
MAP_EXT = {
"yo": TYPE_KEYVAL,
"json": TYPE_JSON,
}
TYPES = {
TYPE_KEYVAL: DictKeyValTransform,
TYPE_JSON: DictJsonTransform
}
def load(self, username):
"""
:param username:
:type username:
:return:
:rtype:
"""
config_dir = StorageTools.getStorageForPhone(username)
logger.debug("Detecting config for username=%s, dir=%s" % (username, config_dir))
exhausted = []
for ftype in self.MAP_EXT:
if len(ftype):
fname = (self.NAME_FILE_CONFIG + "." + ftype)
else:
fname = self.NAME_FILE_CONFIG
fpath = os.path.join(config_dir, fname)
logger.debug("Trying %s" % fpath)
if os.path.isfile(fpath):
return self.load_path(fpath)
exhausted.append(fpath)
logger.error("Could not find a config for username=%s, paths checked: %s" % (username, ":".join(exhausted)))
def _type_to_str(self, type):
"""
:param type:
:type type: int
:return:
:rtype:
"""
for key, val in self.TYPE_NAMES.items():
if key == type:
return val
def load_path(self, path):
"""
:param path:
:type path:
:return:
:rtype:
"""
logger.debug("load_path(path=%s)" % path)
if os.path.isfile(path):
configtype = self.guess_type(path)
logger.debug("Detected config type: %s" % self._type_to_str(configtype))
if configtype in self.TYPES:
logger.debug("Opening config for reading")
with open(path, 'r') as f:
data = f.read()
datadict = self.TYPES[configtype]().reverse(data)
return self.load_data(datadict)
else:
raise ValueError("Unsupported config type")
else:
logger.warn("load_path couldn't find the path: %s" % path)
def load_data(self, datadict):
logger.debug("Loading config")
return ConfigSerialize(Config).deserialize(datadict)
def guess_type(self, config_path):
dissected = os.path.splitext(config_path)
if len(dissected) > 1:
ext = dissected[1][1:].lower()
config_type = self.MAP_EXT[ext] if ext in self.MAP_EXT else None
else:
config_type = None
if config_type is not None:
return config_type
else:
logger.debug("Trying auto detect config type by parsing")
with open(config_path, 'r') as f:
data = f.read()
for config_type, transform in self.TYPES.items():
config_type_str = self.TYPE_NAMES[config_type]
try:
logger.debug("Trying to parse as %s" % config_type_str)
if transform().reverse(data):
logger.debug("Successfully detected %s as config type for %s" % (config_type_str, config_path))
return config_type
except Exception as ex:
logger.debug("%s was not parseable as %s, reason: %s" % (config_path, config_type_str, ex))
def get_str_transform(self, serialize_type):
if serialize_type in self.TYPES:
return self.TYPES[serialize_type]()
def config_to_str(self, config, serialize_type=TYPE_JSON):
transform = self.get_str_transform(serialize_type)
if transform is not None:
return transform.transform(ConfigSerialize(config.__class__).serialize(config))
raise ValueError("unrecognized serialize_type=%d" % serialize_type)
def save(self, config, serialize_type=TYPE_JSON, dest=None):
outputdata = self.config_to_str(config, serialize_type)
if dest is None:
StorageTools.writePhoneConfig(config.phone, outputdata)
else:
with open(dest, 'wb') as outputfile:
outputfile.write(outputdata)
yowsup-3.2.3/yowsup/config/transforms/ 0000775 0000000 0000000 00000000000 13464333726 0020111 5 ustar 00root root 0000000 0000000 yowsup-3.2.3/yowsup/config/transforms/__init__.py 0000664 0000000 0000000 00000000000 13464333726 0022210 0 ustar 00root root 0000000 0000000 yowsup-3.2.3/yowsup/config/transforms/config_dict.py 0000664 0000000 0000000 00000001173 13464333726 0022735 0 ustar 00root root 0000000 0000000 from yowsup.config.base.transform import ConfigTransform
class ConfigDictTransform(ConfigTransform):
def __init__(self, cls):
self._cls = cls
def transform(self, config):
"""
:param config:
:type config: dict
:return:
:rtype: yowsup.config.config.Config
"""
out = {}
for prop in vars(config):
out[prop] = getattr(config, prop)
return out
def reverse(self, data):
"""
:param data:
:type data: yowsup,config.config.Config
:return:
:rtype: dict
"""
return self._cls(**data)
yowsup-3.2.3/yowsup/config/transforms/dict_json.py 0000664 0000000 0000000 00000000441 13464333726 0022436 0 ustar 00root root 0000000 0000000 from yowsup.config.base.transform import ConfigTransform
import json
class DictJsonTransform(ConfigTransform):
def transform(self, data):
return json.dumps(data, sort_keys=True, indent=4, separators=(',', ': '))
def reverse(self, data):
return json.loads(data)
yowsup-3.2.3/yowsup/config/transforms/dict_keyval.py 0000664 0000000 0000000 00000001415 13464333726 0022762 0 ustar 00root root 0000000 0000000 from yowsup.config.base.transform import ConfigTransform
class DictKeyValTransform(ConfigTransform):
def transform(self, data):
"""
:param data:
:type data: dict
:return:
:rtype:
"""
out=[]
keys = sorted(data.keys())
for k in keys:
out.append("%s=%s" % (k, data[k]))
return "\n".join(out)
def reverse(self, data):
out = {}
for l in data.split('\n'):
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
yowsup-3.2.3/yowsup/config/transforms/filter.py 0000664 0000000 0000000 00000002014 13464333726 0021745 0 ustar 00root root 0000000 0000000 from yowsup.config.base.transform import ConfigTransform
class FilterTransform(ConfigTransform):
def __init__(self, transform_filter=None, reverse_filter=None):
"""
:param transform_filter:
:type transform_filter: function | None
:param reverse_filter:
:type reverse_filter: function | None
"""
self._transform_filter = transform_filter # type: function | None
self._reverse_filter = reverse_filter # type: function | None
def transform(self, data):
if self._transform_filter is not None:
out = {}
for key, val in data.items():
if self._transform_filter(key, val):
out[key] = val
return out
return data
def reverse(self, data):
if self._reverse_filter is not None:
out = {}
for key, val in data.items():
if self._reverse_filter(key, val):
out[key] = val
return out
return data
yowsup-3.2.3/yowsup/config/transforms/map.py 0000664 0000000 0000000 00000001745 13464333726 0021247 0 ustar 00root root 0000000 0000000 from yowsup.config.base.transform import ConfigTransform
class MapTransform(ConfigTransform):
def __init__(self, transform_map=None, reverse_map=None):
"""
:param transform_map:
:type transform_map: function | None
:param reverse_map:
:type reverse_map: function | None
"""
self._transform_map = transform_map # type: function | None
self._reverse_map = reverse_map # type: function | None
def transform(self, data):
if self._transform_map is not None:
out = {}
for key, val in data.items():
key, val = self._transform_map(key, val)
out[key] = val
return out
return data
def reverse(self, data):
if self._reverse_map is not None:
out = {}
for key, val in data.items():
key, val = self._reverse_map(key, val)
out[key] = val
return out
return data
yowsup-3.2.3/yowsup/config/transforms/meta.py 0000664 0000000 0000000 00000001567 13464333726 0021422 0 ustar 00root root 0000000 0000000 from yowsup.config.base.transform import ConfigTransform
from yowsup.config.transforms.props import PropsTransform
class MetaPropsTransform(ConfigTransform):
META_FORMAT = "__%s__"
def __init__(self, meta_props=None, meta_format=META_FORMAT):
meta_props = meta_props or ()
meta_format = meta_format
transform_map = {}
reverse_map = {}
for prop in meta_props:
formatted = meta_format % prop
transform_map[prop] = lambda key, val, formatted=formatted: (formatted, val)
reverse_map[formatted] = lambda key, val, prop=prop: (prop, val)
self._props_transform = PropsTransform(transform_map=transform_map, reverse_map=reverse_map)
def transform(self, data):
return self._props_transform.transform(data)
def reverse(self, data):
return self._props_transform.reverse(data)
yowsup-3.2.3/yowsup/config/transforms/props.py 0000664 0000000 0000000 00000002056 13464333726 0021631 0 ustar 00root root 0000000 0000000 from yowsup.config.base.transform import ConfigTransform
import types
class PropsTransform(ConfigTransform):
def __init__(self, transform_map=None, reverse_map=None):
self._transform_map = transform_map or {}
self._reverse_map = reverse_map or {}
def transform(self, data):
"""
:param data:
:type data: dict
:return:
:rtype: dict
"""
out = {}
for key, val in data.items():
if key in self._transform_map:
target = self._transform_map[key]
key, val = target(key, val) if type(target) == types.FunctionType else (key, target)
out[key] = val
return out
def reverse(self, data):
transformed_dict = {}
for key, val in data.items():
if key in self._reverse_map:
target = self._reverse_map[key]
key, val = target(key, val) if type(target) == types.FunctionType else (key, target)
transformed_dict[key] = val
return transformed_dict
yowsup-3.2.3/yowsup/config/transforms/serialize.py 0000664 0000000 0000000 00000001216 13464333726 0022452 0 ustar 00root root 0000000 0000000 from yowsup.config.transforms.props import PropsTransform
class SerializeTransform(PropsTransform):
def __init__(self, serialize_map):
"""
{
"keystore": serializer
}
:param serialize_map:
:type serialize_map:
"""
transform_map = {}
reverse_map = {}
for key, val in serialize_map:
transform_map[key] = lambda key, val: key, serialize_map[key].serialize(val)
reverse_map[key] = lambda key, val: key, serialize_map[key].deserialize(val)
super(SerializeTransform, self).__init__(transform_map=transform_map, reverse_map=reverse_map)
yowsup-3.2.3/yowsup/config/v1/ 0000775 0000000 0000000 00000000000 13464333726 0016241 5 ustar 00root root 0000000 0000000 yowsup-3.2.3/yowsup/config/v1/__init__.py 0000664 0000000 0000000 00000000000 13464333726 0020340 0 ustar 00root root 0000000 0000000 yowsup-3.2.3/yowsup/config/v1/config.py 0000664 0000000 0000000 00000010211 13464333726 0020053 0 ustar 00root root 0000000 0000000 from yowsup.config.base import config
import logging
logger = logging.getLogger(__name__)
class Config(config.Config):
def __init__(
self,
phone=None,
cc=None,
password=None,
pushname=None,
id=None,
mcc=None,
mnc=None,
sim_mcc=None,
sim_mnc=None,
client_static_keypair=None,
server_static_public=None,
expid=None,
fdid=None,
edge_routing_info=None,
chat_dns_domain=None
):
super(Config, self).__init__(1)
self._phone = str(phone) if phone is not None else None # type: str
self._cc = cc # type: int
self._password = password # type: str
self._pushname = pushname # type: str
self._id = id
self._client_static_keypair = client_static_keypair
self._server_static_public = server_static_public
self._expid = expid
self._fdid = fdid
self._mcc = mcc
self._mnc = mnc
self._sim_mcc = sim_mcc
self._sim_mnc = sim_mnc
self._edge_routing_info = edge_routing_info
self._chat_dns_domain = chat_dns_domain
if self._password is not None:
logger.warn("Setting a password in Config is deprecated and not used anymore. "
"client_static_keypair is used instead")
def __str__(self):
from yowsup.config.v1.serialize import ConfigSerialize
from yowsup.config.transforms.dict_json import DictJsonTransform
return DictJsonTransform().transform(ConfigSerialize(self.__class__).serialize(self))
@property
def phone(self):
return self._phone
@phone.setter
def phone(self, value):
self._phone = str(value) if value is not None else None
@property
def cc(self):
return self._cc
@cc.setter
def cc(self, value):
self._cc = value
@property
def password(self):
return self._password
@password.setter
def password(self, value):
self._password = value
if value is not None:
logger.warn("Setting a password in Config is deprecated and not used anymore. "
"client_static_keypair is used instead")
@property
def pushname(self):
return self._pushname
@pushname.setter
def pushname(self, value):
self._pushname = value
@property
def mcc(self):
return self._mcc
@mcc.setter
def mcc(self, value):
self._mcc = value
@property
def mnc(self):
return self._mnc
@mnc.setter
def mnc(self, value):
self._mnc = value
@property
def sim_mcc(self):
return self._sim_mcc
@sim_mcc.setter
def sim_mcc(self, value):
self._sim_mcc = value
@property
def sim_mnc(self):
return self._sim_mnc
@sim_mnc.setter
def sim_mnc(self, value):
self._sim_mnc = value
@property
def id(self):
return self._id
@id.setter
def id(self, value):
self._id = value
@property
def client_static_keypair(self):
return self._client_static_keypair
@client_static_keypair.setter
def client_static_keypair(self, value):
self._client_static_keypair = value
@property
def server_static_public(self):
return self._server_static_public
@server_static_public.setter
def server_static_public(self, value):
self._server_static_public = value
@property
def expid(self):
return self._expid
@expid.setter
def expid(self, value):
self._expid = value
@property
def fdid(self):
return self._fdid
@fdid.setter
def fdid(self, value):
self._fdid = value
@property
def edge_routing_info(self):
return self._edge_routing_info
@edge_routing_info.setter
def edge_routing_info(self, value):
self._edge_routing_info = value
@property
def chat_dns_domain(self):
return self._chat_dns_domain
@chat_dns_domain.setter
def chat_dns_domain(self, value):
self._chat_dns_domain = value
yowsup-3.2.3/yowsup/config/v1/serialize.py 0000664 0000000 0000000 00000004204 13464333726 0020602 0 ustar 00root root 0000000 0000000 from yowsup.config.base import serialize
from yowsup.config.transforms.filter import FilterTransform
from yowsup.config.transforms.meta import MetaPropsTransform
from yowsup.config.transforms.map import MapTransform
from yowsup.config.transforms.config_dict import ConfigDictTransform
from yowsup.config.transforms.props import PropsTransform
from consonance.structs.keypair import KeyPair
from consonance.structs.publickey import PublicKey
import base64
class ConfigSerialize(serialize.ConfigSerialize):
def __init__(self, config_class):
super(ConfigSerialize, self).__init__(
transforms=(
ConfigDictTransform(config_class),
FilterTransform(
transform_filter=lambda key, val: val is not None,
reverse_filter=lambda key, val: key != "version"
),
MapTransform(transform_map=lambda key, val: (key[1:], val)),
PropsTransform(
transform_map={
"server_static_public": lambda key, val: (key, base64.b64encode(val.data).decode()),
"client_static_keypair": lambda key, val: (key, base64.b64encode(val.private.data + val.public.data).decode()),
"id": lambda key, val: (key, base64.b64encode(val).decode()),
"expid": lambda key, val: (key, base64.b64encode(val).decode()),
"edge_routing_info": lambda key, val: (key, base64.b64encode(val).decode())
},
reverse_map={
"server_static_public": lambda key, val: (key, PublicKey(base64.b64decode(val))),
"client_static_keypair": lambda key, val: (key, KeyPair.from_bytes(base64.b64decode(val))),
"id": lambda key, val: (key, base64.b64decode(val)),
"expid": lambda key, val: (key, base64.b64decode(val)),
"edge_routing_info": lambda key, val: (key, base64.b64decode(val))
}
),
MetaPropsTransform(meta_props=("version", )),
)
)
yowsup-3.2.3/yowsup/demos/ 0000775 0000000 0000000 00000000000 13464333726 0015555 5 ustar 00root root 0000000 0000000 yowsup-3.2.3/yowsup/demos/__init__.py 0000664 0000000 0000000 00000000000 13464333726 0017654 0 ustar 00root root 0000000 0000000 yowsup-3.2.3/yowsup/demos/cli/ 0000775 0000000 0000000 00000000000 13464333726 0016324 5 ustar 00root root 0000000 0000000 yowsup-3.2.3/yowsup/demos/cli/__init__.py 0000664 0000000 0000000 00000000042 13464333726 0020431 0 ustar 00root root 0000000 0000000 from .stack import YowsupCliStack
yowsup-3.2.3/yowsup/demos/cli/cli.py 0000664 0000000 0000000 00000013607 13464333726 0017454 0 ustar 00root root 0000000 0000000 import 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-3.2.3/yowsup/demos/cli/layer.py 0000664 0000000 0000000 00000060013 13464333726 0020012 0 ustar 00root root 0000000 0000000 from .cli import Cli, clicmd
from yowsup.layers.interface import YowInterfaceLayer, ProtocolEntityCallback
from yowsup.layers.auth import YowAuthenticationProtocolLayer
from yowsup.layers import YowLayerEvent, EventCallback
from yowsup.layers.network import YowNetworkLayer
import sys
from yowsup.common import YowConstants
import datetime
import os
import logging
import threading
import base64
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_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 Jid
from yowsup.common.optionalmodules import PILOptionalModule
from yowsup.layers.axolotl.protocolentities.iq_key_get import GetKeysIqProtocolEntity
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 = "[%s(%s)]:[%s]\t %s"
FAIL_OPT_PILLOW = "No PIL library installed, try install pillow"
FAIL_OPT_AXOLOTL = "axolotl is not installed, try install python-axolotl"
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 Jid.normalize(ajid)
return Jid.normalize(calias)
def jidToAlias(self, jid):
for alias, ajid in self.jidAliases.items():
if ajid == jid:
return alias
return jid
def setCredentials(self, username, keypair):
self.getLayerInterface(YowAuthenticationProtocolLayer).setCredentials(username, keypair)
return "%s@s.whatsapp.net" % username
@EventCallback(EVENT_START)
def onStart(self, layerEvent):
self.startInput()
return True
@EventCallback(EVENT_SENDANDEXIT)
def onSendAndExit(self, layerEvent):
credentials = layerEvent.getArg("credentials")
target = layerEvent.getArg("target")
message = layerEvent.getArg("message")
self.sendMessageAndDisconnect(credentials, target, message)
return True
@EventCallback(YowNetworkLayer.EVENT_STATE_DISCONNECTED)
def onStateDisconnected(self,layerEvent):
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():
with PILOptionalModule(failMessage = "No PIL library installed, try install pillow") as imp:
Image = imp("Image")
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
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)
@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():
with PILOptionalModule(failMessage = self.__class__.FAIL_OPT_PILLOW) as imp:
Image = imp("Image")
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
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)
@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 self.assertConnected():
jids = [self.aliasToJid(jid) for jid in jids.split(',')]
entity = GetKeysIqProtocolEntity(jids)
self.toLower(entity)
@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, 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 a video with optional caption")
def video_send(self, number, path, caption = None):
self.media_send(number, path, RequestUploadIqProtocolEntity.MEDIA_TYPE_VIDEO)
@clicmd("Send an image with optional caption")
def image_send(self, number, path, caption = None):
self.media_send(number, path, RequestUploadIqProtocolEntity.MEDIA_TYPE_IMAGE)
@clicmd("Send audio file")
def audio_send(self, number, path):
self.media_send(number, path, RequestUploadIqProtocolEntity.MEDIA_TYPE_AUDIO)
def media_send(self, number, path, mediaType, caption = None):
if self.assertConnected():
jid = self.aliasToJid(number)
entity = RequestUploadIqProtocolEntity(mediaType, filePath=path)
successFn = lambda successEntity, originalEntity: self.onRequestUploadResult(jid, mediaType, path, successEntity, originalEntity, caption)
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")
threading.Thread(target=lambda: self.getLayerInterface(YowNetworkLayer).connect()).start()
return True
######## 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")
@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 % (sender, formattedDate, message.getId(), messageOut)
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.media_type in ("image", "audio", "video", "document"):
return self.getDownloadableMediaMessageBody(message)
else:
return "[Media Type: %s]" % message.media_type
def getDownloadableMediaMessageBody(self, message):
return "[media_type={media_type}, length={media_size}, url={media_url}, key={media_key}]".format(
media_type=message.media_type,
media_size=message.file_length,
media_url=message.url,
media_key=base64.b64encode(message.media_key)
)
def doSendMedia(self, mediaType, filePath, url, to, ip = None, caption = None):
if mediaType == RequestUploadIqProtocolEntity.MEDIA_TYPE_IMAGE:
entity = ImageDownloadableMediaMessageProtocolEntity.fromFilePath(filePath, url, ip, to, caption = caption)
elif mediaType == RequestUploadIqProtocolEntity.MEDIA_TYPE_AUDIO:
entity = AudioDownloadableMediaMessageProtocolEntity.fromFilePath(filePath, url, ip, to)
elif mediaType == RequestUploadIqProtocolEntity.MEDIA_TYPE_VIDEO:
entity = VideoDownloadableMediaMessageProtocolEntity.fromFilePath(filePath, url, ip, to, caption = caption)
self.toLower(entity)
def __str__(self):
return "CLI Interface Layer"
########### callbacks ############
def onRequestUploadResult(self, jid, mediaType, filePath, resultRequestUploadIqProtocolEntity, requestUploadIqProtocolEntity, caption = None):
if resultRequestUploadIqProtocolEntity.isDuplicate():
self.doSendMedia(mediaType, filePath, resultRequestUploadIqProtocolEntity.getUrl(), jid,
resultRequestUploadIqProtocolEntity.getIp(), caption)
else:
successFn = lambda filePath, jid, url: self.doSendMedia(mediaType, filePath, url, jid, resultRequestUploadIqProtocolEntity.getIp(), caption)
mediaUploader = MediaUploader(jid, self.getOwnJid(), filePath,
resultRequestUploadIqProtocolEntity.getUrl(),
resultRequestUploadIqProtocolEntity.getResumeOffset(),
successFn, self.onUploadError, self.onUploadProgress, asynchronous=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-3.2.3/yowsup/demos/cli/stack.py 0000664 0000000 0000000 00000001653 13464333726 0020010 0 ustar 00root root 0000000 0000000 from yowsup.stacks import YowStackBuilder
from .layer import YowsupCliLayer
from yowsup.layers import YowLayerEvent
from yowsup.layers.axolotl.props import PROP_IDENTITY_AUTOTRUST
import sys
class YowsupCliStack(object):
def __init__(self, credentials):
stackBuilder = YowStackBuilder()
self._stack = stackBuilder\
.pushDefaultLayers()\
.push(YowsupCliLayer)\
.build()
self._stack.setCredentials(credentials)
self._stack.setProp(PROP_IDENTITY_AUTOTRUST, True)
def set_prop(self, prop, val):
self._stack.setProp(prop, val)
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()
except KeyboardInterrupt:
print("\nYowsdown")
sys.exit(0)
yowsup-3.2.3/yowsup/demos/common/ 0000775 0000000 0000000 00000000000 13464333726 0017045 5 ustar 00root root 0000000 0000000 yowsup-3.2.3/yowsup/demos/common/__init__.py 0000664 0000000 0000000 00000000000 13464333726 0021144 0 ustar 00root root 0000000 0000000 yowsup-3.2.3/yowsup/demos/common/sink_worker.py 0000664 0000000 0000000 00000014525 13464333726 0021763 0 ustar 00root root 0000000 0000000 from yowsup.layers.protocol_media.mediacipher import MediaCipher
from yowsup.layers.protocol_media.protocolentities \
import ImageDownloadableMediaMessageProtocolEntity, AudioDownloadableMediaMessageProtocolEntity,\
VideoDownloadableMediaMessageProtocolEntity, DocumentDownloadableMediaMessageProtocolEntity, \
ContactMediaMessageProtocolEntity, DownloadableMediaMessageProtocolEntity
import threading
from tqdm import tqdm
import requests
import logging
import math
import sys
import os
import base64
if sys.version_info >= (3, 0):
from queue import Queue
else:
from Queue import Queue
logger = logging.getLogger(__name__)
class SinkWorker(threading.Thread):
def __init__(self, storage_dir):
super(SinkWorker, self).__init__()
self.daemon = True
self._storage_dir = storage_dir
self._jobs = Queue()
self._media_cipher = MediaCipher()
def enqueue(self, media_message_protocolentity):
self._jobs.put(media_message_protocolentity)
def _create_progress_iterator(self, iterable, niterations, desc):
return tqdm(
iterable, total=niterations, unit='KB', dynamic_ncols=True,
unit_scale=True, leave=True, desc=desc, ascii=True)
def _download(self, url):
response = requests.get(url, stream=True)
total_size = int(response.headers.get('content-length', 0))
logger.debug("%s total size is %s, downloading" % (url, total_size))
block_size = 1024
wrote = 0
enc_data = b""
for data in self._create_progress_iterator(
response.iter_content(block_size), math.ceil(total_size // block_size) + 1, "Download ",
):
wrote = wrote + len(data)
enc_data = enc_data + data
if total_size != 0 and wrote != total_size:
logger.error("Something went wrong")
return None
return enc_data
def _decrypt(self, ciphertext, ref_key, media_info):
length_kb = int(math.ceil(len(ciphertext) / 1024))
progress = self._create_progress_iterator(range(length_kb), length_kb, "Decrypt ")
try:
plaintext = self._media_cipher.decrypt(ciphertext, ref_key, media_info)
progress.update(length_kb)
return plaintext
except Exception as e:
progress.set_description("Decrypt Error ")
logger.error(e)
return None
def _write(self, data, filename):
length_kb = int(math.ceil(len(data) / 1024))
progress = self._create_progress_iterator(range(length_kb), length_kb, "Write ")
try:
with open(filename, 'wb') as f:
f.write(data)
progress.update(length_kb)
return filename
except Exception as e:
progress.set_description("Write error ")
logger.error(e)
return None
def _create_unique_filepath(self, filepath):
file_dir = os.path.dirname(filepath)
filename = os.path.basename(filepath)
result_filename = filename
dissected = os.path.splitext(filename)
count = 0
while os.path.exists(os.path.join(file_dir, result_filename)):
count += 1
result_filename = "%s_%d%s" % (dissected[0], count, dissected[1])
return os.path.join(file_dir, result_filename)
def run(self):
logger.debug(
"SinkWorker started, storage_dir=%s" % self._storage_dir
)
while True:
media_message_protocolentity = self._jobs.get()
if media_message_protocolentity is None:
sys.exit(0)
if isinstance(media_message_protocolentity, DownloadableMediaMessageProtocolEntity):
logger.info(
"Processing [url=%s, media_key=%s]" %
(media_message_protocolentity.url, base64.b64encode(media_message_protocolentity.media_key))
)
else:
logger.info("Processing %s" % media_message_protocolentity.media_type)
filedata = None
fileext = None
if isinstance(media_message_protocolentity, ImageDownloadableMediaMessageProtocolEntity):
media_info = MediaCipher.INFO_IMAGE
filename = "image"
elif isinstance(media_message_protocolentity, AudioDownloadableMediaMessageProtocolEntity):
media_info = MediaCipher.INFO_AUDIO
filename = "ptt" if media_message_protocolentity.ptt else "audio"
elif isinstance(media_message_protocolentity, VideoDownloadableMediaMessageProtocolEntity):
media_info = MediaCipher.INFO_VIDEO
filename = "video"
elif isinstance(media_message_protocolentity, DocumentDownloadableMediaMessageProtocolEntity):
media_info = MediaCipher.INFO_DOCUM
filename = media_message_protocolentity.file_name
elif isinstance(media_message_protocolentity, ContactMediaMessageProtocolEntity):
filename = media_message_protocolentity.display_name
filedata = media_message_protocolentity.vcard
fileext = "vcard"
else:
logger.error("Unsupported Media type: %s" % media_message_protocolentity.__class__)
sys.exit(1)
if filedata is None:
enc_data = self._download(media_message_protocolentity.url)
if enc_data is None:
logger.error("Download failed")
sys.exit(1)
filedata = self._decrypt(enc_data, media_message_protocolentity.media_key, media_info)
if filedata is None:
logger.error("Decrypt failed")
sys.exit(1)
if not isinstance(media_message_protocolentity, DocumentDownloadableMediaMessageProtocolEntity):
if fileext is None:
fileext = media_message_protocolentity.mimetype.split('/')[1].split(';')[0]
filename_full = "%s.%s" % (filename, fileext)
else:
filename_full = filename
filepath = self._create_unique_filepath(os.path.join(self._storage_dir, filename_full))
if self._write(filedata, filepath):
logger.info("Wrote %s" % filepath)
else:
sys.exit(1)
yowsup-3.2.3/yowsup/demos/contacts/ 0000775 0000000 0000000 00000000000 13464333726 0017373 5 ustar 00root root 0000000 0000000 yowsup-3.2.3/yowsup/demos/contacts/__init__.py 0000664 0000000 0000000 00000000043 13464333726 0021501 0 ustar 00root root 0000000 0000000 from .stack import YowsupSyncStack
yowsup-3.2.3/yowsup/demos/contacts/layer.py 0000664 0000000 0000000 00000002316 13464333726 0021063 0 ustar 00root root 0000000 0000000 from 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-3.2.3/yowsup/demos/contacts/stack.py 0000664 0000000 0000000 00000001724 13464333726 0021056 0 ustar 00root root 0000000 0000000 from .layer import SyncLayer
from yowsup.stacks import YowStackBuilder
from yowsup.layers import YowLayerEvent
from yowsup.layers.auth import YowAuthenticationProtocolLayer
from yowsup.layers.network import YowNetworkLayer
class YowsupSyncStack(object):
def __init__(self, credentials, contacts):
"""
:param credentials:
:param contacts: list of [jid ]
:return:
"""
stackBuilder = YowStackBuilder()
self._stack = stackBuilder \
.pushDefaultLayers() \
.push(SyncLayer) \
.build()
self._stack.setProp(SyncLayer.PROP_CONTACTS, contacts)
self._stack.setProp(YowAuthenticationProtocolLayer.PROP_PASSIVE, True)
self._stack.setCredentials(credentials)
def set_prop(self, key, val):
self._stack.setProp(key, val)
def start(self):
self._stack.broadcastEvent(YowLayerEvent(YowNetworkLayer.EVENT_STATE_CONNECT))
self._stack.loop()
yowsup-3.2.3/yowsup/demos/echoclient/ 0000775 0000000 0000000 00000000000 13464333726 0017672 5 ustar 00root root 0000000 0000000 yowsup-3.2.3/yowsup/demos/echoclient/__init__.py 0000664 0000000 0000000 00000000042 13464333726 0021777 0 ustar 00root root 0000000 0000000 from .stack import YowsupEchoStack yowsup-3.2.3/yowsup/demos/echoclient/layer.py 0000664 0000000 0000000 00000003146 13464333726 0021364 0 ustar 00root root 0000000 0000000 from 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.media_type == "image":
print("Echoing image %s to %s" % (messageProtocolEntity.url, messageProtocolEntity.getFrom(False)))
elif messageProtocolEntity.media_type == "location":
print("Echoing location (%s, %s) to %s" % (messageProtocolEntity.getLatitude(), messageProtocolEntity.getLongitude(), messageProtocolEntity.getFrom(False)))
elif messageProtocolEntity.media_type == "contact":
print("Echoing contact (%s, %s) to %s" % (messageProtocolEntity.getName(), messageProtocolEntity.getCardData(), messageProtocolEntity.getFrom(False)))
yowsup-3.2.3/yowsup/demos/echoclient/stack.py 0000664 0000000 0000000 00000001215 13464333726 0021350 0 ustar 00root root 0000000 0000000 from yowsup.stacks import YowStackBuilder
from .layer import EchoLayer
from yowsup.layers import YowLayerEvent
from yowsup.layers.network import YowNetworkLayer
class YowsupEchoStack(object):
def __init__(self, credentials):
stackBuilder = YowStackBuilder()
self._stack = stackBuilder\
.pushDefaultLayers()\
.push(EchoLayer)\
.build()
self._stack.setCredentials(credentials)
def set_prop(self, key, val):
self._stack.setProp(key, val)
def start(self):
self._stack.broadcastEvent(YowLayerEvent(YowNetworkLayer.EVENT_STATE_CONNECT))
self._stack.loop()
yowsup-3.2.3/yowsup/demos/mediasink/ 0000775 0000000 0000000 00000000000 13464333726 0017521 5 ustar 00root root 0000000 0000000 yowsup-3.2.3/yowsup/demos/mediasink/__init__.py 0000664 0000000 0000000 00000000041 13464333726 0021625 0 ustar 00root root 0000000 0000000 from .stack import MediaSinkStack yowsup-3.2.3/yowsup/demos/mediasink/layer.py 0000664 0000000 0000000 00000003757 13464333726 0021223 0 ustar 00root root 0000000 0000000 from yowsup.layers.interface import YowInterfaceLayer, ProtocolEntityCallback
from yowsup.layers.protocol_media.protocolentities import *
from yowsup.layers.network.layer import YowNetworkLayer
from yowsup.layers import EventCallback
import sys
try:
from tqdm import tqdm
import requests
except ImportError:
print("This demo requires the python packages 'tqdm' and 'requests' to be installed, exiting.")
sys.exit(1)
from ..common.sink_worker import SinkWorker
import tempfile
import logging
import os
logger = logging.getLogger(__name__)
class MediaSinkLayer(YowInterfaceLayer):
PROP_STORAGE_DIR = "org.openwhatsapp.yowsup.prop.demos.mediasink.storage_dir"
def __init__(self):
super(MediaSinkLayer, self).__init__()
self._sink_worker = None
@EventCallback(YowNetworkLayer.EVENT_STATE_CONNECTED)
def on_connected(self, event):
logger.info("Connected, starting SinkWorker")
storage_dir = self.getProp(self.PROP_STORAGE_DIR)
if storage_dir is None:
logger.debug("No storage dir specified, creating tempdir")
storage_dir = tempfile.mkdtemp("yowsup_mediasink")
if not os.path.exists(storage_dir):
logger.debug("%s does not exist, creating" % storage_dir)
os.makedirs(storage_dir)
logger.info("Storing incoming media to %s" % storage_dir)
self._sink_worker = SinkWorker(storage_dir)
self._sink_worker.start()
@ProtocolEntityCallback("message")
def on_message(self, message_protocolentity):
self.toLower(message_protocolentity.ack())
self.toLower(message_protocolentity.ack(True))
if isinstance(message_protocolentity, MediaMessageProtocolEntity):
self.on_media_message(message_protocolentity)
@ProtocolEntityCallback("receipt")
def on_receipt(self, entity):
self.toLower(entity.ack())
def on_media_message(self, media_message_protocolentity):
self._sink_worker.enqueue(media_message_protocolentity)
yowsup-3.2.3/yowsup/demos/mediasink/stack.py 0000664 0000000 0000000 00000001361 13464333726 0021201 0 ustar 00root root 0000000 0000000 from yowsup.stacks import YowStackBuilder
from .layer import MediaSinkLayer
from yowsup.layers import YowLayerEvent
from yowsup.layers.network import YowNetworkLayer
class MediaSinkStack(object):
def __init__(self, credentials, storage_dir=None):
stackBuilder = YowStackBuilder()
self._stack = stackBuilder\
.pushDefaultLayers()\
.push(MediaSinkLayer)\
.build()
self._stack.setProp(MediaSinkLayer.PROP_STORAGE_DIR, storage_dir)
self._stack.setCredentials(credentials)
def set_prop(self, key, val):
self._stack.setProp(key, val)
def start(self):
self._stack.broadcastEvent(YowLayerEvent(YowNetworkLayer.EVENT_STATE_CONNECT))
self._stack.loop()
yowsup-3.2.3/yowsup/demos/sendclient/ 0000775 0000000 0000000 00000000000 13464333726 0017705 5 ustar 00root root 0000000 0000000 yowsup-3.2.3/yowsup/demos/sendclient/__init__.py 0000664 0000000 0000000 00000000042 13464333726 0022012 0 ustar 00root root 0000000 0000000 from .stack import YowsupSendStack yowsup-3.2.3/yowsup/demos/sendclient/layer.py 0000664 0000000 0000000 00000003741 13464333726 0021400 0 ustar 00root root 0000000 0000000 from yowsup.layers.interface import YowInterfaceLayer, ProtocolEntityCallback
from yowsup.layers.protocol_messages.protocolentities import TextMessageProtocolEntity
from yowsup.common.tools import Jid
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
messageEntity = TextMessageProtocolEntity(message, to = Jid.normalize(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-3.2.3/yowsup/demos/sendclient/stack.py 0000664 0000000 0000000 00000001737 13464333726 0021374 0 ustar 00root root 0000000 0000000 from yowsup.stacks import YowStackBuilder
from .layer import SendLayer
from yowsup.layers import YowLayerEvent
from yowsup.layers.auth import YowAuthenticationProtocolLayer
from yowsup.layers.network import YowNetworkLayer
class YowsupSendStack(object):
def __init__(self, credentials, messages):
"""
:param credentials:
:param messages: list of (jid, message) tuples
:return:
"""
stackBuilder = YowStackBuilder()
self._stack = stackBuilder\
.pushDefaultLayers()\
.push(SendLayer)\
.build()
self._stack.setProp(SendLayer.PROP_MESSAGES, messages)
self._stack.setProp(YowAuthenticationProtocolLayer.PROP_PASSIVE, True)
self._stack.setCredentials(credentials)
def set_prop(self, key, val):
self._stack.setProp(key, val)
def start(self):
self._stack.broadcastEvent(YowLayerEvent(YowNetworkLayer.EVENT_STATE_CONNECT))
self._stack.loop()
yowsup-3.2.3/yowsup/env/ 0000775 0000000 0000000 00000000000 13464333726 0015236 5 ustar 00root root 0000000 0000000 yowsup-3.2.3/yowsup/env/__init__.py 0000664 0000000 0000000 00000000105 13464333726 0017343 0 ustar 00root root 0000000 0000000 from .env import YowsupEnv
from .env_android import AndroidYowsupEnv
yowsup-3.2.3/yowsup/env/env.py 0000664 0000000 0000000 00000004635 13464333726 0016410 0 ustar 00root root 0000000 0000000 import abc
import logging
from six import with_metaclass
logger = logging.getLogger(__name__)
DEFAULT = "android"
class YowsupEnvType(abc.ABCMeta):
def __init__(cls, name, bases, dct):
if name != "YowsupEnv":
YowsupEnv.registerEnv(cls)
super(YowsupEnvType, cls).__init__(name, bases, dct)
class YowsupEnv(with_metaclass(YowsupEnvType, object)):
__metaclass__ = YowsupEnvType
__ENVS = {}
__CURR = None
_USERAGENT_STRING = "WhatsApp/{WHATSAPP_VERSION} {OS_NAME}/{OS_VERSION} Device/{MANUFACTURER}-{DEVICE_NAME}"
@classmethod
def registerEnv(cls, envCls):
envName = envCls.__name__.lower().replace("yowsupenv", "")
cls.__ENVS[envName] = envCls
logger.debug("registered env %s => %s" % (envName, envCls))
@classmethod
def setEnv(cls, envName):
if not envName in cls.__ENVS:
raise ValueError("%s env does not exist" % envName)
logger.debug("Current env changed to %s " % envName)
cls.__CURR = cls.__ENVS[envName]()
@classmethod
def getEnv(cls, envName):
if not envName in cls.__ENVS:
raise ValueError("%s env does not exist" % envName)
return cls.__ENVS[envName]()
@classmethod
def getRegisteredEnvs(cls):
return list(cls.__ENVS.keys())
@classmethod
def getCurrent(cls):
"""
:rtype: YowsupEnv
"""
if cls.__CURR is None:
env = DEFAULT
envs = cls.getRegisteredEnvs()
if env not in envs:
env = envs[0]
logger.debug("Env not set, setting it to %s" % env)
cls.setEnv(env)
return cls.__CURR
@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 getManufacturer(self):
pass
def getBuildVersion(self):
pass
def getUserAgent(self):
return self.__class__._USERAGENT_STRING.format(
WHATSAPP_VERSION=self.getVersion(),
OS_NAME=self.getOSName(),
OS_VERSION=self.getOSVersion(),
MANUFACTURER=self.getManufacturer(),
DEVICE_NAME=self.getDeviceName()
)
yowsup-3.2.3/yowsup/env/env_android.py 0000664 0000000 0000000 00000006035 13464333726 0020104 0 ustar 00root root 0000000 0000000 from .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 = "bdZVQh58MKZaaeiYnh7wkw=="
_KEY = "eQV5aq/Cg63Gsq1sshN9T3gh+UUp0wIw0xgHYT1bnCjEqOJQKCRrWxdAe2yvsDeCJL+Y4G3PRD2HUF7oUgiGo8vGlNJOaux26k+A2F3hj8A="
_VERSION = "2.19.51"
_OS_NAME = "Android"
_OS_VERSION = "8.0.0"
_DEVICE_NAME = "star2lte"
_MANUFACTURER = "samsung"
_BUILD_VERSION = "star2ltexx-user 8.0.0 R16NW G965FXXU1ARCC release-keys"
_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 getBuildVersion(self):
return self.__class__._BUILD_VERSION
def getManufacturer(self):
return self.__class__._MANUFACTURER
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-3.2.3/yowsup/layers/ 0000775 0000000 0000000 00000000000 13464333726 0015745 5 ustar 00root root 0000000 0000000 yowsup-3.2.3/yowsup/layers/__init__.py 0000664 0000000 0000000 00000020775 13464333726 0020071 0 ustar 00root root 0000000 0000000 import unittest
import inspect
import threading
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 EventCallback(object):
def __init__(self, eventName):
self.eventName = eventName
def __call__(self, fn):
fn.event_callback = self.eventName
return fn
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
self.event_callbacks = {}
self.__stack = None
self.lock = threading.Lock()
members = inspect.getmembers(self, predicate=inspect.ismethod)
for m in members:
if hasattr(m[1], "event_callback"):
fname = m[0]
fn = m[1]
self.event_callbacks[fn.event_callback] = getattr(self, fname)
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):
self.lock.acquire()
if self.__lower:
self.__lower.send(data)
self.lock.release()
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):
eventName = yowLayerEvent.getName()
if eventName in self.event_callbacks:
return self.event_callbacks[eventName](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
self.upperEventSink = []
self.lowerEventSink = []
self.emitEvent = self.emitEventOverrider
self.broadcastEvent = self.broadcastEventOverrider
def receiveOverrider(self, data):
self.upperSink.append(data)
def sendOverrider(self, data):
self.lowerSink.append(data)
def emitEventOverrider(self, event):
self.upperEventSink.append(event)
def broadcastEventOverrider(self, event):
self.lowerEventSink.append(event)
def assert_emitEvent(self, event):
self.emitEvent(event)
try:
self.assertEqual(event, self.upperEventSink.pop())
except IndexError:
raise AssertionError("Event '%s' was not emited through this layer" % (event.getName()))
def assert_broadcastEvent(self, event):
self.broadcastEvent(event)
try:
self.assertEqual(event, self.lowerEventSink.pop())
except IndexError:
raise AssertionError("Event '%s' was not broadcasted through this layer" % (event.getName()))
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-3.2.3/yowsup/layers/auth/ 0000775 0000000 0000000 00000000000 13464333726 0016706 5 ustar 00root root 0000000 0000000 yowsup-3.2.3/yowsup/layers/auth/__init__.py 0000664 0000000 0000000 00000000101 13464333726 0021007 0 ustar 00root root 0000000 0000000 from .layer_authentication import YowAuthenticationProtocolLayer
yowsup-3.2.3/yowsup/layers/auth/layer_authentication.py 0000664 0000000 0000000 00000006007 13464333726 0023476 0 ustar 00root root 0000000 0000000 from yowsup.common import YowConstants
from yowsup.layers import YowLayerEvent, YowProtocolLayer, EventCallback
from yowsup.layers.network import YowNetworkLayer
from .protocolentities import *
from .layer_interface_authentication import YowAuthenticationProtocolLayerInterface
from .protocolentities import StreamErrorProtocolEntity
class YowAuthenticationProtocolLayer(YowProtocolLayer):
EVENT_AUTHED = "org.openwhatsapp.yowsup.event.auth.authed"
EVENT_AUTH = "org.openwhatsapp.yowsup.event.auth"
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),
"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"
@EventCallback(YowNetworkLayer.EVENT_STATE_CONNECTED)
def on_connected(self, event):
self.broadcastEvent(
YowLayerEvent(
self.EVENT_AUTH,
credentials=self.getProp(self.PROP_CREDENTIALS),
passive=self.getProp(self.PROP_PASSIVE, False)
)
)
def setCredentials(self, credentials):
self.setProp(self.PROP_CREDENTIALS, credentials) #keep for now
self._credentials = credentials
#
def getUsername(self, full = False):
if self._credentials:
return self._credentials[0] if not full else ("%s@%s" % (self._credentials[0], YowConstants.WHATSAPP_SERVER))
else:
prop = self.getProp(YowAuthenticationProtocolLayer.PROP_CREDENTIALS)
return prop[0] if prop else None
def handleStreamFeatures(self, node):
nodeEntity = StreamFeaturesProtocolEntity.fromProtocolTreeNode(node)
self.toUpper(nodeEntity)
def handleSuccess(self, node):
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"))
def handleStreamError(self, node):
nodeEntity = StreamErrorProtocolEntity.fromProtocolTreeNode(node)
errorType = nodeEntity.getErrorType()
if not errorType:
raise NotImplementedError("Unhandled stream:error node:\n%s" % node)
self.toUpper(nodeEntity)
yowsup-3.2.3/yowsup/layers/auth/layer_interface_authentication.py 0000664 0000000 0000000 00000000451 13464333726 0025513 0 ustar 00root root 0000000 0000000 from yowsup.layers import YowLayerInterface
class YowAuthenticationProtocolLayerInterface(YowLayerInterface):
def setCredentials(self, phone, keypair):
self._layer.setCredentials((phone, keypair))
def getUsername(self, full = False):
return self._layer.getUsername(full)
yowsup-3.2.3/yowsup/layers/auth/protocolentities/ 0000775 0000000 0000000 00000000000 13464333726 0022314 5 ustar 00root root 0000000 0000000 yowsup-3.2.3/yowsup/layers/auth/protocolentities/__init__.py 0000664 0000000 0000000 00000000505 13464333726 0024425 0 ustar 00root root 0000000 0000000 from .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 import StreamErrorProtocolEntity
yowsup-3.2.3/yowsup/layers/auth/protocolentities/auth.py 0000664 0000000 0000000 00000001674 13464333726 0023637 0 ustar 00root root 0000000 0000000 from 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-3.2.3/yowsup/layers/auth/protocolentities/challenge.py 0000664 0000000 0000000 00000001443 13464333726 0024612 0 ustar 00root root 0000000 0000000 from 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-3.2.3/yowsup/layers/auth/protocolentities/failure.py 0000664 0000000 0000000 00000001144 13464333726 0024315 0 ustar 00root root 0000000 0000000 from 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):
return self._createProtocolTreeNode({"reason": self.reason})
@staticmethod
def fromProtocolTreeNode(node):
return FailureProtocolEntity( node["reason"] )
yowsup-3.2.3/yowsup/layers/auth/protocolentities/response.py 0000664 0000000 0000000 00000001103 13464333726 0024517 0 ustar 00root root 0000000 0000000 from 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-3.2.3/yowsup/layers/auth/protocolentities/stream_error.py 0000664 0000000 0000000 00000003366 13464333726 0025402 0 ustar 00root root 0000000 0000000 from yowsup.structs import ProtocolEntity, ProtocolTreeNode
class StreamErrorProtocolEntity(ProtocolEntity):
TYPE_CONFLICT = "conflict"
'''
Replaced by new connection
'''
TYPE_ACK = "ack"
'''
'''
TYPE_XML_NOT_WELL_FORMED = "xml-not-well-formed"
'''
'''
TYPES = (TYPE_CONFLICT, TYPE_ACK, TYPE_XML_NOT_WELL_FORMED)
def __init__(self, data = None):
super(StreamErrorProtocolEntity, self).__init__("stream:error")
data = data or {}
self.setErrorData(data)
def setErrorData(self, data):
self.data = data
def getErrorData(self):
return self.data
def getErrorType(self):
for k in self.data.keys():
if k in self.__class__.TYPES:
return k
def __str__(self):
out = "Stream Error type: %s\n" % self.getErrorType()
out += "%s" % self.getErrorData()
out += "\n"
return out
def toProtocolTreeNode(self):
node = super(StreamErrorProtocolEntity, self).toProtocolTreeNode()
type = self.getErrorType()
node.addChild(ProtocolTreeNode(type))
if type == self.__class__.TYPE_CONFLICT and "text" in self.data:
node.addChild(ProtocolTreeNode("text", data=self.data["text"]))
return node
@staticmethod
def fromProtocolTreeNode(protocolTreeNode):
data = {}
for child in protocolTreeNode.getAllChildren():
data[child.tag] = child.data
return StreamErrorProtocolEntity(data)
yowsup-3.2.3/yowsup/layers/auth/protocolentities/stream_features.py 0000664 0000000 0000000 00000001273 13464333726 0026062 0 ustar 00root root 0000000 0000000 from 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-3.2.3/yowsup/layers/auth/protocolentities/success.py 0000664 0000000 0000000 00000002262 13464333726 0024340 0 ustar 00root root 0000000 0000000 from yowsup.structs import ProtocolEntity, ProtocolTreeNode
class SuccessProtocolEntity(ProtocolEntity):
def __init__(self, creation, props, t, location):
super(SuccessProtocolEntity, self).__init__("success")
self.location = location
self.creation = int(creation)
self.props = props
self.t = int(t) ##whatever that is !
def __str__(self):
out = "Account:\n"
out += "Location: %s\n" % self.location
out += "Creation: %s\n" % self.creation
out += "Props: %s\n" % self.props
out += "t: %s\n" % self.t
return out
def toProtocolTreeNode(self):
attributes = {
"location" : self.location,
"creation" : str(self.creation),
"props" : self.props,
"t" : str(self.t)
}
return self._createProtocolTreeNode(attributes)
@staticmethod
def fromProtocolTreeNode(node):
return SuccessProtocolEntity(
node.getAttributeValue("creation"),
node.getAttributeValue("props"),
node.getAttributeValue("t"),
node.getAttributeValue("location")
) yowsup-3.2.3/yowsup/layers/auth/protocolentities/test_failure.py 0000664 0000000 0000000 00000000650 13464333726 0025355 0 ustar 00root root 0000000 0000000 from 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", {"reason": "not-authorized"})
yowsup-3.2.3/yowsup/layers/auth/protocolentities/test_success.py 0000664 0000000 0000000 00000001050 13464333726 0025371 0 ustar 00root root 0000000 0000000 from 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 = {
"creation": "1234",
"location": "atn",
"props": "2",
"t": "1415470561"
}
self.node = ProtocolTreeNode("success", attribs)
yowsup-3.2.3/yowsup/layers/axolotl/ 0000775 0000000 0000000 00000000000 13464333726 0017427 5 ustar 00root root 0000000 0000000 yowsup-3.2.3/yowsup/layers/axolotl/__init__.py 0000664 0000000 0000000 00000000207 13464333726 0021537 0 ustar 00root root 0000000 0000000 from .layer_send import AxolotlSendLayer
from .layer_control import AxolotlControlLayer
from .layer_receive import AxolotlReceivelayer
yowsup-3.2.3/yowsup/layers/axolotl/layer_base.py 0000664 0000000 0000000 00000005426 13464333726 0022116 0 ustar 00root root 0000000 0000000 from yowsup.layers import YowProtocolLayer
from yowsup.layers.auth.layer_authentication import YowAuthenticationProtocolLayer
from yowsup.layers.axolotl.protocolentities import *
from yowsup.axolotl.factory import AxolotlManagerFactory, AxolotlManager
from yowsup.layers.network.layer import YowNetworkLayer
from yowsup.layers import EventCallback
from yowsup.axolotl import exceptions
from yowsup.layers.axolotl.props import PROP_IDENTITY_AUTOTRUST
import logging
logger = logging.getLogger(__name__)
class AxolotlBaseLayer(YowProtocolLayer):
def __init__(self):
super(AxolotlBaseLayer, self).__init__()
self._manager = None # type: AxolotlManager | None
self.skipEncJids = []
def send(self, node):
pass
def receive(self, node):
self.processIqRegistry(node)
@property
def manager(self):
"""
:return:
:rtype: AxolotlManager
"""
return self._manager
@EventCallback(YowNetworkLayer.EVENT_STATE_CONNECTED)
def on_connected(self, yowLayerEvent):
self._manager = AxolotlManagerFactory().get_manager(
self.getProp(YowAuthenticationProtocolLayer.PROP_CREDENTIALS)[0]
)
@EventCallback(YowNetworkLayer.EVENT_STATE_DISCONNECTED)
def on_disconnected(self, yowLayerEvent):
self._manager = None
def getKeysFor(self, jids, resultClbk, errorClbk = None, reason=None):
logger.debug("getKeysFor(jids=%s, resultClbk=[omitted], errorClbk=[omitted], reason=%s)" % (jids, reason))
def onSuccess(resultNode, getKeysEntity):
entity = ResultGetKeysIqProtocolEntity.fromProtocolTreeNode(resultNode)
resultJids = entity.getJids()
successJids = []
errorJids = {} #jid -> exception
for jid in getKeysEntity.jids:
if jid not in resultJids:
self.skipEncJids.append(jid)
continue
recipient_id = jid.split('@')[0]
preKeyBundle = entity.getPreKeyBundleFor(jid)
try:
self.manager.create_session(recipient_id, preKeyBundle,
autotrust=self.getProp(PROP_IDENTITY_AUTOTRUST, False))
successJids.append(jid)
except exceptions.UntrustedIdentityException as e:
errorJids[jid] = e
logger.error(e)
logger.warning("Ignoring message with untrusted identity")
resultClbk(successJids, errorJids)
def onError(errorNode, getKeysEntity):
if errorClbk:
errorClbk(errorNode, getKeysEntity)
entity = GetKeysIqProtocolEntity(jids, reason=reason)
self._sendIq(entity, onSuccess, onError=onError)
yowsup-3.2.3/yowsup/layers/axolotl/layer_control.py 0000664 0000000 0000000 00000013001 13464333726 0022650 0 ustar 00root root 0000000 0000000 from .layer_base import AxolotlBaseLayer
from yowsup.layers import YowLayerEvent, EventCallback
from yowsup.layers.network.layer import YowNetworkLayer
from yowsup.layers.axolotl.protocolentities import *
from yowsup.layers.auth.layer_authentication import YowAuthenticationProtocolLayer
from yowsup.layers.protocol_acks.protocolentities import OutgoingAckProtocolEntity
from axolotl.util.hexutil import HexUtil
from axolotl.ecc.curve import Curve
import logging
import binascii
logger = logging.getLogger(__name__)
class AxolotlControlLayer(AxolotlBaseLayer):
def __init__(self):
super(AxolotlControlLayer, self).__init__()
self._unsent_prekeys = []
self._reboot_connection = False
def send(self, node):
self.toLower(node)
def receive(self, protocolTreeNode):
"""
:type protocolTreeNode: ProtocolTreeNode
"""
if not self.processIqRegistry(protocolTreeNode):
if protocolTreeNode.tag == "notification" and protocolTreeNode["type"] == "encrypt":
if protocolTreeNode.getChild("count") is not None:
return self.onRequestKeysEncryptNotification(protocolTreeNode)
elif protocolTreeNode.getChild("identity") is not None:
return self.onIdentityChangeEncryptNotification(protocolTreeNode)
self.toUpper(protocolTreeNode)
def onIdentityChangeEncryptNotification(self, protocoltreenode):
entity = IdentityChangeEncryptNotification.fromProtocolTreeNode(protocoltreenode)
ack = OutgoingAckProtocolEntity(
protocoltreenode["id"], "notification", protocoltreenode["type"], protocoltreenode["from"]
)
self.toLower(ack.toProtocolTreeNode())
self.getKeysFor([entity.getFrom(True)], resultClbk=lambda _,__: None, reason="identity")
def onRequestKeysEncryptNotification(self, protocolTreeNode):
entity = RequestKeysEncryptNotification.fromProtocolTreeNode(protocolTreeNode)
ack = OutgoingAckProtocolEntity(protocolTreeNode["id"], "notification", protocolTreeNode["type"], protocolTreeNode["from"])
self.toLower(ack.toProtocolTreeNode())
self.flush_keys(
self.manager.generate_signed_prekey(),
self.manager.level_prekeys(force=True)
)
@EventCallback(YowNetworkLayer.EVENT_STATE_CONNECTED)
def on_connected(self, yowLayerEvent):
super(AxolotlControlLayer, self).on_connected(yowLayerEvent)
self.manager.level_prekeys()
self._unsent_prekeys.extend(self.manager.load_unsent_prekeys())
if len(self._unsent_prekeys):
self.setProp(YowAuthenticationProtocolLayer.PROP_PASSIVE, True)
@EventCallback(YowAuthenticationProtocolLayer.EVENT_AUTHED)
def onAuthed(self, yowLayerEvent):
if yowLayerEvent.getArg("passive") and len(self._unsent_prekeys):
logger.debug("SHOULD FLUSH KEYS %d NOW!!" % len(self._unsent_prekeys))
self.flush_keys(
self.manager.load_latest_signed_prekey(generate=True),
self._unsent_prekeys[:], reboot_connection=True
)
self._unsent_prekeys = []
@EventCallback(YowNetworkLayer.EVENT_STATE_DISCONNECTED)
def on_disconnected(self, yowLayerEvent):
super(AxolotlControlLayer, self).on_disconnected(yowLayerEvent)
logger.debug(("Disconnected, reboot_connect? = %s" % self._reboot_connection))
if self._reboot_connection:
self._reboot_connection = False
#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.getLayerInterface(YowNetworkLayer).connect()
def flush_keys(self, signed_prekey, prekeys, reboot_connection=False):
"""
sends prekeys
:return:
:rtype:
"""
preKeysDict = {}
for prekey in prekeys:
keyPair = prekey.getKeyPair()
preKeysDict[self.adjustId(prekey.getId())] = self.adjustArray(keyPair.getPublicKey().serialize()[1:])
signedKeyTuple = (self.adjustId(signed_prekey.getId()),
self.adjustArray(signed_prekey.getKeyPair().getPublicKey().serialize()[1:]),
self.adjustArray(signed_prekey.getSignature()))
setKeysIq = SetKeysIqProtocolEntity(
self.adjustArray(
self.manager.identity.getPublicKey().serialize()[1:]
),
signedKeyTuple,
preKeysDict,
Curve.DJB_TYPE,
self.adjustId(self.manager.registration_id)
)
onResult = lambda _, __: self.on_keys_flushed(prekeys, reboot_connection=reboot_connection)
self._sendIq(setKeysIq, onResult, self.onSentKeysError)
def on_keys_flushed(self, prekeys, reboot_connection):
self.manager.set_prekeys_as_sent(prekeys)
if reboot_connection:
self._reboot_connection = True
self.broadcastEvent(YowLayerEvent(YowNetworkLayer.EVENT_STATE_DISCONNECT))
def onSentKeysError(self, errorNode, keysEntity):
raise Exception("Sent keys were not accepted")
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)
yowsup-3.2.3/yowsup/layers/axolotl/layer_receive.py 0000664 0000000 0000000 00000021352 13464333726 0022622 0 ustar 00root root 0000000 0000000 from .layer_base import AxolotlBaseLayer
from yowsup.layers.protocol_receipts.protocolentities import OutgoingReceiptProtocolEntity
from yowsup.layers.protocol_messages.proto.e2e_pb2 import *
from yowsup.layers.axolotl.protocolentities import *
from yowsup.structs import ProtocolTreeNode
from yowsup.layers.protocol_messages.protocolentities.proto import ProtoProtocolEntity
from yowsup.layers.axolotl.props import PROP_IDENTITY_AUTOTRUST
from yowsup.axolotl import exceptions
from axolotl.untrustedidentityexception import UntrustedIdentityException
import logging
logger = logging.getLogger(__name__)
class AxolotlReceivelayer(AxolotlBaseLayer):
def __init__(self):
super(AxolotlReceivelayer, self).__init__()
self.v2Jids = [] #people we're going to send v2 enc messages
self.sessionCiphers = {}
self.groupCiphers = {}
self.pendingIncomingMessages = {} #(jid, participantJid?) => message
def receive(self, protocolTreeNode):
"""
:type protocolTreeNode: ProtocolTreeNode
"""
if not self.processIqRegistry(protocolTreeNode):
if protocolTreeNode.tag == "message":
self.onMessage(protocolTreeNode)
elif not protocolTreeNode.tag == "receipt":
#receipts will be handled by send layer
self.toUpper(protocolTreeNode)
# elif protocolTreeNode.tag == "iq":
# if protocolTreeNode.getChild("encr_media"):
# protocolTreeNode.addChild("media", {
# "url": protocolTreeNode["url"],
# "ip": protocolTreeNode["ip"],
# })
# self.toUpper(protocolTreeNode)
# return
######
def onEncrMediaResult(self, resultNode):
pass
def processPendingIncomingMessages(self, jid, participantJid = None):
conversationIdentifier = (jid, participantJid)
if conversationIdentifier in self.pendingIncomingMessages:
for messageNode in self.pendingIncomingMessages[conversationIdentifier]:
self.onMessage(messageNode)
del self.pendingIncomingMessages[conversationIdentifier]
##### handling received data #####
def onMessage(self, protocolTreeNode):
encNode = protocolTreeNode.getChild("enc")
if encNode:
self.handleEncMessage(protocolTreeNode)
else:
self.toUpper(protocolTreeNode)
def handleEncMessage(self, node):
encMessageProtocolEntity = EncryptedMessageProtocolEntity.fromProtocolTreeNode(node)
isGroup = node["participant"] is not None
senderJid = node["participant"] if isGroup else node["from"]
if node.getChild("enc")["v"] == "2" and node["from"] not in self.v2Jids:
self.v2Jids.append(node["from"])
try:
if encMessageProtocolEntity.getEnc(EncProtocolEntity.TYPE_PKMSG):
self.handlePreKeyWhisperMessage(node)
elif encMessageProtocolEntity.getEnc(EncProtocolEntity.TYPE_MSG):
self.handleWhisperMessage(node)
if encMessageProtocolEntity.getEnc(EncProtocolEntity.TYPE_SKMSG):
self.handleSenderKeyMessage(node)
except (exceptions.InvalidMessageException, exceptions.InvalidKeyIdException) as e:
logger.warning("InvalidMessage or KeyId for %s, going to send a retry", encMessageProtocolEntity.getAuthor(False))
retry = RetryOutgoingReceiptProtocolEntity.fromMessageNode(node, self.manager.registration_id)
self.toLower(retry.toProtocolTreeNode())
except exceptions.NoSessionException:
logger.warning("No session for %s, getting their keys now", encMessageProtocolEntity.getAuthor(False))
conversationIdentifier = (node["from"], node["participant"])
if conversationIdentifier not in self.pendingIncomingMessages:
self.pendingIncomingMessages[conversationIdentifier] = []
self.pendingIncomingMessages[conversationIdentifier].append(node)
successFn = lambda successJids, b: self.processPendingIncomingMessages(*conversationIdentifier) if len(successJids) else None
self.getKeysFor([senderJid], successFn)
except exceptions.DuplicateMessageException:
logger.warning("Received a message that we've previously decrypted, goint to send the delivery receipt myself")
self.toLower(OutgoingReceiptProtocolEntity(node["id"], node["from"], participant=node["participant"]).toProtocolTreeNode())
except UntrustedIdentityException as e:
if self.getProp(PROP_IDENTITY_AUTOTRUST, False):
logger.warning("Autotrusting identity for %s", e.getName())
self.manager.trust_identity(e.getName(), e.getIdentityKey())
return self.handleEncMessage(node)
else:
logger.error("Ignoring message with untrusted identity")
def handlePreKeyWhisperMessage(self, node):
pkMessageProtocolEntity = EncryptedMessageProtocolEntity.fromProtocolTreeNode(node)
enc = pkMessageProtocolEntity.getEnc(EncProtocolEntity.TYPE_PKMSG)
plaintext = self.manager.decrypt_pkmsg(pkMessageProtocolEntity.getAuthor(False), enc.getData(),
enc.getVersion() == 2)
if enc.getVersion() == 2:
self.parseAndHandleMessageProto(pkMessageProtocolEntity, plaintext)
node = pkMessageProtocolEntity.toProtocolTreeNode()
node.addChild((ProtoProtocolEntity(plaintext, enc.getMediaType())).toProtocolTreeNode())
self.toUpper(node)
def handleWhisperMessage(self, node):
encMessageProtocolEntity = EncryptedMessageProtocolEntity.fromProtocolTreeNode(node)
enc = encMessageProtocolEntity.getEnc(EncProtocolEntity.TYPE_MSG)
plaintext = self.manager.decrypt_msg(encMessageProtocolEntity.getAuthor(False), enc.getData(),
enc.getVersion() == 2)
if enc.getVersion() == 2:
self.parseAndHandleMessageProto(encMessageProtocolEntity, plaintext)
node = encMessageProtocolEntity.toProtocolTreeNode()
node.addChild((ProtoProtocolEntity(plaintext, enc.getMediaType())).toProtocolTreeNode())
self.toUpper(node)
def handleSenderKeyMessage(self, node):
encMessageProtocolEntity = EncryptedMessageProtocolEntity.fromProtocolTreeNode(node)
enc = encMessageProtocolEntity.getEnc(EncProtocolEntity.TYPE_SKMSG)
try:
plaintext = self.manager.group_decrypt (
groupid=encMessageProtocolEntity.getFrom(True),
participantid=encMessageProtocolEntity.getParticipant(False),
data=enc.getData()
)
self.parseAndHandleMessageProto(encMessageProtocolEntity, plaintext)
node = encMessageProtocolEntity.toProtocolTreeNode()
node.addChild((ProtoProtocolEntity(plaintext, enc.getMediaType())).toProtocolTreeNode())
self.toUpper(node)
except exceptions.NoSessionException:
logger.warning("No session for %s, going to send a retry", encMessageProtocolEntity.getAuthor(False))
retry = RetryOutgoingReceiptProtocolEntity.fromMessageNode(node, self.manager.registration_id)
self.toLower(retry.toProtocolTreeNode())
except exceptions.DuplicateMessageException:
logger.warning(
"Received a message that we've previously decrypted, goint to send the delivery receipt myself"
)
self.toLower(
OutgoingReceiptProtocolEntity(
node["id"], node["from"], participant=node["participant"]
).toProtocolTreeNode()
)
def parseAndHandleMessageProto(self, encMessageProtocolEntity, serializedData):
m = Message()
try:
m.ParseFromString(serializedData)
except:
print("DUMP:")
print(serializedData)
print([s for s in serializedData])
# print([ord(s) for s in serializedData])
raise
if not m or not serializedData:
raise ValueError("Empty message")
if m.HasField("sender_key_distribution_message"):
self.handleSenderKeyDistributionMessage(
m.sender_key_distribution_message,
encMessageProtocolEntity.getParticipant(False)
)
def handleSenderKeyDistributionMessage(self, senderKeyDistributionMessage, participantId):
groupId = senderKeyDistributionMessage.group_id
self.manager.group_create_session(
groupid=groupId,
participantid=participantId,
skmsgdata=senderKeyDistributionMessage.axolotl_sender_key_distribution_message
)
yowsup-3.2.3/yowsup/layers/axolotl/layer_send.py 0000664 0000000 0000000 00000025114 13464333726 0022131 0 ustar 00root root 0000000 0000000 from yowsup.layers.protocol_messages.proto.e2e_pb2 import Message
from yowsup.layers.axolotl.protocolentities import *
from yowsup.layers.auth.layer_authentication import YowAuthenticationProtocolLayer
from yowsup.layers.protocol_groups.protocolentities import InfoGroupsIqProtocolEntity, InfoGroupsResultIqProtocolEntity
from axolotl.protocol.whispermessage import WhisperMessage
from yowsup.layers.protocol_messages.protocolentities.message import MessageAttributes
from .layer_base import AxolotlBaseLayer
import logging
logger = logging.getLogger(__name__)
class AxolotlSendLayer(AxolotlBaseLayer):
MAX_SENT_QUEUE = 100
def __init__(self):
super(AxolotlSendLayer, self).__init__()
self.sessionCiphers = {}
self.groupCiphers = {}
'''
Sent messages will be put in Queue until we receive a receipt for them.
This is for handling retry receipts which requires re-encrypting and resend of the original message
As the receipt for a sent message might arrive at a different yowsup instance,
ideally the original message should be fetched from a persistent storage.
Therefore, if the original message is not in sentQueue for any reason, we will
notify the upper layers and let them handle it.
'''
self.sentQueue = []
def __str__(self):
return "Axolotl Layer"
def send(self, node):
if node.tag == "message" and node["to"] not in self.skipEncJids:
self.processPlaintextNodeAndSend(node)
else:
self.toLower(node)
def receive(self, protocolTreeNode):
if not self.processIqRegistry(protocolTreeNode):
if protocolTreeNode.tag == "receipt":
'''
Going to keep all group message enqueued, as we get receipts from each participant
So can't just remove it on first receipt. Therefore, the MAX queue length mechanism should better be working
'''
messageNode = self.getEnqueuedMessageNode(protocolTreeNode["id"], protocolTreeNode["participant"] is not None)
if not messageNode:
logger.debug("Axolotl layer does not have the message, bubbling it upwards")
self.toUpper(protocolTreeNode)
elif protocolTreeNode["type"] == "retry":
logger.info("Got retry to for message %s, and Axolotl layer has the message" % protocolTreeNode["id"])
retryReceiptEntity = RetryIncomingReceiptProtocolEntity.fromProtocolTreeNode(protocolTreeNode)
self.toLower(retryReceiptEntity.ack().toProtocolTreeNode())
self.getKeysFor(
[protocolTreeNode["participant"] or protocolTreeNode["from"]],
lambda successJids, b: self.processPlaintextNodeAndSend(messageNode, retryReceiptEntity) if len(successJids) == 1 else None
)
else:
#not interested in any non retry receipts, bubble upwards
self.toUpper(protocolTreeNode)
def processPlaintextNodeAndSend(self, node, retryReceiptEntity = None):
recipient_id = node["to"].split('@')[0]
isGroup = "-" in recipient_id
if isGroup:
self.sendToGroup(node, retryReceiptEntity)
elif self.manager.session_exists(recipient_id):
self.sendToContact(node)
else:
self.getKeysFor([node["to"]], lambda successJids, b: self.sendToContact(node) if len(successJids) == 1 else self.toLower(node), lambda: self.toLower(node))
def enqueueSent(self, node):
logger.debug("enqueueSent(node=[omitted])")
if len(self.sentQueue) >= self.__class__.MAX_SENT_QUEUE:
logger.warn("Discarding queued node without receipt")
self.sentQueue.pop(0)
self.sentQueue.append(node)
def getEnqueuedMessageNode(self, messageId, keepEnqueued = False):
for i in range(0, len(self.sentQueue)):
if self.sentQueue[i]["id"] == messageId:
if keepEnqueued:
return self.sentQueue[i]
return self.sentQueue.pop(i)
def sendEncEntities(self, node, encEntities, participant=None):
logger.debug("sendEncEntities(node=[omitted], encEntities=[omitted], participant=%s)" % participant)
message_attrs = MessageAttributes.from_message_protocoltreenode(node)
message_attrs.participant = participant
messageEntity = EncryptedMessageProtocolEntity(
encEntities,
node["type"],
message_attrs
)
# if participant is set, this message is directed to that specific participant as a result of a retry, therefore
# we already have the original group message and there is no need to store it again.
if participant is None:
self.enqueueSent(node)
self.toLower(messageEntity.toProtocolTreeNode())
def sendToContact(self, node):
recipient_id = node["to"].split('@')[0]
protoNode = node.getChild("proto")
messageData = protoNode.getData()
ciphertext = self.manager.encrypt(
recipient_id,
messageData
)
mediaType = protoNode["mediatype"]
return self.sendEncEntities(node, [EncProtocolEntity(EncProtocolEntity.TYPE_MSG if ciphertext.__class__ == WhisperMessage else EncProtocolEntity.TYPE_PKMSG, 2, ciphertext.serialize(), mediaType)])
def sendToGroupWithSessions(self, node, jidsNeedSenderKey = None, retryCount=0):
"""
For each jid in jidsNeedSenderKey will create a pkmsg enc node with the associated jid.
If retryCount > 0 and we have only one jidsNeedSenderKey, this is a retry requested by a specific participant
and this message is to be directed at specific at that participant indicated by jidsNeedSenderKey[0]. In this
case the participant's jid would go in the parent's EncryptedMessage and not into the enc node.
"""
logger.debug(
"sendToGroupWithSessions(node=[omitted], jidsNeedSenderKey=%s, retryCount=%d)" % (jidsNeedSenderKey, retryCount)
)
jidsNeedSenderKey = jidsNeedSenderKey or []
groupJid = node["to"]
protoNode = node.getChild("proto")
encEntities = []
participant = jidsNeedSenderKey[0] if len(jidsNeedSenderKey) == 1 and retryCount > 0 else None
if len(jidsNeedSenderKey):
senderKeyDistributionMessage = self.manager.group_create_skmsg(groupJid)
for jid in jidsNeedSenderKey:
message = self.serializeSenderKeyDistributionMessageToProtobuf(node["to"], senderKeyDistributionMessage)
if retryCount > 0:
message.MergeFromString(protoNode.getData())
ciphertext = self.manager.encrypt(jid.split('@')[0], message.SerializeToString())
encEntities.append(
EncProtocolEntity(
EncProtocolEntity.TYPE_MSG if ciphertext.__class__ == WhisperMessage else EncProtocolEntity.TYPE_PKMSG
, 2, ciphertext.serialize(), protoNode["mediatype"], jid=None if participant else jid
)
)
if not retryCount:
messageData = protoNode.getData()
ciphertext = self.manager.group_encrypt(groupJid, messageData)
mediaType = protoNode["mediatype"]
encEntities.append(EncProtocolEntity(EncProtocolEntity.TYPE_SKMSG, 2, ciphertext, mediaType))
self.sendEncEntities(node, encEntities, participant)
def ensureSessionsAndSendToGroup(self, node, jids):
logger.debug("ensureSessionsAndSendToGroup(node=[omitted], jids=%s)" % jids)
jidsNoSession = []
for jid in jids:
if not self.manager.session_exists(jid.split('@')[0]):
jidsNoSession.append(jid)
if len(jidsNoSession):
self.getKeysFor(jidsNoSession, lambda successJids, b: self.sendToGroupWithSessions(node, successJids))
else:
self.sendToGroupWithSessions(node, jids)
def sendToGroup(self, node, retryReceiptEntity = None):
"""
Group send sequence:
check if senderkeyrecord exists
no: - create,
- get group jids from info request
- for each jid without a session, get keys to create the session
- send message with dist key for all participants
yes:
- send skmsg without any dist key
received retry for a participant
- request participants keys
- send message with dist key only + conversation, only for this participat
"""
logger.debug("sendToGroup(node=[omitted], retryReceiptEntity=[%s])" %
("[retry_count=%s, retry_jid=%s]" % (
retryReceiptEntity.getRetryCount(), retryReceiptEntity.getRetryJid())
) if retryReceiptEntity is not None else None)
groupJid = node["to"]
ownJid = self.getLayerInterface(YowAuthenticationProtocolLayer).getUsername(True)
senderKeyRecord = self.manager.load_senderkey(node["to"])
def sendToGroup(resultNode, requestEntity):
groupInfo = InfoGroupsResultIqProtocolEntity.fromProtocolTreeNode(resultNode)
jids = list(groupInfo.getParticipants().keys()) #keys in py3 returns dict_keys
if ownJid in jids:
jids.remove(ownJid)
return self.ensureSessionsAndSendToGroup(node, jids)
if senderKeyRecord.isEmpty():
logger.debug("senderKeyRecord is empty, requesting group info")
groupInfoIq = InfoGroupsIqProtocolEntity(groupJid)
self._sendIq(groupInfoIq, sendToGroup)
else:
logger.debug("We have a senderKeyRecord")
retryCount = 0
jidsNeedSenderKey = []
if retryReceiptEntity is not None:
retryCount = retryReceiptEntity.getRetryCount()
jidsNeedSenderKey.append(retryReceiptEntity.getRetryJid())
self.sendToGroupWithSessions(node, jidsNeedSenderKey, retryCount)
def serializeSenderKeyDistributionMessageToProtobuf(self, groupId, senderKeyDistributionMessage, message = None):
m = message or Message()
m.sender_key_distribution_message.group_id = groupId
m.sender_key_distribution_message.axolotl_sender_key_distribution_message = senderKeyDistributionMessage.serialize()
m.sender_key_distribution_message.axolotl_sender_key_distribution_message = senderKeyDistributionMessage.serialize()
# m.conversation = text
return m
yowsup-3.2.3/yowsup/layers/axolotl/props.py 0000664 0000000 0000000 00000000125 13464333726 0021142 0 ustar 00root root 0000000 0000000 PROP_IDENTITY_AUTOTRUST = "org.openwhatsapp.yowsup.prop.axolotl.INDENTITY_AUTOTRUST" yowsup-3.2.3/yowsup/layers/axolotl/protocolentities/ 0000775 0000000 0000000 00000000000 13464333726 0023035 5 ustar 00root root 0000000 0000000 yowsup-3.2.3/yowsup/layers/axolotl/protocolentities/__init__.py 0000664 0000000 0000000 00000001056 13464333726 0025150 0 ustar 00root root 0000000 0000000 from .iq_key_get import GetKeysIqProtocolEntity
from .iq_keys_set import SetKeysIqProtocolEntity
from .iq_keys_get_result import ResultGetKeysIqProtocolEntity
from .message_encrypted import EncryptedMessageProtocolEntity
from .enc import EncProtocolEntity
from .receipt_outgoing_retry import RetryOutgoingReceiptProtocolEntity
from .receipt_incoming_retry import RetryIncomingReceiptProtocolEntity
from .notification_encrypt_identitychange import IdentityChangeEncryptNotification
from .notification_encrypt_requestkeys import RequestKeysEncryptNotification
yowsup-3.2.3/yowsup/layers/axolotl/protocolentities/enc.py 0000664 0000000 0000000 00000002610 13464333726 0024153 0 ustar 00root root 0000000 0000000 from yowsup.structs import ProtocolEntity, ProtocolTreeNode
import sys
class EncProtocolEntity(ProtocolEntity):
TYPE_PKMSG = "pkmsg"
TYPE_MSG = "msg"
TYPE_SKMSG = "skmsg"
TYPES = (TYPE_PKMSG, TYPE_MSG, TYPE_SKMSG)
def __init__(self, type, version, data, mediaType = None, jid = None):
assert type in self.__class__.TYPES, "Unknown message enc type %s" % type
super(EncProtocolEntity, self).__init__("enc")
self.type = type
self.version = int(version)
self.data = data
self.mediaType = mediaType
self.jid = jid
def getType(self):
return self.type
def getVersion(self):
return self.version
def getData(self):
return self.data
def getMediaType(self):
return self.mediaType
def getJid(self):
return self.jid
def toProtocolTreeNode(self):
attribs = {"type": self.type, "v": str(self.version)}
if self.mediaType:
attribs["mediatype"] = self.mediaType
encNode = ProtocolTreeNode("enc", attribs, data = self.data)
if self.jid:
return ProtocolTreeNode("to", {"jid": self.jid}, [encNode])
return encNode
@staticmethod
def fromProtocolTreeNode(node):
return EncProtocolEntity(node["type"], node["v"], node.data.encode('latin-1') if sys.version_info >= (3,0) else node.data, node["mediatype"])
yowsup-3.2.3/yowsup/layers/axolotl/protocolentities/iq_key_get.py 0000664 0000000 0000000 00000002477 13464333726 0025541 0 ustar 00root root 0000000 0000000 from yowsup.common import YowConstants
from yowsup.layers.protocol_iq.protocolentities import IqProtocolEntity
from yowsup.structs import ProtocolTreeNode
class GetKeysIqProtocolEntity(IqProtocolEntity):
def __init__(self, jids, reason=None):
super(GetKeysIqProtocolEntity, self).__init__("encrypt", _type="get", to=YowConstants.WHATSAPP_SERVER)
self.jids = jids
self.reason = reason
@property
def reason(self):
# type: () -> str
return self._reason
@reason.setter
def reason(self, value):
# type: (str) -> None
self._reason = value
@property
def jids(self):
# type: () -> list[str]
return self._jids
@jids.setter
def jids(self, value):
# type: (list[str]) -> None
assert type(value) is list, "expected list of jids, got %s" % type(value)
self._jids = value
def toProtocolTreeNode(self):
node = super(GetKeysIqProtocolEntity, self).toProtocolTreeNode()
keyNode = ProtocolTreeNode("key")
for jid in self.jids:
attrs = { "jid": jid }
if self.reason is not None:
attrs["reason"] = self.reason
userNode = ProtocolTreeNode("user", attrs)
keyNode.addChild(userNode)
node.addChild(keyNode)
return node
yowsup-3.2.3/yowsup/layers/axolotl/protocolentities/iq_keys_get_result.py 0000664 0000000 0000000 00000013077 13464333726 0027320 0 ustar 00root root 0000000 0000000 from yowsup.common import YowConstants
from 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 = YowConstants.WHATSAPP_SERVER, _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-3.2.3/yowsup/layers/axolotl/protocolentities/iq_keys_set.py 0000664 0000000 0000000 00000005504 13464333726 0025732 0 ustar 00root root 0000000 0000000 from yowsup.common import YowConstants
from 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 = YowConstants.WHATSAPP_SERVER)
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 node
yowsup-3.2.3/yowsup/layers/axolotl/protocolentities/message_encrypted.py 0000664 0000000 0000000 00000004373 13464333726 0027117 0 ustar 00root root 0000000 0000000 from yowsup.layers.protocol_messages.protocolentities import MessageProtocolEntity
from yowsup.structs import ProtocolTreeNode
from yowsup.layers.axolotl.protocolentities.enc import EncProtocolEntity
class EncryptedMessageProtocolEntity(MessageProtocolEntity):
'''
HEX:33089eb3c90312210510e0196be72fe65913c6a84e75a54f40a3ee290574d6a23f408df990e718da761a210521f1a3f3d5cb87fde19fadf618d3001b64941715efd3e0f36bba48c23b08c82f2242330a21059b0ce2c4720ec79719ba862ee3cda6d6332746d05689af13aabf43ea1c8d747f100018002210d31cd6ebea79e441c4935f72398c772e2ee21447eb675cfa28b99de8d2013000
'''
def __init__(self, encEntities, _type, messageAttributes):
super(EncryptedMessageProtocolEntity, self).__init__(_type, messageAttributes)
self.setEncEntities(encEntities)
def setEncEntities(self, encEntities = None):
assert type(encEntities) is list and len(encEntities) \
, "Must have at least a list of minumum 1 enc entity"
self.encEntities = encEntities
def getEnc(self, encType):
for enc in self.encEntities:
if enc.type == encType:
return enc
def getEncEntities(self):
return self.encEntities
def toProtocolTreeNode(self):
node = super(EncryptedMessageProtocolEntity, self).toProtocolTreeNode()
participantsNode = ProtocolTreeNode("participants")
for enc in self.encEntities:
encNode = enc.toProtocolTreeNode()
if encNode.tag == "to":
participantsNode.addChild(encNode)
else:
node.addChild(encNode)
if len(participantsNode.getAllChildren()):
node.addChild(participantsNode)
return node
@staticmethod
def fromProtocolTreeNode(node):
entity = MessageProtocolEntity.fromProtocolTreeNode(node)
entity.__class__ = EncryptedMessageProtocolEntity
entity.setEncEntities(
[EncProtocolEntity.fromProtocolTreeNode(encNode) for encNode in node.getAllChildren("enc")]
)
return entity
yowsup-3.2.3/yowsup/layers/axolotl/protocolentities/notification_encrypt_identitychange.py 0000664 0000000 0000000 00000002004 13464333726 0032714 0 ustar 00root root 0000000 0000000 from yowsup.common import YowConstants
from yowsup.layers.protocol_notifications.protocolentities import NotificationProtocolEntity
from yowsup.structs import ProtocolTreeNode
class IdentityChangeEncryptNotification(NotificationProtocolEntity):
"""
"""
def __init__(self, timestamp, _id = None, notify = None, offline = None):
super(IdentityChangeEncryptNotification, self).__init__(
"encrypt", _id, YowConstants.WHATSAPP_SERVER, timestamp, notify, offline
)
def toProtocolTreeNode(self):
node = super(IdentityChangeEncryptNotification, self).toProtocolTreeNode()
node.addChild(ProtocolTreeNode("identity"))
return node
@staticmethod
def fromProtocolTreeNode(node):
entity = NotificationProtocolEntity.fromProtocolTreeNode(node)
entity.__class__ = IdentityChangeEncryptNotification
return entity
yowsup-3.2.3/yowsup/layers/axolotl/protocolentities/notification_encrypt_requestkeys.py 0000664 0000000 0000000 00000002453 13464333726 0032311 0 ustar 00root root 0000000 0000000 from yowsup.common import YowConstants
from yowsup.layers.protocol_notifications.protocolentities import NotificationProtocolEntity
from yowsup.structs import ProtocolTreeNode
class RequestKeysEncryptNotification(NotificationProtocolEntity):
"""
"""
def __init__(self, count, timestamp, _id = None, notify = None, offline = None):
super(RequestKeysEncryptNotification, self).__init__(
"encrypt", _id, YowConstants.WHATSAPP_SERVER, timestamp, notify, offline
)
self._count = count
@property
def count(self):
return self._count
@count.setter
def count(self, value):
self._count = value
def toProtocolTreeNode(self):
node = super(RequestKeysEncryptNotification, self).toProtocolTreeNode()
count_node = ProtocolTreeNode("count", {"value": str(self.count)})
node.addChild(count_node)
return node
@staticmethod
def fromProtocolTreeNode(node):
entity = NotificationProtocolEntity.fromProtocolTreeNode(node)
entity.__class__ = RequestKeysEncryptNotification
entity.count = node.getChild("count")["value"]
return entity
yowsup-3.2.3/yowsup/layers/axolotl/protocolentities/receipt_incoming_retry.py 0000664 0000000 0000000 00000004561 13464333726 0030160 0 ustar 00root root 0000000 0000000 from yowsup.structs import ProtocolTreeNode
from yowsup.layers.protocol_receipts.protocolentities import IncomingReceiptProtocolEntity
from yowsup.layers.axolotl.protocolentities.iq_keys_get_result import ResultGetKeysIqProtocolEntity
class RetryIncomingReceiptProtocolEntity(IncomingReceiptProtocolEntity):
'''
HEX:xxxxxxxxx
'''
def __init__(self, _id, jid, remoteRegistrationId, receiptTimestamp, retryTimestamp, v = 1, count = 1, participant = None, offline = None):
super(RetryIncomingReceiptProtocolEntity, self).__init__(_id, jid, receiptTimestamp, offline=offline, type="retry", participant=participant)
self.setRetryData(remoteRegistrationId, v,count, retryTimestamp)
def setRetryData(self, remoteRegistrationId, v, count, retryTimestamp):
self.remoteRegistrationId = remoteRegistrationId
self.v = int(v)
self.count = int(count)
self.retryTimestamp = int(retryTimestamp)
def toProtocolTreeNode(self):
node = super(RetryIncomingReceiptProtocolEntity, self).toProtocolTreeNode()
retry = ProtocolTreeNode("retry", {
"count": str(self.count),
"id": self.getId(),
"v": str(self.v),
"t": str(self.retryTimestamp)
})
node.addChild(retry)
registration = ProtocolTreeNode("registration", data=ResultGetKeysIqProtocolEntity._intToBytes(self.remoteRegistrationId))
node.addChild(registration)
return node
def getRetryCount(self):
return self.count
def getRetryJid(self):
return self.getParticipant() or self.getFrom()
def __str__(self):
out = super(RetryIncomingReceiptProtocolEntity, self).__str__()
return out
@staticmethod
def fromProtocolTreeNode(node):
entity = IncomingReceiptProtocolEntity.fromProtocolTreeNode(node)
entity.__class__ = RetryIncomingReceiptProtocolEntity
retryNode = node.getChild("retry")
entity.setRetryData(ResultGetKeysIqProtocolEntity._bytesToInt(node.getChild("registration").data), retryNode["v"], retryNode["count"], retryNode["t"])
return entity
yowsup-3.2.3/yowsup/layers/axolotl/protocolentities/receipt_outgoing_retry.py 0000664 0000000 0000000 00000005431 13464333726 0030205 0 ustar 00root root 0000000 0000000 from yowsup.structs import 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, jid, localRegistrationId, retryTimestamp, v = 1, count = 1, participant = None):
super(RetryOutgoingReceiptProtocolEntity, self).__init__(_id, jid, participant=participant)
'''
Note to self: Android clients won't retry sending if the retry node didn't contain the message timestamp
'''
self.setRetryData(localRegistrationId, v,count, retryTimestamp)
def setRetryData(self, localRegistrationId, v, count, retryTimestamp):
self.localRegistrationId = localRegistrationId
self.v = v
self.count = count
self.retryTimestamp = int(retryTimestamp)
def toProtocolTreeNode(self):
node = super(RetryOutgoingReceiptProtocolEntity, self).toProtocolTreeNode()
node.setAttribute("type", "retry")
retryAttribs = {
"count": str(self.count),
"id":self.getId(),
"v":str(self.v),
"t": str(self.retryTimestamp)
}
retry = ProtocolTreeNode("retry", retryAttribs)
node.addChild(retry)
registration = ProtocolTreeNode("registration", data=ResultGetKeysIqProtocolEntity._intToBytes(self.localRegistrationId))
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(ResultGetKeysIqProtocolEntity._bytesToInt(node.getChild("registration").data), retryNode["v"], retryNode["count"], retryNode["t"])
return entity
@staticmethod
def fromMessageNode(messageNodeToBeRetried, localRegistrationId):
return RetryOutgoingReceiptProtocolEntity(
messageNodeToBeRetried.getAttributeValue("id"),
messageNodeToBeRetried.getAttributeValue("from"),
localRegistrationId,
messageNodeToBeRetried.getAttributeValue("t"),
participant=messageNodeToBeRetried.getAttributeValue("participant")
)
yowsup-3.2.3/yowsup/layers/axolotl/protocolentities/test_iq_keys_get_result.py 0000664 0000000 0000000 00000005444 13464333726 0030356 0 ustar 00root root 0000000 0000000 from yowsup.common import YowConstants
from 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" % (i, YowConstants.WHATSAPP_SERVER)})
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-3.2.3/yowsup/layers/axolotl/protocolentities/test_iq_keys_set.py 0000664 0000000 0000000 00000001747 13464333726 0026776 0 ustar 00root root 0000000 0000000 from 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-3.2.3/yowsup/layers/axolotl/protocolentities/test_notification_encrypt_requestkeys.py 0000664 0000000 0000000 00000001024 13464333726 0033341 0 ustar 00root root 0000000 0000000 from yowsup.layers.protocol_notifications.protocolentities.test_notification import NotificationProtocolEntityTest
from yowsup.layers.axolotl.protocolentities import RequestKeysEncryptNotification
from yowsup.structs import ProtocolTreeNode
class TestRequestKeysEncryptNotification(NotificationProtocolEntityTest):
def setUp(self):
super(TestRequestKeysEncryptNotification, self).setUp()
self.ProtocolEntity = RequestKeysEncryptNotification
self.node.addChild(ProtocolTreeNode("count", {"value": "9"})) yowsup-3.2.3/yowsup/layers/coder/ 0000775 0000000 0000000 00000000000 13464333726 0017041 5 ustar 00root root 0000000 0000000 yowsup-3.2.3/yowsup/layers/coder/__init__.py 0000664 0000000 0000000 00000000040 13464333726 0021144 0 ustar 00root root 0000000 0000000 from .layer import YowCoderLayer yowsup-3.2.3/yowsup/layers/coder/decoder.py 0000664 0000000 0000000 00000021336 13464333726 0021025 0 ustar 00root root 0000000 0000000 from yowsup.structs import ProtocolTreeNode
import math
import binascii
import sys
import zlib
class ReadDecoder:
def __init__(self, tokenDictionary):
self.tokenDictionary = tokenDictionary
def getProtocolTreeNode(self, data):
if type(data) is list:
data = bytearray(data)
if data[0] & self.tokenDictionary.FLAG_DEFLATE != 0:
data = bytearray(b'\x00' + zlib.decompress(bytes(data[1:])))
if data[0] & self.tokenDictionary.FLAG_SEGMENTED != 0:
raise ValueError("server to client stanza fragmentation not supported")
return self.nextTreeInternal(data[1:])
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 getTokenDouble(self, n, n2):
pos = n2 + n * 256
token = self.tokenDictionary.getToken(pos, True)
if not token:
raise ValueError("Invalid token %s" % pos)
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 readPacked8(self, n, data):
size = self.readInt8(data)
remove = 0
if (size & 0x80) != 0 and n == 251:
remove = 1
size = size & 0x7F
text = bytearray(self.readArray(size, data))
hexData = binascii.hexlify(str(text) if sys.version_info < (2,7) else text).upper()
dataSize = len(hexData)
out = []
if remove == 0:
for i in range(0, dataSize):
char = chr(hexData[i]) if type(hexData[i]) is int else hexData[i] #python2/3 compat
val = ord(binascii.unhexlify("0%s" % char))
if i == (dataSize - 1) and val > 11 and n != 251: continue
out.append(self.unpackByte(n, val))
else:
out = map(ord, list(hexData[0: -remove])) if sys.version_info < (3,0) else list(hexData[0: -remove])
return out
def unpackByte(self, n, n2):
if n == 251:
return self.unpackHex(n2)
if n == 255:
return self.unpackNibble(n2)
raise ValueError("bad packed type %s" % n)
def unpackHex(self, n):
if n in range(0, 10):
return n + 48
if n in range(10, 16):
return 65 + (n - 10)
raise ValueError("bad hex %s" % n)
def unpackNibble(self, n):
if n in range(0, 10):
return n + 48
if n in (10, 11):
return 45 + (n - 10)
raise ValueError("bad nibble %s" % n)
def readHeader(self, data, offset = 0):
ret = 0
if len(data) >= (3 + offset):
b0 = data[offset]
b1 = data[offset + 1]
b2 = data[offset + 2]
ret = b0 + (b1 << 16) + (b2 << 8)
return ret
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 readInt20(self, data):
int1 = data.pop(0)
int2 = data.pop(0)
int3 = data.pop(0)
return ((int1 & 0xF) << 16) | (int2 << 8) | int3
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 readInt31(self, data):
data.pop(0)
int1 = data.pop(0)
int2 = data.pop(0)
int3 = data.pop(0)
return (int1 << 24) | (int1 << 16) | int2 << 8 | int3
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(self.readInt8(data), data)
value = self.readString(self.readInt8(data), data)
attribs[key]=value
return attribs
def readString(self,token, data):
if token == -1:
raise Exception("-1 token in readString")
if 2 < token < 236:
return self.getToken(token, data)
if token == 0:
return None
if token in (236, 237, 238, 239):
return self.getTokenDouble(token - 236, self.readInt8(data))
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")
if token in (251, 255):
return "".join(map(chr, self.readPacked8(token, data)))
if token == 252:
size8 = self.readInt8(data)
buf8 = self.readArray(size8, data)
return "".join(map(chr, buf8))
if token == 253:
size20 = self.readInt20(data)
buf20 = self.readArray(size20, data)
return "".join(map(chr, buf20))
if token == 254:
size31 = self.readInt31()
buf31 = self.readArray(size31, data)
return "".join(map(chr, buf31))
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):
size = self.readListSize(self.readInt8(data), data)
token = self.readInt8(data)
if token == 1:
token = self.readInt8(data)
if token == 2:
return None
tag = self.readString(token, 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)
read2 = self.readInt8(data)
nodeData = None
nodeChildren = None
if self.isListTag(read2):
nodeChildren = self.readList(read2, data)
elif read2 == 252:
size = self.readInt8(data)
nodeData = self.readArray(size, data)
elif read2 == 253:
size = self.readInt20(data)
nodeData = self.readArray(size, data)
elif read2 == 254:
size = self.readInt31(data)
nodeData = self.readArray(size, data)
elif read2 in (255, 251):
nodeData = self.readPacked8(read2, data)
else:
nodeData = self.readString(read2, data)
if nodeData and type(nodeData) is not str:
nodeData = "".join(map(chr, nodeData))
return ProtocolTreeNode(tag, attribs, nodeChildren, nodeData)
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-3.2.3/yowsup/layers/coder/encoder.py 0000664 0000000 0000000 00000012633 13464333726 0021037 0 ustar 00root root 0000000 0000000 class WriteEncoder:
def __init__(self, tokenDictionary):
self.tokenDictionary = tokenDictionary
def protocolTreeNodeToBytes(self, node):
outBytes = [0] # flags
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, True);
def writeBytes(self, bytes_, data, packed = False):
bytes__ = []
for b in bytes_:
if type(b) is int:
bytes__.append(b)
else:
bytes__.append(ord(b))
size = len(bytes__)
toWrite = bytes__
if size >= 0x100000:
data.append(254)
self.writeInt31(size, data)
elif size >= 0x100:
data.append(253)
self.writeInt20(size, data)
else:
r = None
if packed:
if size < 128:
r = self.tryPackAndWriteHeader(255, bytes__, data)
if r is None:
r = self.tryPackAndWriteHeader(251, bytes__, data)
if r is None:
data.append(252)
self.writeInt8(size, data)
else:
toWrite = r
data.extend(toWrite)
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 writeInt20(self, v, data):
data.append((0xF0000 & v) >> 16)
data.append((0xFF00 & v) >> 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 writeInt31(self, v, data):
data.append((0x7F000000 & v) >> 24)
data.append((0xFF0000 & v) >> 16)
data.append((0xFF00 & v) >> 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, token, data):
if token <= 255 and token >=0:
data.append(token)
else:
raise ValueError("Invalid token: %s" % token)
def writeString(self, tag, data, packed = False):
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, packed)
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, True)
else:
self.writeToken(0, data)
self.writeString(server, data)
def tryPackAndWriteHeader(self, v, headerData, data):
size = len(headerData)
if size >= 128:
return None
arr = [0] * int((size + 1) / 2)
for i in range(0, size):
packByte = self.packByte(v, headerData[i])
if packByte == -1:
arr = []
break
n2 = int(i / 2)
arr[n2] |= (packByte << 4 * (1 - i % 2))
if len(arr) > 0:
if size % 2 == 1:
arr[-1] |= 15 #0xF
data.append(v)
self.writeInt8(size %2 << 7 | len(arr), data)
return arr
return None
def packByte(self, v, n2):
if v == 251:
return self.packHex(n2)
if v == 255:
return self.packNibble(n2)
return -1
def packHex(self, n):
if n in range(48, 58):
return n - 48
if n in range(65, 71):
return 10 + (n - 65)
return -1
def packNibble(self, n):
if n in (45, 46):
return 10 + (n - 45)
if n in range(48, 58):
return n - 48
return -1
yowsup-3.2.3/yowsup/layers/coder/layer.py 0000664 0000000 0000000 00000001474 13464333726 0020535 0 ustar 00root root 0000000 0000000 from yowsup.layers import YowLayer
from .encoder import WriteEncoder
from .decoder import ReadDecoder
from .tokendictionary import TokenDictionary
class YowCoderLayer(YowLayer):
def __init__(self):
YowLayer.__init__(self)
tokenDictionary = TokenDictionary()
self.writer = WriteEncoder(tokenDictionary)
self.reader = ReadDecoder(tokenDictionary)
def send(self, data):
self.write(self.writer.protocolTreeNodeToBytes(data))
def receive(self, data):
node = self.reader.getProtocolTreeNode(bytearray(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-3.2.3/yowsup/layers/coder/test_decoder.py 0000664 0000000 0000000 00000001431 13464333726 0022056 0 ustar 00root root 0000000 0000000 import 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 = [0, 248, 6, 95, 179, 252, 3, 120, 121, 122, 252, 4, 102, 111, 114, 109, 252, 3, 97, 98, 99, 248, 1, 248, 4, 93,
236, 104, 255, 130, 18, 63, 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-3.2.3/yowsup/layers/coder/test_encoder.py 0000664 0000000 0000000 00000001742 13464333726 0022075 0 ustar 00root root 0000000 0000000 import 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 (
[0, 248, 6, 95, 179, 252, 3, 120, 121, 122, 252, 4, 102, 111, 114, 109, 252, 3, 97, 98, 99, 248, 1, 248, 4, 93,
236, 104, 255, 130, 18, 63, 252, 6, 49, 50, 51, 52, 53, 54],
[0, 248, 6, 95, 252, 4, 102, 111, 114, 109, 252, 3, 97, 98, 99, 179, 252, 3, 120, 121, 122, 248, 1, 248, 4, 93,
236, 104, 255, 130, 18, 63, 252, 6, 49, 50, 51, 52, 53, 54]
)
)
yowsup-3.2.3/yowsup/layers/coder/test_tokendictionary.py 0000664 0000000 0000000 00000001343 13464333726 0023661 0 ustar 00root root 0000000 0000000 from 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(80), "iq")
def test_getIndex(self):
self.assertEqual(self.tokenDictionary.getIndex("iq"), (80, False))
def test_getSecondaryToken(self):
self.assertEqual(self.tokenDictionary.getToken(238), "amrnb")
def test_getSecondaryTokenExplicit(self):
self.assertEqual(self.tokenDictionary.getToken(11, True), "wmv")
def test_getSecondaryIndex(self):
self.assertEqual(self.tokenDictionary.getIndex("wmv"), (11, True)) yowsup-3.2.3/yowsup/layers/coder/tokendictionary.py 0000664 0000000 0000000 00000030754 13464333726 0022632 0 ustar 00root root 0000000 0000000 class TokenDictionary:
FLAG_SEGMENTED = 0x1
FLAG_DEFLATE = 0x2
def __init__(self):
self.dictionary = [
'',
'',
'',
'account',
'ack',
'action',
'active',
'add',
'after',
'all',
'allow',
'apple',
'audio',
'auth',
'author',
'available',
'bad-protocol',
'bad-request',
'before',
'bits',
'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',
'encrypt',
'error',
'event',
'expiration',
'expired',
'fail',
'failure',
'false',
'favorites',
'feature',
'features',
'feature-not-implemented',
'field',
'file',
'filehash',
'first',
'free',
'from',
'g.us',
'gcm',
'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',
'mimetype',
'missing',
'modify',
'msg',
'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',
'pkmsg',
'platform',
'port',
'presence',
'preview',
'probe',
'prop',
'props',
'qcount',
'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',
'size',
'skmsg',
'stat',
'state',
'status',
'stream:error',
'stream:features',
'subject',
'subscribe',
'success',
'sync',
't',
'text',
'timeout',
'timestamp',
'tizen',
'to',
'true',
'type',
'unavailable',
'unsubscribe',
'upgrade',
'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',
'v',
'value',
'version',
'voip',
'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',
'background',
'backoff',
'chunked',
'context',
'full',
'in',
'interactive',
'out',
'registration',
'sid',
'urn:xmpp:whatsapp:sync',
'flt',
's16',
'u8',
]
self.secondaryDictionary = [
'adpcm',
'amrnb',
'amrwb',
'mp3',
'pcm',
'qcelp',
'wma',
'h263',
'h264',
'jpeg',
'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',
'clear',
'conflict',
'conn_no_nna',
'cost',
'currency',
'duration',
'extend',
'fps',
'g_notify',
'g_sound',
'gone',
'google_play',
'hash',
'height',
'invalid',
'jid-malformed',
'latitude',
'lc',
'lg',
'live',
'location',
'log',
'longitude',
'max_groups',
'max_participants',
'max_subject',
'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',
'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',
'max_list_recipients',
'en-AU',
'en-GB',
'es-MX',
'pt-PT',
'zh-Hans',
'zh-Hant',
'relayelection',
'relaylatency',
'interruption',
'Bell.caf',
'Boing.caf',
'Glass.caf',
'Harp.caf',
'TimePassing.caf',
'Tri-tone.caf',
'Xylophone.caf',
'aurora.m4r',
'bamboo.m4r',
'chord.m4r',
'circles.m4r',
'complete.m4r',
'hello.m4r',
'input.m4r',
'keys.m4r',
'note.m4r',
'popcorn.m4r',
'pulse.m4r',
'synth.m4r',
'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',
'eligible',
'planned',
'current',
'future',
'disable',
'expire',
'start',
'stop',
'accuracy',
'speed',
'bearing',
'recording',
'key',
'identity',
'w:gp2',
'admin',
'locked',
'unlocked',
'new',
'battery',
'archive',
'adm',
'plaintext_size',
'plaintext_disabled',
'plaintext_reenable_threshold',
'compressed_size',
'delivered',
'everyone',
'transport',
'mspes',
'e2e_groups',
'e2e_images',
'encr_media',
'encrypt_v2',
'encrypt_image',
'encrypt_sends_push',
'force_long_connect',
'audio_opus',
'video_max_edge',
'call-id',
'call',
'preaccept',
'accept',
'offer',
'reject',
'busy',
'te',
'terminate',
'begin',
'end',
'opus',
'rtt',
'token',
'priority',
'p2p',
'rate',
'amr',
'ptt',
'srtp',
'os',
'browser',
'encrypt_group_gen2',
"encrypt_audio",
"encrypt_blist",
"encrypt_contact",
"encrypt_location",
"encrypt_url",
"encrypt_video",
"doc_types",
"upload_oom_hprof_enabled",
"tos",
"client",
"e2e_audio",
"e2e_blists",
"e2e_video",
"document",
"contact",
"file_max_size",
"small_call_btn",
"enable_mp4_operations_mux",
"android_vacuuming_enabled",
"android_vacuum_experiment_enabled",
"aec",
"agc",
"options",
"encode",
"bwe",
"rc",
"ns",
"ec_threshold",
"ec_off_threshold",
"algorithm",
"targetlevel",
"compressiongain",
"limiterenable",
"cbr",
"complexity",
"minfpp",
"maxrtt",
"low_data_usage_bitrate",
"usync",
"refresh",
"media_max_autodownload"
]
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-3.2.3/yowsup/layers/interface/ 0000775 0000000 0000000 00000000000 13464333726 0017705 5 ustar 00root root 0000000 0000000 yowsup-3.2.3/yowsup/layers/interface/__init__.py 0000664 0000000 0000000 00000000100 13464333726 0022005 0 ustar 00root root 0000000 0000000 from .interface import YowInterfaceLayer, ProtocolEntityCallback yowsup-3.2.3/yowsup/layers/interface/interface.py 0000664 0000000 0000000 00000014453 13464333726 0022226 0 ustar 00root root 0000000 0000000 from yowsup.layers import YowLayer, YowLayerEvent
from yowsup.layers.protocol_iq.protocolentities import IqProtocolEntity
from yowsup.layers.auth import YowAuthenticationProtocolLayer
from yowsup.layers.protocol_media.protocolentities.iq_requestupload import RequestUploadIqProtocolEntity
from yowsup.layers.protocol_media.mediauploader import MediaUploader
from yowsup.layers.network.layer import YowNetworkLayer
from yowsup.layers.auth.protocolentities import StreamErrorProtocolEntity
from yowsup.layers import EventCallback
import inspect
import logging
logger = logging.getLogger(__name__)
class ProtocolEntityCallback(object):
def __init__(self, entityType):
self.entityType = entityType
def __call__(self, fn):
fn.entity_callback = self.entityType
return fn
class YowInterfaceLayer(YowLayer):
PROP_RECONNECT_ON_STREAM_ERR = "org.openwhatsapp.yowsup.prop.interface.reconnect_on_stream_error"
def __init__(self):
super(YowInterfaceLayer, self).__init__()
self.reconnect = False
self.entity_callbacks = {}
self.iqRegistry = {}
# self.receiptsRegistry = {}
members = inspect.getmembers(self, predicate=inspect.ismethod)
for m in members:
if hasattr(m[1], "entity_callback"):
fname = m[0]
fn = m[1]
self.entity_callbacks[fn.entity_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 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.entity_callbacks:
self.entity_callbacks[entityType](entity)
else:
self.toUpper(entity)
@ProtocolEntityCallback("stream:error")
def onStreamError(self, streamErrorEntity):
logger.error(streamErrorEntity)
if self.getProp(self.__class__.PROP_RECONNECT_ON_STREAM_ERR, True):
if streamErrorEntity.getErrorType() == StreamErrorProtocolEntity.TYPE_CONFLICT:
logger.warn("Not reconnecting because you signed in in another location")
else:
logger.info("Initiating reconnect")
self.reconnect = True
else:
logger.warn("Not reconnecting because property %s is not set" %
self.__class__.PROP_RECONNECT_ON_STREAM_ERR)
self.toUpper(streamErrorEntity)
self.disconnect()
@EventCallback(YowNetworkLayer.EVENT_STATE_CONNECTED)
def onConnected(self, yowLayerEvent):
self.reconnect = False
@EventCallback(YowNetworkLayer.EVENT_STATE_DISCONNECTED)
def onDisconnected(self, yowLayerEvent):
if self.reconnect:
self.reconnect = False
self.connect()
def _sendMediaMessage(self, builder, success, error=None, progress=None):
# axolotlIface = self.getLayerInterface(YowAxolotlLayer)
# if axolotlIface:
# axolotlIface.encryptMedia(builder)
iq = RequestUploadIqProtocolEntity(
builder.mediaType, filePath=builder.getFilepath(), encrypted=builder.isEncrypted())
def successFn(resultEntity, requestUploadEntity): return self.__onRequestUploadSuccess(
resultEntity, requestUploadEntity, builder, success, error, progress)
def errorFn(errorEntity, requestUploadEntity): return self.__onRequestUploadError(
errorEntity, requestUploadEntity, error)
self._sendIq(iq, successFn, errorFn)
def __onRequestUploadSuccess(self, resultRequestUploadIqProtocolEntity, requestUploadEntity, builder, success, error=None, progress=None):
if(resultRequestUploadIqProtocolEntity.isDuplicate()):
return success(builder.build(resultRequestUploadIqProtocolEntity.getUrl(), resultRequestUploadIqProtocolEntity.getIp()))
else:
def successFn(path, jid, url): return self.__onMediaUploadSuccess(
builder, url, resultRequestUploadIqProtocolEntity.getIp(), success)
def errorFn(path, jid, errorText): return self.__onMediaUploadError(
builder, errorText, error)
mediaUploader = MediaUploader(builder.jid, self.getOwnJid(), builder.getFilepath(),
resultRequestUploadIqProtocolEntity.getUrl(),
resultRequestUploadIqProtocolEntity.getResumeOffset(),
successFn, errorFn, progress, asynchronous=True)
mediaUploader.start()
def __onRequestUploadError(self, errorEntity, requestUploadEntity, builder, error=None):
if error:
return error(errorEntity.code, errorEntity.text, errorEntity.backoff)
def __onMediaUploadSuccess(self, builder, url, ip, successClbk):
messageNode = builder.build(url, ip)
return successClbk(messageNode)
def __onMediaUploadError(self, builder, errorText, errorClbk=None):
if errorClbk:
return errorClbk(0, errorText, 0)
def __str__(self):
return "Interface Layer"
yowsup-3.2.3/yowsup/layers/logger/ 0000775 0000000 0000000 00000000000 13464333726 0017224 5 ustar 00root root 0000000 0000000 yowsup-3.2.3/yowsup/layers/logger/__init__.py 0000664 0000000 0000000 00000000042 13464333726 0021331 0 ustar 00root root 0000000 0000000 from .layer import YowLoggerLayer
yowsup-3.2.3/yowsup/layers/logger/layer.py 0000664 0000000 0000000 00000000753 13464333726 0020717 0 ustar 00root root 0000000 0000000 from 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-3.2.3/yowsup/layers/network/ 0000775 0000000 0000000 00000000000 13464333726 0017436 5 ustar 00root root 0000000 0000000 yowsup-3.2.3/yowsup/layers/network/__init__.py 0000664 0000000 0000000 00000000043 13464333726 0021544 0 ustar 00root root 0000000 0000000 from .layer import YowNetworkLayer
yowsup-3.2.3/yowsup/layers/network/dispatcher/ 0000775 0000000 0000000 00000000000 13464333726 0021564 5 ustar 00root root 0000000 0000000 yowsup-3.2.3/yowsup/layers/network/dispatcher/__init__.py 0000664 0000000 0000000 00000000000 13464333726 0023663 0 ustar 00root root 0000000 0000000 yowsup-3.2.3/yowsup/layers/network/dispatcher/dispatcher.py 0000664 0000000 0000000 00000001124 13464333726 0024262 0 ustar 00root root 0000000 0000000 class ConnectionCallbacks(object):
def onConnected(self):
pass
def onDisconnected(self):
pass
def onRecvData(self, data):
pass
def onConnecting(self):
pass
def onConnectionError(self, error):
pass
class YowConnectionDispatcher(object):
def __init__(self, connectionCallbacks):
assert isinstance(connectionCallbacks, ConnectionCallbacks)
self.connectionCallbacks = connectionCallbacks
def connect(self, host):
pass
def disconnect(self):
pass
def sendData(self, data):
pass yowsup-3.2.3/yowsup/layers/network/dispatcher/dispatcher_asyncore.py 0000664 0000000 0000000 00000003211 13464333726 0026164 0 ustar 00root root 0000000 0000000 from yowsup.layers.network.dispatcher.dispatcher import YowConnectionDispatcher
import asyncore
import logging
import socket
import traceback
logger = logging.getLogger(__name__)
class AsyncoreConnectionDispatcher(YowConnectionDispatcher, asyncore.dispatcher_with_send):
def __init__(self, connectionCallbacks):
super(AsyncoreConnectionDispatcher, self).__init__(connectionCallbacks)
asyncore.dispatcher_with_send.__init__(self)
self._connected = False
def sendData(self, data):
if self._connected:
self.out_buffer = self.out_buffer + data
self.initiate_send()
else:
logger.warn("Attempted to send %d bytes while still not connected" % len(data))
def connect(self, host):
logger.debug("connect(%s)" % str(host))
self.connectionCallbacks.onConnecting()
self.create_socket(socket.AF_INET, socket.SOCK_STREAM)
asyncore.dispatcher_with_send.connect(self, host)
asyncore.loop(timeout=1)
def handle_connect(self):
logger.debug("handle_connect")
if not self._connected:
self._connected = True
self.connectionCallbacks.onConnected()
def handle_close(self):
logger.debug("handle_close")
self.close()
self._connected = False
self.connectionCallbacks.onDisconnected()
def handle_error(self):
logger.error(traceback.format_exc())
self.handle_close()
def handle_read(self):
data = self.recv(1024)
self.connectionCallbacks.onRecvData(data)
def disconnect(self):
logger.debug("disconnect")
self.handle_close()
yowsup-3.2.3/yowsup/layers/network/dispatcher/dispatcher_socket.py 0000664 0000000 0000000 00000003347 13464333726 0025643 0 ustar 00root root 0000000 0000000 from yowsup.layers.network.dispatcher.dispatcher import YowConnectionDispatcher
import socket
import logging
logger = logging.getLogger(__name__)
class SocketConnectionDispatcher(YowConnectionDispatcher):
def __init__(self, connectionCallbacks):
super(SocketConnectionDispatcher, self).__init__(connectionCallbacks)
self.socket = None
def connect(self, host):
if not self.socket:
self.socket = socket.socket()
self.connectAndLoop(host)
else:
logger.error("Already connected?")
def disconnect(self):
if self.socket:
try:
self.socket.shutdown(socket.SHUT_WR)
self.socket.close()
except socket.error as e:
logger.error(e)
self.socket = None
self.connectionCallbacks.onDisconnected()
else:
logger.error("Not connected?")
def connectAndLoop(self, host):
socket = self.socket
self.connectionCallbacks.onConnecting()
try:
socket.connect(host)
self.connectionCallbacks.onConnected()
while True:
data = socket.recv(1024)
if len(data):
self.connectionCallbacks.onRecvData(data)
else:
break
self.connectionCallbacks.onDisconnected()
except Exception as e:
logger.error(e)
self.connectionCallbacks.onConnectionError(e)
finally:
self.socket = None
socket.close()
def sendData(self, data):
try:
self.socket.send(data)
except socket.error as e:
logger.error(e)
self.disconnect()
yowsup-3.2.3/yowsup/layers/network/layer.py 0000664 0000000 0000000 00000010235 13464333726 0021125 0 ustar 00root root 0000000 0000000 from yowsup.layers import YowLayer, YowLayerEvent, EventCallback
from yowsup.layers.network.layer_interface import YowNetworkLayerInterface
from yowsup.layers.network.dispatcher.dispatcher import ConnectionCallbacks
from yowsup.layers.network.dispatcher.dispatcher import YowConnectionDispatcher
from yowsup.layers.network.dispatcher.dispatcher_socket import SocketConnectionDispatcher
from yowsup.layers.network.dispatcher.dispatcher_asyncore import AsyncoreConnectionDispatcher
import logging
logger = logging.getLogger(__name__)
class YowNetworkLayer(YowLayer, ConnectionCallbacks):
"""This layer wraps a connection dispatcher that provides connection and a communication channel
to remote endpoints. Unless explicitly configured, applications should not make assumption about
the dispatcher being used as the default dispatcher could be changed across versions"""
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"
PROP_DISPATCHER = "org.openwhatsapp.yowsup.prop.net.dispatcher"
STATE_DISCONNECTED = 0
STATE_CONNECTING = 1
STATE_CONNECTED = 2
STATE_DISCONNECTING = 3
DISPATCHER_SOCKET = 0
DISPATCHER_ASYNCORE = 1
DISPATCHER_DEFAULT = DISPATCHER_ASYNCORE
def __init__(self):
self.state = self.__class__.STATE_DISCONNECTED
YowLayer.__init__(self)
ConnectionCallbacks.__init__(self)
self.interface = YowNetworkLayerInterface(self)
self.connected = False
self._dispatcher = None # type: YowConnectionDispatcher
def __create_dispatcher(self, dispatcher_type):
if dispatcher_type == self.DISPATCHER_ASYNCORE:
logger.debug("Created asyncore dispatcher")
return AsyncoreConnectionDispatcher(self)
else:
logger.debug("Created socket dispatcher")
return SocketConnectionDispatcher(self)
def onConnected(self):
logger.debug("Connected")
self.state = self.__class__.STATE_CONNECTED
self.connected = True
self.emitEvent(YowLayerEvent(YowNetworkLayer.EVENT_STATE_CONNECTED))
def onDisconnected(self):
if self.state != self.__class__.STATE_DISCONNECTED:
self.state = self.__class__.STATE_DISCONNECTED
self.connected = False
logger.debug("Disconnected")
self.emitEvent(YowLayerEvent(self.__class__.EVENT_STATE_DISCONNECTED, reason="", detached=True))
def onConnecting(self):
pass
def onConnectionError(self, error):
self.onDisconnected()
@EventCallback(EVENT_STATE_CONNECT)
def onConnectLayerEvent(self, ev):
if not self.connected:
self.createConnection()
else:
logger.warn("Received connect event while already connected")
return True
@EventCallback(EVENT_STATE_DISCONNECT)
def onDisconnectLayerEvent(self, ev):
self.destroyConnection(ev.getArg("reason"))
return True
def createConnection(self):
self._dispatcher = self.__create_dispatcher(self.getProp(self.PROP_DISPATCHER, self.DISPATCHER_DEFAULT))
self.state = self.__class__.STATE_CONNECTING
endpoint = self.getProp(self.__class__.PROP_ENDPOINT)
logger.info("Connecting to %s:%s" % endpoint)
self._dispatcher.connect(endpoint)
def destroyConnection(self, reason = None):
self.state = self.__class__.STATE_DISCONNECTING
self._dispatcher.disconnect()
def getStatus(self):
return self.connected
def send(self, data):
if self.connected:
self._dispatcher.sendData(data)
def onRecvData(self, data):
self.receive(data)
def receive(self, data):
self.toUpper(data)
def __str__(self):
return "Network Layer"
yowsup-3.2.3/yowsup/layers/network/layer_interface.py 0000664 0000000 0000000 00000000440 13464333726 0023142 0 ustar 00root root 0000000 0000000 from 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-3.2.3/yowsup/layers/noise/ 0000775 0000000 0000000 00000000000 13464333726 0017062 5 ustar 00root root 0000000 0000000 yowsup-3.2.3/yowsup/layers/noise/__init__.py 0000664 0000000 0000000 00000000000 13464333726 0021161 0 ustar 00root root 0000000 0000000 yowsup-3.2.3/yowsup/layers/noise/layer.py 0000664 0000000 0000000 00000013433 13464333726 0020554 0 ustar 00root root 0000000 0000000 from yowsup.layers.noise.workers.handshake import WANoiseProtocolHandshakeWorker
from yowsup.layers import YowLayer, EventCallback
from yowsup.layers.auth.layer_authentication import YowAuthenticationProtocolLayer
from yowsup.layers.network.layer import YowNetworkLayer
from yowsup.layers.noise.layer_noise_segments import YowNoiseSegmentsLayer
from yowsup.config.manager import ConfigManager
from yowsup.env.env import YowsupEnv
from consonance.protocol import WANoiseProtocol
from consonance.config.client import ClientConfig
from consonance.config.useragent import UserAgentConfig
from consonance.streams.segmented.blockingqueue import BlockingQueueSegmentedStream
from consonance.structs.keypair import KeyPair
import threading
import logging
logger = logging.getLogger(__name__)
try:
import Queue
except ImportError:
import queue as Queue
class YowNoiseLayer(YowLayer):
DEFAULT_PUSHNAME = "yowsup"
HEADER = b'WA\x02\x01'
EDGE_HEADER = b'ED\x00\x01'
def __init__(self):
super(YowNoiseLayer, self).__init__()
self._wa_noiseprotocol = WANoiseProtocol(
2, 1, protocol_state_callbacks=self._on_protocol_state_changed
) # type: WANoiseProtocol
self._handshake_worker = None
self._stream = BlockingQueueSegmentedStream() # type: BlockingQueueSegmentedStream
self._read_buffer = bytearray()
self._flush_lock = threading.Lock()
self._incoming_segments_queue = Queue.Queue()
self._config_manager = ConfigManager()
self._username = None
self._rs = None
def __str__(self):
return "Noise Layer"
@EventCallback(YowNetworkLayer.EVENT_STATE_DISCONNECTED)
def on_disconnected(self, event):
self._wa_noiseprotocol.reset()
@EventCallback(YowAuthenticationProtocolLayer.EVENT_AUTH)
def on_auth(self, event):
logger.debug("Received auth event")
credentials = event.getArg("credentials")
self._username, local_static = int(credentials[0]), credentials[1]
config = self._config_manager.load(self._username) # type: yowsup.config.v1.config.Config
# event's keypair will override config's keypair
local_static = local_static or config.client_static_keypair
if type(local_static) is bytes:
local_static = KeyPair.from_bytes(local_static)
assert type(local_static) is KeyPair
passive = event.getArg('passive')
self.setProp(YowNoiseSegmentsLayer.PROP_ENABLED, False)
if config.edge_routing_info:
self.toLower(self.EDGE_HEADER)
self.setProp(YowNoiseSegmentsLayer.PROP_ENABLED, True)
self.toLower(config.edge_routing_info)
self.setProp(YowNoiseSegmentsLayer.PROP_ENABLED, False)
self.toLower(self.HEADER)
self.setProp(YowNoiseSegmentsLayer.PROP_ENABLED, True)
remote_static = config.server_static_public
self._rs = remote_static
yowsupenv = YowsupEnv.getCurrent()
client_config = ClientConfig(
username=self._username,
passive=passive,
useragent=UserAgentConfig(
platform=0,
app_version=yowsupenv.getVersion(),
mcc=config.mcc or "000",
mnc=config.mnc or "000",
os_version=yowsupenv.getOSVersion(),
manufacturer=yowsupenv.getManufacturer(),
device=yowsupenv.getDeviceName(),
os_build_number=yowsupenv.getOSVersion(),
phone_id=config.fdid or "",
locale_lang="en",
locale_country="US"
),
pushname=config.pushname or self.DEFAULT_PUSHNAME,
short_connect=True
)
if not self._in_handshake():
logger.debug("Performing handshake [username= %d, passive=%s]" % (self._username, passive) )
self._handshake_worker = WANoiseProtocolHandshakeWorker(
self._wa_noiseprotocol, self._stream, client_config, local_static, remote_static,
)
logger.debug("Starting handshake worker")
self._stream.set_events_callback(self._handle_stream_event)
self._handshake_worker.start()
def _in_handshake(self):
"""
:return:
:rtype: bool
"""
return self._wa_noiseprotocol.state == WANoiseProtocol.STATE_HANDSHAKE
def _on_protocol_state_changed(self, state):
if state == WANoiseProtocol.STATE_TRANSPORT:
if self._rs != self._wa_noiseprotocol.rs:
config = self._config_manager.load(self._username)
config.server_static_public = self._wa_noiseprotocol.rs
self._config_manager.save(config)
self._rs = self._wa_noiseprotocol.rs
self._flush_incoming_buffer()
def _handle_stream_event(self, event):
if event == BlockingQueueSegmentedStream.EVENT_WRITE:
self.toLower(self._stream.get_write_segment())
elif event == BlockingQueueSegmentedStream.EVENT_READ:
self._stream.put_read_segment(self._incoming_segments_queue.get(block=True))
def send(self, data):
"""
:param data:
:type data: bytearray | bytes
:return:
:rtype:
"""
data = bytes(data) if type(data) is not bytes else data
self._wa_noiseprotocol.send(data)
def _flush_incoming_buffer(self):
self._flush_lock.acquire()
while self._incoming_segments_queue.qsize():
self.toUpper(self._wa_noiseprotocol.receive())
self._flush_lock.release()
def receive(self, data):
"""
:param data:
:type data: bytes
:return:
:rtype:
"""
self._incoming_segments_queue.put(data)
if not self._in_handshake():
self._flush_incoming_buffer()
yowsup-3.2.3/yowsup/layers/noise/layer_noise_segments.py 0000664 0000000 0000000 00000002402 13464333726 0023650 0 ustar 00root root 0000000 0000000 from yowsup.layers import YowLayer
import logging
import struct
logger = logging.getLogger(__name__)
class YowNoiseSegmentsLayer(YowLayer):
PROP_ENABLED = "org.openwhatsapp.yowsup.prop.noise.segmented_enabled"
def __init__(self):
super(YowNoiseSegmentsLayer, self).__init__()
self._read_buffer = bytearray()
def __str__(self):
return "Noise Segments Layer"
def send(self, data):
if len(data) >= 16777216:
raise ValueError("data too large to write; length=%d" % len(data))
if self.getProp(self.PROP_ENABLED, False):
self.toLower(struct.pack('>I', len(data))[1:])
self.toLower(data)
def receive(self, data):
if self.getProp(self.PROP_ENABLED, False):
self._read_buffer.extend(data)
while len(self._read_buffer) > 3:
read_size = struct.unpack('>I', b"\x00" + self._read_buffer[:3])[0] # type: int
if len(self._read_buffer) >= (3 + read_size):
data = self._read_buffer[3:read_size+3]
self._read_buffer = self._read_buffer[3 + read_size:]
self.toUpper(bytes(data))
else:
break
else:
self.toUpper(data)
yowsup-3.2.3/yowsup/layers/noise/workers/ 0000775 0000000 0000000 00000000000 13464333726 0020556 5 ustar 00root root 0000000 0000000 yowsup-3.2.3/yowsup/layers/noise/workers/__init__.py 0000664 0000000 0000000 00000000000 13464333726 0022655 0 ustar 00root root 0000000 0000000 yowsup-3.2.3/yowsup/layers/noise/workers/handshake.py 0000664 0000000 0000000 00000002543 13464333726 0023062 0 ustar 00root root 0000000 0000000 from consonance.protocol import WANoiseProtocol
from consonance.streams.segmented.segmented import SegmentedStream
from consonance.config.client import ClientConfig
from dissononce.dh.keypair import KeyPair
from dissononce.dh.x25519.x25519 import PublicKey
import threading
class WANoiseProtocolHandshakeWorker(threading.Thread):
def __init__(self, wanoiseprotocol, stream, client_config, s, rs=None, finish_callback=None):
"""
:param wanoiseprotocol:
:type wanoiseprotocol: WANoiseProtocol
:param stream:
:type stream: SegmentedStream
:param client_config:
:type client_config: ClientConfig
:param s:
:type s: KeyPair
:param rs:
:type rs: PublicKey | None
"""
super(WANoiseProtocolHandshakeWorker, self).__init__()
self.daemon = True
self._protocol = wanoiseprotocol # type: WANoiseProtocol
self._stream = stream # type: SegmentedStream
self._client_config = client_config # type: ClientConfig
self._s = s # type: KeyPair
self._rs = rs # type: PublicKey
self._finish_callback = finish_callback
def run(self):
self._protocol.reset()
self._protocol.start(self._stream, self._client_config, self._s, self._rs)
if self._finish_callback is not None:
self._finish_callback()
yowsup-3.2.3/yowsup/layers/protocol_acks/ 0000775 0000000 0000000 00000000000 13464333726 0020607 5 ustar 00root root 0000000 0000000 yowsup-3.2.3/yowsup/layers/protocol_acks/__init__.py 0000664 0000000 0000000 00000000047 13464333726 0022721 0 ustar 00root root 0000000 0000000 from .layer import YowAckProtocolLayer
yowsup-3.2.3/yowsup/layers/protocol_acks/layer.py 0000664 0000000 0000000 00000001021 13464333726 0022267 0 ustar 00root root 0000000 0000000 from 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-3.2.3/yowsup/layers/protocol_acks/protocolentities/ 0000775 0000000 0000000 00000000000 13464333726 0024215 5 ustar 00root root 0000000 0000000 yowsup-3.2.3/yowsup/layers/protocol_acks/protocolentities/__init__.py 0000664 0000000 0000000 00000000212 13464333726 0026321 0 ustar 00root root 0000000 0000000 from .ack import AckProtocolEntity
from .ack_incoming import IncomingAckProtocolEntity
from .ack_outgoing import OutgoingAckProtocolEntity yowsup-3.2.3/yowsup/layers/protocol_acks/protocolentities/ack.py 0000664 0000000 0000000 00000001743 13464333726 0025332 0 ustar 00root root 0000000 0000000 from 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-3.2.3/yowsup/layers/protocol_acks/protocolentities/ack_incoming.py 0000664 0000000 0000000 00000002430 13464333726 0027207 0 ustar 00root root 0000000 0000000 from 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-3.2.3/yowsup/layers/protocol_acks/protocolentities/ack_outgoing.py 0000664 0000000 0000000 00000003176 13464333726 0027247 0 ustar 00root root 0000000 0000000 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-3.2.3/yowsup/layers/protocol_acks/protocolentities/test_ack_incoming.py 0000664 0000000 0000000 00000000746 13464333726 0030256 0 ustar 00root root 0000000 0000000 from 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-3.2.3/yowsup/layers/protocol_acks/protocolentities/test_ack_outgoing.py 0000664 0000000 0000000 00000000705 13464333726 0030301 0 ustar 00root root 0000000 0000000 from 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-3.2.3/yowsup/layers/protocol_acks/test_layer.py 0000664 0000000 0000000 00000001124 13464333726 0023332 0 ustar 00root root 0000000 0000000 from 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-3.2.3/yowsup/layers/protocol_calls/ 0000775 0000000 0000000 00000000000 13464333726 0020764 5 ustar 00root root 0000000 0000000 yowsup-3.2.3/yowsup/layers/protocol_calls/__init__.py 0000664 0000000 0000000 00000000051 13464333726 0023071 0 ustar 00root root 0000000 0000000 from .layer import YowCallsProtocolLayer
yowsup-3.2.3/yowsup/layers/protocol_calls/layer.py 0000664 0000000 0000000 00000002137 13464333726 0022455 0 ustar 00root root 0000000 0000000 from 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-3.2.3/yowsup/layers/protocol_calls/protocolentities/ 0000775 0000000 0000000 00000000000 13464333726 0024372 5 ustar 00root root 0000000 0000000 yowsup-3.2.3/yowsup/layers/protocol_calls/protocolentities/__init__.py 0000664 0000000 0000000 00000000066 13464333726 0026505 0 ustar 00root root 0000000 0000000 from .call import CallProtocolEntity
yowsup-3.2.3/yowsup/layers/protocol_calls/protocolentities/call.py 0000664 0000000 0000000 00000007365 13464333726 0025672 0 ustar 00root root 0000000 0000000 from 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-3.2.3/yowsup/layers/protocol_calls/protocolentities/test_call.py 0000664 0000000 0000000 00000001226 13464333726 0026717 0 ustar 00root root 0000000 0000000 from 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-3.2.3/yowsup/layers/protocol_chatstate/ 0000775 0000000 0000000 00000000000 13464333726 0021646 5 ustar 00root root 0000000 0000000 yowsup-3.2.3/yowsup/layers/protocol_chatstate/__init__.py 0000664 0000000 0000000 00000000055 13464333726 0023757 0 ustar 00root root 0000000 0000000 from .layer import YowChatstateProtocolLayer
yowsup-3.2.3/yowsup/layers/protocol_chatstate/layer.py 0000664 0000000 0000000 00000001140 13464333726 0023330 0 ustar 00root root 0000000 0000000 from 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-3.2.3/yowsup/layers/protocol_chatstate/protocolentities/ 0000775 0000000 0000000 00000000000 13464333726 0025254 5 ustar 00root root 0000000 0000000 yowsup-3.2.3/yowsup/layers/protocol_chatstate/protocolentities/__init__.py 0000664 0000000 0000000 00000000257 13464333726 0027371 0 ustar 00root root 0000000 0000000 from .chatstate import ChatstateProtocolEntity
from .chatstate_incoming import IncomingChatstateProtocolEntity
from .chatstate_outgoing import OutgoingChatstateProtocolEntity
yowsup-3.2.3/yowsup/layers/protocol_chatstate/protocolentities/chatstate.py 0000664 0000000 0000000 00000002322 13464333726 0027605 0 ustar 00root root 0000000 0000000 from yowsup.structs import ProtocolEntity, ProtocolTreeNode
class ChatstateProtocolEntity(ProtocolEntity):
'''
INCOMING
<{{composing|paused}}>{{composing|paused}}>
OUTGOING
<{{composing|paused}}>{{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-3.2.3/yowsup/layers/protocol_chatstate/protocolentities/chatstate_incoming.py 0000664 0000000 0000000 00000002316 13464333726 0031473 0 ustar 00root root 0000000 0000000 from .chatstate import ChatstateProtocolEntity
class IncomingChatstateProtocolEntity(ChatstateProtocolEntity):
'''
INCOMING
<{{composing|paused}}>{{composing|paused}}>
OUTGOING
<{{composing|paused}}>{{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-3.2.3/yowsup/layers/protocol_chatstate/protocolentities/chatstate_outgoing.py 0000664 0000000 0000000 00000002272 13464333726 0031524 0 ustar 00root root 0000000 0000000 from .chatstate import ChatstateProtocolEntity
class OutgoingChatstateProtocolEntity(ChatstateProtocolEntity):
'''
INCOMING
<{{composing|paused}}>{{composing|paused}}>
OUTGOING
<{{composing|paused}}>{{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-3.2.3/yowsup/layers/protocol_chatstate/protocolentities/test_chatstate_incoming.py 0000664 0000000 0000000 00000001002 13464333726 0032521 0 ustar 00root root 0000000 0000000 from 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-3.2.3/yowsup/layers/protocol_chatstate/protocolentities/test_chatstate_outgoing.py 0000664 0000000 0000000 00000001002 13464333726 0032551 0 ustar 00root root 0000000 0000000 from 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-3.2.3/yowsup/layers/protocol_chatstate/test_layer.py 0000664 0000000 0000000 00000001366 13464333726 0024401 0 ustar 00root root 0000000 0000000 from 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-3.2.3/yowsup/layers/protocol_contacts/ 0000775 0000000 0000000 00000000000 13464333726 0021504 5 ustar 00root root 0000000 0000000 yowsup-3.2.3/yowsup/layers/protocol_contacts/__init__.py 0000664 0000000 0000000 00000000055 13464333726 0023615 0 ustar 00root root 0000000 0000000 from .layer import YowContactsIqProtocolLayer yowsup-3.2.3/yowsup/layers/protocol_contacts/layer.py 0000664 0000000 0000000 00000003320 13464333726 0023170 0 ustar 00root root 0000000 0000000 from 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-3.2.3/yowsup/layers/protocol_contacts/protocolentities/ 0000775 0000000 0000000 00000000000 13464333726 0025112 5 ustar 00root root 0000000 0000000 yowsup-3.2.3/yowsup/layers/protocol_contacts/protocolentities/__init__.py 0000664 0000000 0000000 00000001107 13464333726 0027222 0 ustar 00root root 0000000 0000000 from .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-3.2.3/yowsup/layers/protocol_contacts/protocolentities/iq_statuses_get.py 0000664 0000000 0000000 00000003167 13464333726 0030676 0 ustar 00root root 0000000 0000000 from yowsup.common import YowConstants
from 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 = YowConstants.WHATSAPP_SERVER)
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-3.2.3/yowsup/layers/protocol_contacts/protocolentities/iq_statuses_result.py 0000664 0000000 0000000 00000003771 13464333726 0031436 0 ustar 00root root 0000000 0000000 from 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)
self.setResultStatusesProps(statuses)
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.items())
return out
def toProtocolTreeNode(self):
node = super(ResultStatusesIqProtocolEntity, self).toProtocolTreeNode()
users = [ProtocolTreeNode('user', {'jid': jid, 't': t}, None, status) for jid, (status, t) in self.statuses.items()]
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-3.2.3/yowsup/layers/protocol_contacts/protocolentities/iq_sync.py 0000664 0000000 0000000 00000003557 13464333726 0027143 0 ustar 00root root 0000000 0000000 from 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-3.2.3/yowsup/layers/protocol_contacts/protocolentities/iq_sync_get.py 0000664 0000000 0000000 00000005274 13464333726 0030000 0 ustar 00root root 0000000 0000000 from 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-3.2.3/yowsup/layers/protocol_contacts/protocolentities/iq_sync_result.py 0000664 0000000 0000000 00000007632 13464333726 0030537 0 ustar 00root root 0000000 0000000 from 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-3.2.3/yowsup/layers/protocol_contacts/protocolentities/notification_contact.py 0000664 0000000 0000000 00000001454 13464333726 0031671 0 ustar 00root root 0000000 0000000 from 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 entity yowsup-3.2.3/yowsup/layers/protocol_contacts/protocolentities/notification_contact_add.py 0000664 0000000 0000000 00000002367 13464333726 0032505 0 ustar 00root root 0000000 0000000 from 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 entity yowsup-3.2.3/yowsup/layers/protocol_contacts/protocolentities/notification_contact_remove.py 0000664 0000000 0000000 00000002417 13464333726 0033246 0 ustar 00root root 0000000 0000000 from 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 entity yowsup-3.2.3/yowsup/layers/protocol_contacts/protocolentities/notification_contact_update.py 0000664 0000000 0000000 00000002417 13464333726 0033233 0 ustar 00root root 0000000 0000000 from 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 entity yowsup-3.2.3/yowsup/layers/protocol_contacts/protocolentities/notificiation_contacts_sync.py 0000664 0000000 0000000 00000002325 13464333726 0033257 0 ustar 00root root 0000000 0000000 from 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 entity yowsup-3.2.3/yowsup/layers/protocol_contacts/protocolentities/test_iq_sync_get.py 0000664 0000000 0000000 00000000661 13464333726 0031032 0 ustar 00root root 0000000 0000000 from 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-3.2.3/yowsup/layers/protocol_contacts/protocolentities/test_iq_sync_result.py 0000664 0000000 0000000 00000001370 13464333726 0031567 0 ustar 00root root 0000000 0000000 from 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-3.2.3/yowsup/layers/protocol_contacts/protocolentities/test_notification_contact_add.py 0000664 0000000 0000000 00000001240 13464333726 0033531 0 ustar 00root root 0000000 0000000 from 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-3.2.3/yowsup/layers/protocol_contacts/protocolentities/test_notification_contact_remove.py 0000664 0000000 0000000 00000001145 13464333726 0034302 0 ustar 00root root 0000000 0000000 from 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-3.2.3/yowsup/layers/protocol_contacts/protocolentities/test_notification_contact_update.py 0000664 0000000 0000000 00000001144 13464333726 0034266 0 ustar 00root root 0000000 0000000 from 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-3.2.3/yowsup/layers/protocol_contacts/test_layer.py 0000664 0000000 0000000 00000002300 13464333726 0024224 0 ustar 00root root 0000000 0000000 from 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-3.2.3/yowsup/layers/protocol_groups/ 0000775 0000000 0000000 00000000000 13464333726 0021205 5 ustar 00root root 0000000 0000000 yowsup-3.2.3/yowsup/layers/protocol_groups/__init__.py 0000664 0000000 0000000 00000000052 13464333726 0023313 0 ustar 00root root 0000000 0000000 from .layer import YowGroupsProtocolLayer
yowsup-3.2.3/yowsup/layers/protocol_groups/layer.py 0000664 0000000 0000000 00000015161 13464333726 0022677 0 ustar 00root root 0000000 0000000 from yowsup.layers import YowLayer, YowLayerEvent, YowProtocolLayer
from yowsup.layers.protocol_iq.protocolentities import ErrorIqProtocolEntity
from yowsup.layers.protocol_iq.protocolentities.iq_result import ResultIqProtocolEntity
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")
self.toUpper(ErrorIqProtocolEntity.fromProtocolTreeNode(node))
def onSetSubjectSuccess(self, node, originalIqEntity):
logger.info("Group subject change success")
self.toUpper(ResultIqProtocolEntity.fromProtocolTreeNode(node))
def onSetSubjectFailed(self, node, originalIqEntity):
logger.error("Group subject change failed")
self.toUpper(ErrorIqProtocolEntity.fromProtocolTreeNode(node))
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")
self.toUpper(ErrorIqProtocolEntity.fromProtocolTreeNode(node))
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")
self.toUpper(ErrorIqProtocolEntity.fromProtocolTreeNode(node))
def onPromoteParticipantsSuccess(self, node, originalIqEntity):
logger.info("Group promote participants success")
self.toUpper(ResultIqProtocolEntity.fromProtocolTreeNode(node))
def onDemoteParticipantsFailed(self, node, originalIqEntity):
logger.error("Group demote participants failed")
self.toUpper(ErrorIqProtocolEntity.fromProtocolTreeNode(node))
def onDemoteParticipantsSuccess(self, node, originalIqEntity):
logger.info("Group demote participants success")
self.toUpper(ResultIqProtocolEntity.fromProtocolTreeNode(node))
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")
self.toUpper(ErrorIqProtocolEntity.fromProtocolTreeNode(node))
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")
self.toUpper(ErrorIqProtocolEntity.fromProtocolTreeNode(node))
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-3.2.3/yowsup/layers/protocol_groups/protocolentities/ 0000775 0000000 0000000 00000000000 13464333726 0024613 5 ustar 00root root 0000000 0000000 yowsup-3.2.3/yowsup/layers/protocol_groups/protocolentities/__init__.py 0000664 0000000 0000000 00000003252 13464333726 0026726 0 ustar 00root root 0000000 0000000 from .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-3.2.3/yowsup/layers/protocol_groups/protocolentities/iq_groups.py 0000664 0000000 0000000 00000000707 13464333726 0027201 0 ustar 00root root 0000000 0000000 from 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-3.2.3/yowsup/layers/protocol_groups/protocolentities/iq_groups_create.py 0000664 0000000 0000000 00000003441 13464333726 0030522 0 ustar 00root root 0000000 0000000 from yowsup.common import YowConstants
from 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 = YowConstants.WHATSAPP_GROUP_SERVER, _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-3.2.3/yowsup/layers/protocol_groups/protocolentities/iq_groups_create_success.py 0000664 0000000 0000000 00000002167 13464333726 0032256 0 ustar 00root root 0000000 0000000 from yowsup.common import YowConstants
from 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 = YowConstants.WHATSAPP_GROUP_SERVER, _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-3.2.3/yowsup/layers/protocol_groups/protocolentities/iq_groups_info.py 0000664 0000000 0000000 00000002421 13464333726 0030207 0 ustar 00root root 0000000 0000000 from 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-3.2.3/yowsup/layers/protocol_groups/protocolentities/iq_groups_leave.py 0000664 0000000 0000000 00000003317 13464333726 0030355 0 ustar 00root root 0000000 0000000 from yowsup.common import YowConstants
from yowsup.structs import ProtocolEntity, ProtocolTreeNode
from .iq_groups import GroupsIqProtocolEntity
class LeaveGroupsIqProtocolEntity(GroupsIqProtocolEntity):
'''
'''
def __init__(self, groupList):
super(LeaveGroupsIqProtocolEntity, self).__init__(to = YowConstants.WHATSAPP_GROUP_SERVER, _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-3.2.3/yowsup/layers/protocol_groups/protocolentities/iq_groups_leave_success.py 0000664 0000000 0000000 00000002723 13464333726 0032105 0 ustar 00root root 0000000 0000000 from yowsup.common import YowConstants
from 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=YowConstants.WHATSAPP_GROUP_SERVER, _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-3.2.3/yowsup/layers/protocol_groups/protocolentities/iq_groups_list.py 0000664 0000000 0000000 00000004207 13464333726 0030233 0 ustar 00root root 0000000 0000000 from yowsup.common import YowConstants
from yowsup.structs import ProtocolEntity, ProtocolTreeNode
from .iq_groups import GroupsIqProtocolEntity
class ListGroupsIqProtocolEntity(GroupsIqProtocolEntity):
'''
<"{{participating | owning}}">"{{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 = YowConstants.WHATSAPP_GROUP_SERVER, _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-3.2.3/yowsup/layers/protocol_groups/protocolentities/iq_groups_participants.py 0000664 0000000 0000000 00000003151 13464333726 0031756 0 ustar 00root root 0000000 0000000 from 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-3.2.3/yowsup/layers/protocol_groups/protocolentities/iq_groups_participants_add.py 0000664 0000000 0000000 00000002101 13464333726 0032560 0 ustar 00root root 0000000 0000000 from 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-3.2.3/yowsup/layers/protocol_groups/protocolentities/iq_groups_participants_add_failure.py 0000664 0000000 0000000 00000001516 13464333726 0034300 0 ustar 00root root 0000000 0000000 from 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 entity yowsup-3.2.3/yowsup/layers/protocol_groups/protocolentities/iq_groups_participants_add_success.py 0000664 0000000 0000000 00000003371 13464333726 0034322 0 ustar 00root root 0000000 0000000 from 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-3.2.3/yowsup/layers/protocol_groups/protocolentities/iq_groups_participants_demote.py 0000664 0000000 0000000 00000002141 13464333726 0033311 0 ustar 00root root 0000000 0000000 from 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-3.2.3/yowsup/layers/protocol_groups/protocolentities/iq_groups_participants_promote.py 0000664 0000000 0000000 00000002152 13464333726 0033523 0 ustar 00root root 0000000 0000000 from 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-3.2.3/yowsup/layers/protocol_groups/protocolentities/iq_groups_participants_remove.py 0000664 0000000 0000000 00000002150 13464333726 0033331 0 ustar 00root root 0000000 0000000 from 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
yowsup-3.2.3/yowsup/layers/protocol_groups/protocolentities/iq_groups_participants_remove_success.py0000664 0000000 0000000 00000003435 13464333726 0035070 0 ustar 00root root 0000000 0000000 from 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-3.2.3/yowsup/layers/protocol_groups/protocolentities/iq_groups_subject.py 0000664 0000000 0000000 00000002064 13464333726 0030716 0 ustar 00root root 0000000 0000000 from 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-3.2.3/yowsup/layers/protocol_groups/protocolentities/iq_result_groups_info.py 0000664 0000000 0000000 00000010240 13464333726 0031603 0 ustar 00root root 0000000 0000000 from 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-3.2.3/yowsup/layers/protocol_groups/protocolentities/iq_result_groups_list.py 0000664 0000000 0000000 00000006475 13464333726 0031642 0 ustar 00root root 0000000 0000000 from yowsup.common import YowConstants
from 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 = YowConstants.WHATSAPP_GROUP_SERVER)
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 entity
yowsup-3.2.3/yowsup/layers/protocol_groups/protocolentities/iq_result_participants_list.py 0000664 0000000 0000000 00000003134 13464333726 0033011 0 ustar 00root root 0000000 0000000 from 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-3.2.3/yowsup/layers/protocol_groups/protocolentities/notification_groups.py 0000664 0000000 0000000 00000003314 13464333726 0031253 0 ustar 00root root 0000000 0000000 from 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-3.2.3/yowsup/layers/protocol_groups/protocolentities/notification_groups_add.py 0000664 0000000 0000000 00000003632 13464333726 0032066 0 ustar 00root root 0000000 0000000 from .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-3.2.3/yowsup/layers/protocol_groups/protocolentities/notification_groups_create.py 0000664 0000000 0000000 00000012502 13464333726 0032575 0 ustar 00root root 0000000 0000000 from .notification_groups import GroupsNotificationProtocolEntity
from yowsup.structs import ProtocolTreeNode
class CreateGroupsNotificationProtocolEntity(GroupsNotificationProtocolEntity):
"""
"""
TYPE_CREATE_NEW = "new"
TYPE_PARTICIPANT_ADMIN = "admin"
TYPE_PARTICIPANT_SUPERADMIN = "superadmin"
def __init__(self, _id, _from, timestamp, notify, participant, offline,
createType, key, groupId, creationTimestamp, creatorJid,
subject, subjectTime, subjectOwnerJid,
participants):
super(CreateGroupsNotificationProtocolEntity, self).__init__(_id, _from, timestamp, notify, participant, offline)
self.setGroupProps(createType, key, groupId, creationTimestamp, creatorJid,
subject, subjectTime, subjectOwnerJid, participants)
def setGroupProps(self, createType, key, 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
self._key = key
@property
def key(self):
return self._key
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 getGroupSuperAdmin(self, full = True):
for jid, _type in self.participants.items():
if _type == self.__class__.TYPE_PARTICIPANT_SUPERADMIN:
return jid if full else jid.split('@')[0]
def getGroupAdmins(self, full = True):
out = []
for jid, _type in self.participants.items():
if _type == self.__class__.TYPE_PARTICIPANT_ADMIN:
out.append(jid if full else jid.split('@')[0])
return out
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()
out += "Key: %s\n" % self.key
return out
def toProtocolTreeNode(self):
node = super(CreateGroupsNotificationProtocolEntity, self).toProtocolTreeNode()
createNode = ProtocolTreeNode("create", {"type": self.getCreatetype(), "key": self.key})
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"], createNode["key"], groupNode["id"], groupNode["creation"], groupNode["creator"], groupNode["subject"],
groupNode["s_t"], groupNode["s_o"], participants
)
yowsup-3.2.3/yowsup/layers/protocol_groups/protocolentities/notification_groups_remove.py 0000664 0000000 0000000 00000004116 13464333726 0032631 0 ustar 00root root 0000000 0000000 from .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 list, "Must be a list of jids, got %s instead." % type(participants)
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.append(p["jid"])
return RemoveGroupsNotificationProtocolEntity(
node["id"], node["from"], node["t"], node["notify"], node["participant"], node["offline"],
removeNode["subject"], participants
)
yowsup-3.2.3/yowsup/layers/protocol_groups/protocolentities/notification_groups_subject.py 0000664 0000000 0000000 00000004400 13464333726 0032767 0 ustar 00root root 0000000 0000000 from 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-3.2.3/yowsup/layers/protocol_groups/protocolentities/test_iq_groups.py 0000664 0000000 0000000 00000000226 13464333726 0030234 0 ustar 00root root 0000000 0000000 from yowsup.layers.protocol_iq.protocolentities.test_iq import IqProtocolEntityTest
class GroupsIqProtocolEntityTest(IqProtocolEntityTest):
pass
yowsup-3.2.3/yowsup/layers/protocol_groups/protocolentities/test_iq_groups_create.py 0000664 0000000 0000000 00000000676 13464333726 0031570 0 ustar 00root root 0000000 0000000 from 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-3.2.3/yowsup/layers/protocol_groups/protocolentities/test_iq_groups_create_success.py 0000664 0000000 0000000 00000000716 13464333726 0033313 0 ustar 00root root 0000000 0000000 from 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-3.2.3/yowsup/layers/protocol_groups/protocolentities/test_iq_groups_list.py 0000664 0000000 0000000 00000000645 13464333726 0031274 0 ustar 00root root 0000000 0000000 from 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-3.2.3/yowsup/layers/protocol_groups/protocolentities/test_iq_result_groups.py 0000664 0000000 0000000 00000000256 13464333726 0031635 0 ustar 00root root 0000000 0000000 from yowsup.layers.protocol_iq.protocolentities.test_iq_result import ResultIqProtocolEntityTest
class GroupsResultIqProtocolEntityTest(ResultIqProtocolEntityTest):
pass yowsup-3.2.3/yowsup/layers/protocol_groups/protocolentities/test_iq_result_groups_list.py 0000664 0000000 0000000 00000001420 13464333726 0032662 0 ustar 00root root 0000000 0000000 from 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-3.2.3/yowsup/layers/protocol_groups/structs/ 0000775 0000000 0000000 00000000000 13464333726 0022714 5 ustar 00root root 0000000 0000000 yowsup-3.2.3/yowsup/layers/protocol_groups/structs/__init__.py 0000664 0000000 0000000 00000000030 13464333726 0025016 0 ustar 00root root 0000000 0000000 from .group import Group yowsup-3.2.3/yowsup/layers/protocol_groups/structs/group.py 0000664 0000000 0000000 00000002407 13464333726 0024425 0 ustar 00root root 0000000 0000000 class 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-3.2.3/yowsup/layers/protocol_ib/ 0000775 0000000 0000000 00000000000 13464333726 0020260 5 ustar 00root root 0000000 0000000 yowsup-3.2.3/yowsup/layers/protocol_ib/__init__.py 0000664 0000000 0000000 00000000047 13464333726 0022372 0 ustar 00root root 0000000 0000000 from .layer import YowIbProtocolLayer
yowsup-3.2.3/yowsup/layers/protocol_ib/layer.py 0000664 0000000 0000000 00000002502 13464333726 0021745 0 ustar 00root root 0000000 0000000 from yowsup.layers import YowLayer, YowLayerEvent, YowProtocolLayer
from .protocolentities import *
import logging
logger = logging.getLogger(__name__)
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))
elif node.getChild("edge_routing"):
logger.debug("ignoring edge_routing ib node for now")
elif node.getChild("attestation"):
logger.debug("ignoring attestation ib node for now")
elif node.getChild("fbip"):
logger.debug("ignoring fbip ib node for now")
else:
logger.warning("Unsupported ib node: %s" % node)
yowsup-3.2.3/yowsup/layers/protocol_ib/protocolentities/ 0000775 0000000 0000000 00000000000 13464333726 0023666 5 ustar 00root root 0000000 0000000 yowsup-3.2.3/yowsup/layers/protocol_ib/protocolentities/__init__.py 0000664 0000000 0000000 00000000267 13464333726 0026004 0 ustar 00root root 0000000 0000000 from .clean_iq import CleanIqProtocolEntity
from .dirty_ib import DirtyIbProtocolEntity
from .offline_ib import OfflineIbProtocolEntity
from .account_ib import AccountIbProtocolEntity yowsup-3.2.3/yowsup/layers/protocol_ib/protocolentities/account_ib.py 0000664 0000000 0000000 00000003714 13464333726 0026353 0 ustar 00root root 0000000 0000000 from 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-3.2.3/yowsup/layers/protocol_ib/protocolentities/clean_iq.py 0000664 0000000 0000000 00000002421 13464333726 0026012 0 ustar 00root root 0000000 0000000 from 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 entity yowsup-3.2.3/yowsup/layers/protocol_ib/protocolentities/dirty_ib.py 0000664 0000000 0000000 00000002401 13464333726 0026042 0 ustar 00root root 0000000 0000000 from 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-3.2.3/yowsup/layers/protocol_ib/protocolentities/ib.py 0000664 0000000 0000000 00000000715 13464333726 0024635 0 ustar 00root root 0000000 0000000 from 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-3.2.3/yowsup/layers/protocol_ib/protocolentities/offline_ib.py 0000664 0000000 0000000 00000002050 13464333726 0026331 0 ustar 00root root 0000000 0000000 from 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-3.2.3/yowsup/layers/protocol_ib/protocolentities/test_clean_iq.py 0000664 0000000 0000000 00000000765 13464333726 0027062 0 ustar 00root root 0000000 0000000 from 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-3.2.3/yowsup/layers/protocol_ib/protocolentities/test_dirty_ib.py 0000664 0000000 0000000 00000001057 13464333726 0027107 0 ustar 00root root 0000000 0000000 from 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-3.2.3/yowsup/layers/protocol_ib/protocolentities/test_ib.py 0000664 0000000 0000000 00000000567 13464333726 0025701 0 ustar 00root root 0000000 0000000 from 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-3.2.3/yowsup/layers/protocol_ib/protocolentities/test_offline_iq.py 0000664 0000000 0000000 00000000736 13464333726 0027420 0 ustar 00root root 0000000 0000000 from 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-3.2.3/yowsup/layers/protocol_iq/ 0000775 0000000 0000000 00000000000 13464333726 0020277 5 ustar 00root root 0000000 0000000 yowsup-3.2.3/yowsup/layers/protocol_iq/__init__.py 0000664 0000000 0000000 00000000045 13464333726 0022407 0 ustar 00root root 0000000 0000000 from .layer import YowIqProtocolLayer yowsup-3.2.3/yowsup/layers/protocol_iq/layer.py 0000664 0000000 0000000 00000007534 13464333726 0021776 0 ustar 00root root 0000000 0000000 import time
import logging
from threading import Thread, Lock
from yowsup.layers import YowProtocolLayer, YowLayerEvent, EventCallback
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"))
@EventCallback(YowAuthenticationProtocolLayer.EVENT_AUTHED)
def onAuthed(self, event):
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()
def stop_thread(self):
if self._pingThread:
self.__logger.debug("stopping ping thread")
if self._pingThread:
self._pingThread.stop()
self._pingThread = None
self._pingQueue = {}
@EventCallback(YowNetworkLayer.EVENT_STATE_DISCONNECT)
def onDisconnect(self, event):
self.stop_thread()
@EventCallback(YowNetworkLayer.EVENT_STATE_DISCONNECTED)
def onDisconnected(self, event):
self.stop_thread()
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-3.2.3/yowsup/layers/protocol_iq/protocolentities/ 0000775 0000000 0000000 00000000000 13464333726 0023705 5 ustar 00root root 0000000 0000000 yowsup-3.2.3/yowsup/layers/protocol_iq/protocolentities/__init__.py 0000664 0000000 0000000 00000000540 13464333726 0026015 0 ustar 00root root 0000000 0000000 from .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-3.2.3/yowsup/layers/protocol_iq/protocolentities/iq.py 0000664 0000000 0000000 00000004331 13464333726 0024671 0 ustar 00root root 0000000 0000000 from 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-3.2.3/yowsup/layers/protocol_iq/protocolentities/iq_crypto.py 0000664 0000000 0000000 00000001213 13464333726 0026265 0 ustar 00root root 0000000 0000000 from .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 node yowsup-3.2.3/yowsup/layers/protocol_iq/protocolentities/iq_error.py 0000664 0000000 0000000 00000003155 13464333726 0026105 0 ustar 00root root 0000000 0000000 from 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-3.2.3/yowsup/layers/protocol_iq/protocolentities/iq_ping.py 0000664 0000000 0000000 00000001053 13464333726 0025704 0 ustar 00root root 0000000 0000000 from 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-3.2.3/yowsup/layers/protocol_iq/protocolentities/iq_props.py 0000664 0000000 0000000 00000000610 13464333726 0026110 0 ustar 00root root 0000000 0000000 from .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 node yowsup-3.2.3/yowsup/layers/protocol_iq/protocolentities/iq_push.py 0000664 0000000 0000000 00000000633 13464333726 0025731 0 ustar 00root root 0000000 0000000 from .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 node yowsup-3.2.3/yowsup/layers/protocol_iq/protocolentities/iq_result.py 0000664 0000000 0000000 00000000641 13464333726 0026267 0 ustar 00root root 0000000 0000000 from 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-3.2.3/yowsup/layers/protocol_iq/protocolentities/iq_result_pong.py 0000664 0000000 0000000 00000000604 13464333726 0027311 0 ustar 00root root 0000000 0000000 from 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-3.2.3/yowsup/layers/protocol_iq/protocolentities/test_iq.py 0000664 0000000 0000000 00000000671 13464333726 0025733 0 ustar 00root root 0000000 0000000 from 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-3.2.3/yowsup/layers/protocol_iq/protocolentities/test_iq_error.py 0000664 0000000 0000000 00000000771 13464333726 0027145 0 ustar 00root root 0000000 0000000 from 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-3.2.3/yowsup/layers/protocol_iq/protocolentities/test_iq_result.py 0000664 0000000 0000000 00000000411 13464333726 0027321 0 ustar 00root root 0000000 0000000 from 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-3.2.3/yowsup/layers/protocol_media/ 0000775 0000000 0000000 00000000000 13464333726 0020745 5 ustar 00root root 0000000 0000000 yowsup-3.2.3/yowsup/layers/protocol_media/__init__.py 0000664 0000000 0000000 00000000052 13464333726 0023053 0 ustar 00root root 0000000 0000000 from .layer import YowMediaProtocolLayer
yowsup-3.2.3/yowsup/layers/protocol_media/layer.py 0000664 0000000 0000000 00000007310 13464333726 0022434 0 ustar 00root root 0000000 0000000 from yowsup.layers import YowProtocolLayer
from .protocolentities import ImageDownloadableMediaMessageProtocolEntity
from .protocolentities import AudioDownloadableMediaMessageProtocolEntity
from .protocolentities import VideoDownloadableMediaMessageProtocolEntity
from .protocolentities import DocumentDownloadableMediaMessageProtocolEntity
from .protocolentities import LocationMediaMessageProtocolEntity
from .protocolentities import ContactMediaMessageProtocolEntity
from .protocolentities import ResultRequestUploadIqProtocolEntity
from .protocolentities import MediaMessageProtocolEntity
from .protocolentities import ExtendedTextMediaMessageProtocolEntity
from yowsup.layers.protocol_iq.protocolentities import IqProtocolEntity, ErrorIqProtocolEntity
import logging
logger = logging.getLogger(__name__)
class YowMediaProtocolLayer(YowProtocolLayer):
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 sendMessageEntity(self, entity):
if entity.getType() == "media":
self.entityToLower(entity)
def recvMessageStanza(self, node):
if node.getAttributeValue("type") == "media":
mediaNode = node.getChild("proto")
if mediaNode.getAttributeValue("mediatype") == "image":
entity = ImageDownloadableMediaMessageProtocolEntity.fromProtocolTreeNode(node)
self.toUpper(entity)
elif mediaNode.getAttributeValue("mediatype") in ("audio", "ptt"):
entity = AudioDownloadableMediaMessageProtocolEntity.fromProtocolTreeNode(node)
self.toUpper(entity)
elif mediaNode.getAttributeValue("mediatype") in ("video", "gif"):
entity = VideoDownloadableMediaMessageProtocolEntity.fromProtocolTreeNode(node)
self.toUpper(entity)
elif mediaNode.getAttributeValue("mediatype") == "location":
entity = LocationMediaMessageProtocolEntity.fromProtocolTreeNode(node)
self.toUpper(entity)
elif mediaNode.getAttributeValue("mediatype") == "contact":
entity = ContactMediaMessageProtocolEntity.fromProtocolTreeNode(node)
self.toUpper(entity)
elif mediaNode.getAttributeValue("mediatype") == "document":
entity = DocumentDownloadableMediaMessageProtocolEntity.fromProtocolTreeNode(node)
self.toUpper(entity)
elif mediaNode.getAttributeValue("mediatype") == "url":
entity = ExtendedTextMediaMessageProtocolEntity.fromProtocolTreeNode(node)
self.toUpper(entity)
else:
logger.warn("Unsupported mediatype: %s, will send receipts" % mediaNode.getAttributeValue("mediatype"))
self.toLower(MediaMessageProtocolEntity.fromProtocolTreeNode(node).ack(True).toProtocolTreeNode())
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-3.2.3/yowsup/layers/protocol_media/mediacipher.py 0000664 0000000 0000000 00000006121 13464333726 0023571 0 ustar 00root root 0000000 0000000 from axolotl.kdf.hkdfv3 import HKDFv3
from axolotl.util.byteutil import ByteUtil
from cryptography.hazmat.primitives.ciphers import Cipher, algorithms, modes
from cryptography.hazmat.backends import default_backend
from cryptography.hazmat.primitives import padding
import hmac
import hashlib
class MediaCipher(object):
INFO_IMAGE = b"WhatsApp Image Keys"
INFO_AUDIO = b"WhatsApp Audio Keys"
INFO_VIDEO = b"WhatsApp Video Keys"
INFO_DOCUM = b"WhatsApp Document Keys"
def encrypt_image(self, plaintext, ref_key):
return self.encrypt(plaintext, ref_key, self.INFO_IMAGE)
def encrypt_audio(self, ciphertext, ref_key):
return self.encrypt(ciphertext, ref_key, self.INFO_AUDIO)
def encrypt_video(self, ciphertext, ref_key):
return self.encrypt(ciphertext, ref_key, self.INFO_VIDEO)
def encrypt_document(self, ciphertext, ref_key):
return self.encrypt(ciphertext, ref_key, self.INFO_DOCUM)
def decrypt_image(self, ciphertext, ref_key):
return self.decrypt(ciphertext, ref_key, self.INFO_IMAGE)
def decrypt_audio(self, ciphertext, ref_key):
return self.decrypt(ciphertext, ref_key, self.INFO_AUDIO)
def decrypt_video(self, ciphertext, ref_key):
return self.decrypt(ciphertext, ref_key, self.INFO_VIDEO)
def decrypt_document(self, ciphertext, ref_key):
return self.decrypt(ciphertext, ref_key, self.INFO_DOCUM)
def encrypt(self, plaintext, ref_key, media_info):
derived = HKDFv3().deriveSecrets(ref_key, media_info, 112)
parts = ByteUtil.split(derived, 16, 32)
iv = parts[0]
key = parts[1]
mac_key = derived[48:80]
cipher_encryptor = Cipher(
algorithms.AES(key), modes.CBC(iv), backend=default_backend()
).encryptor()
if len(plaintext) % 16 != 0:
padder = padding.PKCS7(128).padder()
padded_plaintext = padder.update(plaintext) + padder.finalize()
else:
padded_plaintext = plaintext
ciphertext = cipher_encryptor.update(padded_plaintext) + cipher_encryptor.finalize()
mac = hmac.new(mac_key, digestmod=hashlib.sha256)
mac.update(iv)
mac.update(ciphertext)
return ciphertext + mac.digest()[:10]
def decrypt(self, ciphertext, ref_key, media_info):
derived = HKDFv3().deriveSecrets(ref_key, media_info, 112)
parts = ByteUtil.split(derived, 16, 32)
iv = parts[0]
key = parts[1]
mac_key = derived[48:80]
media_ciphertext = ciphertext[:-10]
mac_value = ciphertext[-10:]
mac = hmac.new(mac_key, digestmod=hashlib.sha256)
mac.update(iv)
mac.update(media_ciphertext)
if mac_value != mac.digest()[:10]:
raise ValueError("Invalid MAC")
cipher_decryptor = Cipher(
algorithms.AES(key), modes.CBC(iv), backend=default_backend()
).decryptor()
decrypted = cipher_decryptor.update(media_ciphertext) + cipher_decryptor.finalize()
unpadder = padding.PKCS7(128).unpadder()
return unpadder.update(decrypted) + unpadder.finalize()
yowsup-3.2.3/yowsup/layers/protocol_media/mediadownloader.py 0000664 0000000 0000000 00000004013 13464333726 0024453 0 ustar 00root root 0000000 0000000 import 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-3.2.3/yowsup/layers/protocol_media/mediauploader.py 0000664 0000000 0000000 00000012152 13464333726 0024133 0 ustar 00root root 0000000 0000000 from yowsup.common.http.warequest import WARequest
from yowsup.common.http.waresponseparser import JSONResponseParser
import socket
import ssl
import os
import hashlib
import sys
from time import sleep
import threading
import logging
from yowsup.common.tools import MimeTools
logger = logging.getLogger(__name__)
class MediaUploader(WARequest, threading.Thread):
def __init__(self, jid, accountJid, sourcePath, uploadUrl, resumeOffset=0, successClbk=None, errorClbk=None, progressCallback=None, asynchronous=True):
WARequest.__init__(self)
self.asynchronous = asynchronous
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.asynchronous:
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 = MimeTools.getMIME(filename)
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-3.2.3/yowsup/layers/protocol_media/protocolentities/ 0000775 0000000 0000000 00000000000 13464333726 0024353 5 ustar 00root root 0000000 0000000 yowsup-3.2.3/yowsup/layers/protocol_media/protocolentities/__init__.py 0000664 0000000 0000000 00000001523 13464333726 0026465 0 ustar 00root root 0000000 0000000 from .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_downloadable_document import DocumentDownloadableMediaMessageProtocolEntity
from .message_media_location import LocationMediaMessageProtocolEntity
from .message_media_contact import ContactMediaMessageProtocolEntity
from .message_media_extendedtext import ExtendedTextMediaMessageProtocolEntity
from .iq_requestupload import RequestUploadIqProtocolEntity
from .iq_requestupload_result import ResultRequestUploadIqProtocolEntity
yowsup-3.2.3/yowsup/layers/protocol_media/protocolentities/attributes/ 0000775 0000000 0000000 00000000000 13464333726 0026541 5 ustar 00root root 0000000 0000000 yowsup-3.2.3/yowsup/layers/protocol_media/protocolentities/attributes/__init__.py 0000664 0000000 0000000 00000000000 13464333726 0030640 0 ustar 00root root 0000000 0000000 yowsup-3.2.3/yowsup/layers/protocol_media/protocolentities/attributes/attributes_audio.py 0000664 0000000 0000000 00000000752 13464333726 0032466 0 ustar 00root root 0000000 0000000 class AudioAttributes(object):
def __init__(self, seconds, ptt):
"""
:param seconds: duration of audio playback in seconds
:type seconds: int
:param ptt: indicates whether this is a push-to-talk audio message
:type ptt: bool
"""
self._seconds = seconds # type: int
self._ptt = ptt # type: bool
@property
def seconds(self):
return self._seconds
@property
def ptt(self):
return self._ptt
yowsup-3.2.3/yowsup/layers/protocol_media/protocolentities/attributes/attributes_contact.py 0000664 0000000 0000000 00000000440 13464333726 0033012 0 ustar 00root root 0000000 0000000 class ContactAttributes(object):
def __init__(self, display_name, vcard):
self._display_name = display_name
self._vcard = vcard
@property
def display_name(self):
return self._display_name
@property
def vcard(self):
return self._vcard
yowsup-3.2.3/yowsup/layers/protocol_media/protocolentities/attributes/attributes_document.py 0000664 0000000 0000000 00000001546 13464333726 0033205 0 ustar 00root root 0000000 0000000 import os
class DocumentAttributes(object):
def __init__(self, file_name, file_length, title=None, page_count=None, jpeg_thumbnail=None):
self._file_name = file_name
self._file_length = file_length
self._title = title
self._page_count = page_count
self._jpeg_thumbnail = jpeg_thumbnail
@property
def file_name(self):
return self._file_name
@property
def file_length(self):
return self._file_length
@property
def title(self):
return self._title
@property
def page_count(self):
return self._page_count
@property
def jpeg_thumbnail(self):
return self._jpeg_thumbnail
@staticmethod
def from_filepath(filepath):
return DocumentAttributes(
os.path.basename(filepath),
os.path.getsize(filepath)
)
attributes_downloadablemedia.py 0000664 0000000 0000000 00000003446 13464333726 0034744 0 ustar 00root root 0000000 0000000 yowsup-3.2.3/yowsup/layers/protocol_media/protocolentities/attributes from yowsup.layers.protocol_media.protocolentities.attributes.attributes_media import MediaAttributes
from yowsup.common.tools import MimeTools
import base64
import hashlib
import os
class DownloadableMediaMessageAttributes(MediaAttributes):
def __init__(self, mimetype, file_length, file_sha256, url=None, media_key=None, context_info=None):
super(DownloadableMediaMessageAttributes, self).__init__(context_info)
self._mimetype = mimetype
self._file_length = file_length
self._file_sha256 = file_sha256
self._url = url
self._media_key = media_key
def __str__(self):
return "[url=%s, mimetype=%s, file_length=%d, file_sha256=%s, media_key=%s]" % (
self.url,self.mimetype, self.file_length, base64.b64encode(self.file_sha256),
base64.b64encode(self.media_key)
)
@property
def url(self):
return self._url
@property
def mimetype(self):
return self._mimetype
@property
def file_length(self):
return self._file_length
@property
def file_sha256(self):
return self._file_sha256
@property
def media_key(self):
return self._media_key
@staticmethod
def from_file(
filepath, mimetype=None, file_length=None,
file_sha256=None, url=None, media_key=None, context_info=None
):
mimetype = MimeTools.getMIME(filepath) if mimetype is None else mimetype
file_length = os.path.getsize(filepath) if file_length is None else file_length
if file_sha256 is None:
with open(filepath, 'rb') as f:
file_sha256 = hashlib.sha256(f.read()).digest()
return DownloadableMediaMessageAttributes(
mimetype, file_length, file_sha256, url, media_key, context_info
)
yowsup-3.2.3/yowsup/layers/protocol_media/protocolentities/attributes/attributes_extendedtext.py 0000664 0000000 0000000 00000001476 13464333726 0034076 0 ustar 00root root 0000000 0000000 class ExtendedTextAttributes(object):
def __init__(self,
text, matched_text, canonical_url, description, title, jpeg_thumbnail
):
self._text = text
self._matched_text = matched_text
self._canonical_url = canonical_url
self._description = description
self._title = title
self._jpeg_thumbnail = jpeg_thumbnail
@property
def text(self):
return self._text
@property
def matched_text(self):
return self._matched_text
@property
def canonical_url(self):
return self._canonical_url
@property
def description(self):
return self._description
@property
def title(self):
return self._title
@property
def jpeg_thumbnail(self):
return self._jpeg_thumbnail
yowsup-3.2.3/yowsup/layers/protocol_media/protocolentities/attributes/attributes_image.py 0000664 0000000 0000000 00000001536 13464333726 0032450 0 ustar 00root root 0000000 0000000 from yowsup.common.tools import ImageTools
import os
class ImageAttributes(object):
def __init__(self, width, height, caption=None, jpeg_thumbnail=None):
self.width = width
self.height = height
self.caption = caption
self.jpeg_thumbnail = jpeg_thumbnail
@staticmethod
def from_filepath(filepath, dimensions=None, caption=None, jpeg_thumbnail=None):
assert os.path.exists(filepath)
if not jpeg_thumbnail:
jpeg_thumbnail = ImageTools.generatePreviewFromImage(filepath)
dimensions = dimensions or ImageTools.getImageDimensions(filepath)
width, height = dimensions if dimensions else (None, None)
assert width and height, "Could not determine image dimensions, install pillow or pass dimensions"
return ImageAttributes(width, height, caption, jpeg_thumbnail) yowsup-3.2.3/yowsup/layers/protocol_media/protocolentities/attributes/attributes_location.py 0000664 0000000 0000000 00000004424 13464333726 0033175 0 ustar 00root root 0000000 0000000 class LocationAttributes(object):
def __init__(self,
degrees_latitude, degrees_longitude,
name=None, address=None, url=None,
duration=None, accuracy_in_meters=None, speed_in_mps=None, degrees_clockwise_from_magnetic_north=None,
axolotl_sender_key_distribution_message=None, jpeg_thumbnail=None):
"""
:param degrees_latitude: Actual location, Place
:param degrees_longitude: Actual location, Place
:param name: Place
:param address: Place
:param url: Place
:param duration:
:param accuracy_in_meters:
:param speed_in_mps:
:param degrees_clockwise_from_magnetic_north:
:param axolotl_sender_key_distribution_message:
:param jpeg_thumbnail: Actual location, Place
"""
self._degrees_latitude = degrees_latitude
self._degrees_longitude = degrees_longitude
self._name = name
self._address = address
self._url = url
self._duration = duration
self._accuracy_in_meters = accuracy_in_meters
self._speed_in_mps = speed_in_mps
self._degrees_clockwise_from_magnetic_north = degrees_clockwise_from_magnetic_north
self._axolotl_sender_key_distribution_message = axolotl_sender_key_distribution_message
self._jpeg_thumbnail = jpeg_thumbnail
@property
def degrees_latitude(self):
return self._degrees_latitude
@property
def degrees_longitude(self):
return self._degrees_longitude
@property
def name(self):
return self._name
@property
def address(self):
return self._address
@property
def url(self):
return self._url
@property
def duration(self):
return self._duration
@property
def accuracy_in_meters(self):
return self._accuracy_in_meters
@property
def speed_in_mps(self):
return self._speed_in_mps
@property
def degrees_clockwise_from_magnetic_north(self):
return self._degrees_clockwise_from_magnetic_north
@property
def axolotl_sender_key_distribution_message(self):
return self._axolotl_sender_key_distribution_message
@property
def jpeg_thumbnail(self):
return self._jpeg_thumbnail
yowsup-3.2.3/yowsup/layers/protocol_media/protocolentities/attributes/attributes_media.py 0000664 0000000 0000000 00000000722 13464333726 0032441 0 ustar 00root root 0000000 0000000 from yowsup.layers.protocol_media.protocolentities.attributes.context_info import ContextInfo
class MediaAttributes(object):
def __init__(self, context_info=None):
"""
:type context_info: ContextInfo | None
"""
if context_info:
assert type(context_info) is ContextInfo
self._context_info = context_info # type: ContextInfo | None
@property
def context_info(self):
return self._context_info
yowsup-3.2.3/yowsup/layers/protocol_media/protocolentities/attributes/attributes_video.py 0000664 0000000 0000000 00000002110 13464333726 0032461 0 ustar 00root root 0000000 0000000 class VideoAttributes(object):
def __init__(self, width, height, seconds,
gif_playback=None, jpeg_thumbnail=None, gif_attribution=None, caption=None, streaming_sidecar=None):
self._width = width
self._height = height
self._seconds = seconds
self._gif_playback = gif_playback
self._jpeg_thumbnail = jpeg_thumbnail
self._gif_attribution = gif_attribution
self._caption = caption
self._streaming_sidecar = streaming_sidecar
@property
def width(self):
return self._width
@property
def height(self):
return self._height
@property
def seconds(self):
return self._seconds
@property
def gif_playback(self):
return self._gif_playback
@property
def jpeg_thumbnail(self):
return self._jpeg_thumbnail
@property
def gif_attribution(self):
return self._gif_attribution
@property
def caption(self):
return self._caption
@property
def streaming_sidecar(self):
return self._streaming_sidecar
yowsup-3.2.3/yowsup/layers/protocol_media/protocolentities/attributes/context_info.py 0000664 0000000 0000000 00000002174 13464333726 0031616 0 ustar 00root root 0000000 0000000 class ContextInfo(object):
def __init__(self,
stanza_id=None,
participant=None,
quoted_message=None,
remote_jid=None,
mentioned_jid=None,
edit_version=None,
revoke_message=None
):
self._stanza_id= stanza_id
self._participant = participant
self._quoted_message = quoted_message
self._remote_jid = remote_jid
self._mentioned_jid = mentioned_jid
self._edit_version = edit_version
self._revoke_message = revoke_message
@property
def stanza_id(self):
return self._stanza_id
@property
def participant(self):
return self._participant
@property
def quoted_message(self):
return self._quoted_message
@property
def remote_jid(self):
return self._remote_jid
@property
def mentioned_jid(self):
return self._mentioned_jid
@property
def edit_version(self):
return self._edit_version
@property
def revoke_message(self):
return self._revoke_message
yowsup-3.2.3/yowsup/layers/protocol_media/protocolentities/iq_requestupload.py 0000664 0000000 0000000 00000006274 13464333726 0030324 0 ustar 00root root 0000000 0000000 from yowsup.common import YowConstants
from 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"
MEDIA_TYPE_DOCUM = "document"
XMLNS = "w:m"
TYPES_MEDIA = (MEDIA_TYPE_AUDIO, MEDIA_TYPE_IMAGE, MEDIA_TYPE_VIDEO, MEDIA_TYPE_DOCUM)
def __init__(self, mediaType, b64Hash = None, size = None, origHash = None, filePath = None ):
super(RequestUploadIqProtocolEntity, self).__init__("w:m", _type = "set", to = YowConstants.WHATSAPP_SERVER)
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("encr_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("encr_media")
entity.setRequestArguments(
mediaNode.getAttributeValue("type"),
mediaNode.getAttributeValue("hash"),
mediaNode.getAttributeValue("size"),
mediaNode.getAttributeValue("orighash")
)
return entity
yowsup-3.2.3/yowsup/layers/protocol_media/protocolentities/iq_requestupload_result.py 0000664 0000000 0000000 00000004256 13464333726 0031720 0 ustar 00root root 0000000 0000000 from yowsup.common import YowConstants
from 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 = YowConstants.WHATSAPP_SERVER)
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("encr_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("encr_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-3.2.3/yowsup/layers/protocol_media/protocolentities/message_media.py 0000664 0000000 0000000 00000010544 13464333726 0027514 0 ustar 00root root 0000000 0000000 from yowsup.layers.protocol_messages.protocolentities.protomessage import ProtomessageProtocolEntity
from yowsup.layers.protocol_media.protocolentities.attributes.attributes_media import MediaAttributes
from yowsup.layers.protocol_messages.protocolentities.attributes.attributes_message import MessageAttributes
import logging
logger = logging.getLogger(__name__)
class MediaMessageProtocolEntity(ProtomessageProtocolEntity):
TYPE_MEDIA_IMAGE = "image"
TYPE_MEDIA_VIDEO = "video"
TYPE_MEDIA_AUDIO = "audio"
TYPE_MEDIA_CONTACT = "contact"
TYPE_MEDIA_LOCATION = "location"
TYPE_MEDIA_DOCUMENT = "document"
TYPE_MEDIA_GIF = "gif"
TYPE_MEDIA_PTT = "ptt"
TYPE_MEDIA_URL = "url"
TYPES_MEDIA = (
TYPE_MEDIA_IMAGE, TYPE_MEDIA_AUDIO, TYPE_MEDIA_VIDEO,
TYPE_MEDIA_CONTACT, TYPE_MEDIA_LOCATION, TYPE_MEDIA_DOCUMENT,
TYPE_MEDIA_GIF, TYPE_MEDIA_PTT, TYPE_MEDIA_URL
)
def __init__(self, media_type, media_message_attrs, message_attrs):
"""
:type media_type: str
:type media_message_attrs: MediaAttributes
:type message_attrs: MessageAttributes
"""
super(MediaMessageProtocolEntity, self).__init__("media", message_attrs)
self.media_type = media_type # type: str
if media_message_attrs.context_info:
self.context_stanza_id = media_message_attrs.context_info.stanza_id
self.context_participant = media_message_attrs.context_info.participant
self.context_quoted_message = media_message_attrs.context_info.quoted_message
self.context_edit_version = media_message_attrs.context_info.edit_version
self.context_remote_jid = media_message_attrs.context_info.remote_jid
self.context_mentioned_jid = media_message_attrs.context_info.mentioned_jid
self.context_revoke_message = media_message_attrs.context_info.revoke_message
def __str__(self):
out = super(MediaMessageProtocolEntity, self).__str__()
out += "\nmediatype=%s" % self.media_type
return out
@property
def context_stanza_id(self):
return self.proto.stanza_id
@context_stanza_id.setter
def context_stanza_id(self, value):
self.proto.context_info.stanza_id = value
@property
def context_participant(self):
return self.proto.context_info.participant
@context_participant.setter
def context_participant(self, value):
self.proto.context_info = value
@property
def context_quoted_message(self):
return self.proto.context_info.quoted_message
@context_quoted_message.setter
def context_quoted_message(self, value):
self.proto.context_info.quoted_message = value
@property
def context_edit_version(self):
return self.proto.context_info.edit_version
@context_edit_version.setter
def context_edit_version(self, value):
self.proto.context_info.edit_version = value
@property
def context_remote_jid(self):
return self.proto.context_info.remote_jid
@context_remote_jid.setter
def context_remote_jid(self, value):
self.proto.context_info.remote_jid = value
@property
def context_mentioned_jid(self):
return self.proto.context_info.mentioned_jid
@context_mentioned_jid.setter
def context_mentioned_jid(self, value):
self.proto.context_info.mentioned_jid = value
@property
def context_revoke_message(self):
return self.proto.context_info.revoke_message
@context_revoke_message.setter
def context_revoke_message(self, value):
self.proto.context_info.revoke_message = value
@property
def media_type(self):
return self._media_type
@media_type.setter
def media_type(self, value):
if value not in MediaMessageProtocolEntity.TYPES_MEDIA:
logger.warn("media type: '%s' is not supported" % value)
self._media_type = value
def toProtocolTreeNode(self):
node = super(MediaMessageProtocolEntity, self).toProtocolTreeNode()
protoNode = node.getChild("proto")
protoNode["mediatype"] = self.media_type
return node
@classmethod
def fromProtocolTreeNode(cls, node):
entity = ProtomessageProtocolEntity.fromProtocolTreeNode(node)
entity.__class__ = cls
entity.media_type = node.getChild("proto")["mediatype"]
return entity
yowsup-3.2.3/yowsup/layers/protocol_media/protocolentities/message_media_contact.py 0000664 0000000 0000000 00000002124 13464333726 0031222 0 ustar 00root root 0000000 0000000 from yowsup.layers.protocol_messages.protocolentities.attributes.attributes_message import MessageAttributes
from .message_media import MediaMessageProtocolEntity
from .attributes.attributes_contact import ContactAttributes
from .attributes.attributes_media import MediaAttributes
class ContactMediaMessageProtocolEntity(MediaMessageProtocolEntity):
def __init__(self, contact_attrs, media_attrs, message_attrs):
# type: (ContactAttributes, MediaAttributes, MessageAttributes) -> None
super(ContactMediaMessageProtocolEntity, self).__init__("contact", media_attrs, message_attrs)
self.display_name = contact_attrs.display_name
self.vcard = contact_attrs.vcard
@property
def proto(self):
return self._proto.contact_message
@property
def display_name(self):
return self.proto.display_name
@display_name.setter
def display_name(self, value):
self.proto.display_name = value
@property
def vcard(self):
return self.proto.vcard
@vcard.setter
def vcard(self, value):
self.proto.vcard = value
yowsup-3.2.3/yowsup/layers/protocol_media/protocolentities/message_media_downloadable.py 0000664 0000000 0000000 00000003473 13464333726 0032232 0 ustar 00root root 0000000 0000000 from .message_media import MediaMessageProtocolEntity
from yowsup.layers.protocol_messages.protocolentities.attributes.attributes_message import MessageAttributes
from yowsup.layers.protocol_media.protocolentities.attributes.attributes_downloadablemedia \
import DownloadableMediaMessageAttributes
class DownloadableMediaMessageProtocolEntity(MediaMessageProtocolEntity):
def __init__(self, media_type, downloadable_media_message_attrs, message_attrs):
# type: (str, DownloadableMediaMessageAttributes, MessageAttributes)
super(DownloadableMediaMessageProtocolEntity, self).__init__(
media_type, downloadable_media_message_attrs, message_attrs
)
self.url = downloadable_media_message_attrs.url
self.mimetype = downloadable_media_message_attrs.mimetype
self.file_sha256 = downloadable_media_message_attrs.file_sha256
self.file_length = downloadable_media_message_attrs.file_length
self.media_key = downloadable_media_message_attrs.media_key
@property
def url(self):
return self.proto.url
@url.setter
def url(self, value):
self.proto.url = value
@property
def mimetype(self):
return self.proto.mimetype
@mimetype.setter
def mimetype(self, value):
self.proto.mimetype = value
@property
def file_sha256(self):
return self.proto.file_sha256
@file_sha256.setter
def file_sha256(self, value):
self.proto.file_sha256 = value
@property
def file_length(self):
return self.proto.file_length
@file_length.setter
def file_length(self, value):
self.proto.file_length = value
@property
def media_key(self):
return self.proto.media_key
@media_key.setter
def media_key(self, value):
self.proto.media_key = value
yowsup-3.2.3/yowsup/layers/protocol_media/protocolentities/message_media_downloadable_audio.py 0000664 0000000 0000000 00000002720 13464333726 0033405 0 ustar 00root root 0000000 0000000 from .message_media_downloadable import DownloadableMediaMessageProtocolEntity
from yowsup.layers.protocol_media.protocolentities.attributes.attributes_downloadablemedia \
import DownloadableMediaMessageAttributes
from yowsup.layers.protocol_media.protocolentities.attributes.attributes_audio \
import AudioAttributes
from yowsup.layers.protocol_messages.protocolentities.attributes.attributes_message import MessageAttributes
class AudioDownloadableMediaMessageProtocolEntity(DownloadableMediaMessageProtocolEntity):
def __init__(self, audio_attrs, downloadablemedia_attrs, message_attrs):
"""
:type audio_attrs: AudioAttributes
:type downloadablemedia_attrs: DownloadableMediaMessageAttributes
:type message_attrs: MessageAttributes
"""
super(AudioDownloadableMediaMessageProtocolEntity, self).__init__(
"audio", downloadablemedia_attrs, message_attrs
)
self.seconds = audio_attrs.seconds
self.ptt = audio_attrs.ptt
@property
def proto(self):
return self._proto.audio_message
@property
def seconds(self):
return self.proto.seconds
@seconds.setter
def seconds(self, value):
"""
:type value: int
"""
self.proto.seconds = value
@property
def ptt(self):
return self.proto.ptt
@ptt.setter
def ptt(self, value):
"""
:type value: bool
"""
self.proto.ptt = value
yowsup-3.2.3/yowsup/layers/protocol_media/protocolentities/message_media_downloadable_document.py 0000664 0000000 0000000 00000004455 13464333726 0034131 0 ustar 00root root 0000000 0000000 from .message_media_downloadable import DownloadableMediaMessageProtocolEntity
from yowsup.layers.protocol_media.protocolentities.attributes.attributes_downloadablemedia \
import DownloadableMediaMessageAttributes
from yowsup.layers.protocol_media.protocolentities.attributes.attributes_document \
import DocumentAttributes
from yowsup.layers.protocol_messages.protocolentities.attributes.attributes_message import MessageAttributes
class DocumentDownloadableMediaMessageProtocolEntity(DownloadableMediaMessageProtocolEntity):
def __init__(self, document_attrs, downloadablemedia_attrs, message_attrs):
"""
:type document_attrs: DocumentAttributes
:type downloadablemedia_attrs: DownloadableMediaMessageAttributes
:type message_attrs: MessageAttributes
"""
super(DocumentDownloadableMediaMessageProtocolEntity, self).__init__(
"document", downloadablemedia_attrs, message_attrs
)
self.file_name = document_attrs.file_name
self.file_length = document_attrs.file_length
if document_attrs.title is not None:
self.title = document_attrs.title
if document_attrs.page_count is not None:
self.page_count = document_attrs.page_count
if document_attrs.jpeg_thumbnail is not None:
self.jpeg_thumbnail = document_attrs.jpeg_thumbnail
@property
def proto(self):
return self._proto.document_message
@property
def file_name(self):
return self.proto.file_name
@file_name.setter
def file_name(self, value):
self.proto.file_name = value
@property
def file_length(self):
return self.proto.file_length
@file_length.setter
def file_length(self, value):
self.proto.file_length = value
@property
def title(self):
return self.proto.title
@title.setter
def title(self, value):
self.proto.title = value
@property
def page_count(self):
return self.proto.page_count
@page_count.setter
def page_count(self, value):
self.proto.page_count = value
@property
def jpeg_thumbnail(self):
return self.proto.image_message.jpeg_thumbnail
@jpeg_thumbnail.setter
def jpeg_thumbnail(self, value):
self.proto.image_message.jpeg_thumbnail = value
yowsup-3.2.3/yowsup/layers/protocol_media/protocolentities/message_media_downloadable_image.py 0000664 0000000 0000000 00000003421 13464333726 0033365 0 ustar 00root root 0000000 0000000 from .message_media_downloadable import DownloadableMediaMessageProtocolEntity
from yowsup.layers.protocol_media.protocolentities.attributes.attributes_downloadablemedia \
import DownloadableMediaMessageAttributes
from yowsup.layers.protocol_media.protocolentities.attributes.attributes_image import ImageAttributes
from yowsup.layers.protocol_messages.protocolentities.attributes.attributes_message import MessageAttributes
class ImageDownloadableMediaMessageProtocolEntity(DownloadableMediaMessageProtocolEntity):
def __init__(self, image_attrs, downloadablemedia_attrs, message_attrs):
# type: (ImageAttributes, DownloadableMediaMessageAttributes, MessageAttributes) -> None
super(ImageDownloadableMediaMessageProtocolEntity, self).__init__(
"image", downloadablemedia_attrs, message_attrs
)
self.width = image_attrs.width
self.height = image_attrs.height
self.caption = image_attrs.caption
self.jpeg_thumbnail = image_attrs.jpeg_thumbnail
@property
def proto(self):
return self._proto.image_message
@property
def width(self):
return self.proto.width
@width.setter
def width(self, value):
self.proto.width = value
@property
def height(self):
return self.proto.height
@height.setter
def height(self, value):
self.proto.height = value
@property
def jpeg_thumbnail(self):
return self.proto.jpeg_thumbnail
@jpeg_thumbnail.setter
def jpeg_thumbnail(self, value):
self.proto.jpeg_thumbnail = value if value is not None else b""
@property
def caption(self):
return self.proto.caption
@caption.setter
def caption(self, value):
self.proto.caption = value if value is not None else ""
yowsup-3.2.3/yowsup/layers/protocol_media/protocolentities/message_media_downloadable_video.py 0000664 0000000 0000000 00000005771 13464333726 0033423 0 ustar 00root root 0000000 0000000 from .message_media_downloadable import DownloadableMediaMessageProtocolEntity
from yowsup.layers.protocol_media.protocolentities.attributes.attributes_downloadablemedia \
import DownloadableMediaMessageAttributes
from yowsup.layers.protocol_media.protocolentities.attributes.attributes_video import VideoAttributes
from yowsup.layers.protocol_messages.protocolentities.attributes.attributes_message import MessageAttributes
class VideoDownloadableMediaMessageProtocolEntity(DownloadableMediaMessageProtocolEntity):
def __init__(self, video_attrs, downloadablemedia_attrs, message_attrs):
"""
:type video_attrs: VideoAttributes
:type downloadablemedia_attrs: DownloadableMediaMessageAttributes
:type message_attrs: MessageAttributes
"""
super(VideoDownloadableMediaMessageProtocolEntity, self).__init__(
"video", downloadablemedia_attrs, message_attrs
)
self.width = video_attrs.width
self.height = video_attrs.height
self.seconds = video_attrs.seconds
if video_attrs.caption is not None:
self.caption = video_attrs.caption
self.gif_playback = video_attrs.gif_playback if video_attrs.gif_playback else False
if video_attrs.jpeg_thumbnail is not None:
self.jpeg_thumbnail = video_attrs.jpeg_thumbnail
if video_attrs.gif_attribution is not None:
self.gif_attribution = video_attrs.gif_attribution
if video_attrs.streaming_sidecar is not None:
self.streaming_sidecar = video_attrs.streaming_sidecar
@property
def proto(self):
return self._proto.video_message
@property
def width(self):
return self._proto.width
@width.setter
def width(self, value):
self.proto.width = value
@property
def height(self):
return self.proto.height
@height.setter
def height(self, value):
self.proto.height = value
@property
def seconds(self):
return self.proto.seconds
@seconds.setter
def seconds(self, value):
self.proto.seconds = value
@property
def gif_playback(self):
return self.proto.gif_playback
@gif_playback.setter
def gif_playback(self, value):
self.proto.gif_playback = value
@property
def jpeg_thumbnail(self):
return self._proto.jpeg_thumbnail
@jpeg_thumbnail.setter
def jpeg_thumbnail(self, value):
self.proto.jpeg_thumbnail = value
@property
def caption(self):
return self.proto.caption
@caption.setter
def caption(self, value):
self.proto.caption = value
@property
def gif_attribution(self):
return self.proto.gif_attribution
@gif_attribution.setter
def gif_attribution(self, value):
self.proto.gif_attributions = value
@property
def streaming_sidecar(self):
return self.proto.streaming_sidecar
@streaming_sidecar.setter
def streaming_sidecar(self, value):
self.proto.streaming_sidecar = value
yowsup-3.2.3/yowsup/layers/protocol_media/protocolentities/message_media_extendedtext.py 0000664 0000000 0000000 00000004047 13464333726 0032302 0 ustar 00root root 0000000 0000000 from yowsup.layers.protocol_messages.protocolentities.attributes.attributes_message import MessageAttributes
from .message_media import MediaMessageProtocolEntity
from .attributes.attributes_extendedtext import ExtendedTextAttributes
from .attributes.attributes_media import MediaAttributes
class ExtendedTextMediaMessageProtocolEntity(MediaMessageProtocolEntity):
def __init__(self, extended_text_attrs, media_attrs, message_attrs):
# type: (ExtendedTextAttributes, MediaAttributes, MessageAttributes) -> None
super(ExtendedTextMediaMessageProtocolEntity, self).__init__("url", media_attrs, message_attrs)
self.text = extended_text_attrs.text
self.matched_text = extended_text_attrs.matched_text
self.canonical_url = extended_text_attrs.canonical_url
self.description = extended_text_attrs.description
self.title = extended_text_attrs.title
self.jpeg_thumbnail = extended_text_attrs.jpeg_thumbnail
@property
def proto(self):
return self._proto.extended_text_message
@property
def text(self):
return self.proto.text
@text.setter
def text(self, value):
self.proto.text = value
@property
def matched_text(self):
return self.proto.matched_text
@matched_text.setter
def matched_text(self, value):
self.proto.matched_text = value
@property
def canonical_url(self):
return self.proto.canonical_url
@canonical_url.setter
def canonical_url(self, value):
self.proto.canonical_url = value
@property
def description(self):
return self.proto.description
@description.setter
def description(self, value):
self.proto.description = value
@property
def title(self):
return self.proto.title
@title.setter
def title(self, value):
self.proto.title = value
@property
def jpeg_thumbnail(self):
return self.proto.jpeg_thumbnail
@jpeg_thumbnail.setter
def jpeg_thumbnail(self, value):
self.proto.jpeg_thumbnail = value
yowsup-3.2.3/yowsup/layers/protocol_media/protocolentities/message_media_location.py 0000664 0000000 0000000 00000007063 13464333726 0031406 0 ustar 00root root 0000000 0000000 from yowsup.layers.protocol_messages.protocolentities.attributes.attributes_message import MessageAttributes
from .message_media import MediaMessageProtocolEntity
from .attributes.attributes_location import LocationAttributes
from .attributes.attributes_media import MediaAttributes
class LocationMediaMessageProtocolEntity(MediaMessageProtocolEntity):
def __init__(self, location_attrs, media_message_attrs, message_attrs):
# type: (LocationAttributes, MediaAttributes, MessageAttributes) -> None
super(LocationMediaMessageProtocolEntity, self).__init__("location", media_message_attrs, message_attrs)
self.degrees_latitude = location_attrs.degrees_latitude
self.degrees_longitude = location_attrs.degrees_longitude
self.name = location_attrs.name
self.address = location_attrs.address
self.url = location_attrs.url
self.duration = location_attrs.duration
self.accuracy_in_meters = location_attrs.accuracy_in_meters
self.speed_in_mps = location_attrs.speed_in_mps
self.degrees_clockwise_from_magnetic_north = location_attrs.degrees_clockwise_from_magnetic_north
self.axolotl_sender_key_distribution_message = location_attrs.axolotl_sender_key_distribution_message
self.jpeg_thumbnail = location_attrs.jpeg_thumbnail
@property
def proto(self):
return self._proto.location_message
@property
def degrees_latitude(self):
return self.proto.degrees_latitude
@degrees_latitude.setter
def degrees_latitude(self, value):
self.proto.degrees_latitude = value
@property
def degrees_longitude(self):
return self.proto.degrees_longitude
@degrees_longitude.setter
def degrees_longitude(self, value):
self.proto.degrees_longitude = value
@property
def name(self):
return self.proto.name
@name.setter
def name(self, value):
self.proto.name = value
@property
def address(self):
return self.proto.addrees
@address.setter
def address(self, value):
self.proto.address = value
@property
def url(self):
return self.proto.url
@url.setter
def url(self, value):
self.proto.url = value
@property
def duration(self):
return self.proto.duration
@duration.setter
def duration(self, value):
self.proto.duration = value
@property
def accuracy_in_meters(self):
return self.proto.accuracy_in_meters
@accuracy_in_meters.setter
def accuracy_in_meters(self, value):
self.proto.accuracy_in_meters = value
@property
def speed_in_mps(self):
return self.proto.speed_in_mps
@speed_in_mps.setter
def speed_in_mps(self, value):
self.proto.speed_in_mps = value
@property
def degrees_clockwise_from_magnetic_north(self):
return self.proto.degrees_clockwise_from_magnetic_north
@degrees_clockwise_from_magnetic_north.setter
def degrees_clockwise_from_magnetic_north(self, value):
self.proto.degrees_clockwise_from_magnetic_north = value
@property
def axolotl_sender_key_distribution_message(self):
return self.proto.axolotl_sender_key_distribution_message
@axolotl_sender_key_distribution_message.setter
def axolotl_sender_key_distribution_message(self, value):
self.proto.axolotl_sender_key_distribution_message = value
@property
def jpeg_thumbnail(self):
return self.proto.jpeg_thumbnail
@jpeg_thumbnail.setter
def jpeg_thumbnail(self, value):
self.proto.jpeg_thumbnail = value
yowsup-3.2.3/yowsup/layers/protocol_media/protocolentities/test_iq_requestupload.py 0000664 0000000 0000000 00000001170 13464333726 0031351 0 ustar 00root root 0000000 0000000 from 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("encr_media", {"hash": "hash", "size": "1234", "orighash": "orighash", "type": "image"})
self.ProtocolEntity = RequestUploadIqProtocolEntity
self.node.setAttribute("type", "set")
self.node.addChild(mediaNode) yowsup-3.2.3/yowsup/layers/protocol_media/protocolentities/test_iq_requestupload_result.py 0000664 0000000 0000000 00000001113 13464333726 0032744 0 ustar 00root root 0000000 0000000 from 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("encr_media", {"url": "url", "ip": "1.2.3.4"})
self.ProtocolEntity = ResultRequestUploadIqProtocolEntity
self.node.addChild(mediaNode) yowsup-3.2.3/yowsup/layers/protocol_media/protocolentities/test_message_media.py 0000664 0000000 0000000 00000001225 13464333726 0030547 0 ustar 00root root 0000000 0000000 from yowsup.layers.protocol_media.protocolentities.message_media import MediaMessageProtocolEntity
from yowsup.layers.protocol_messages.protocolentities.test_message import MessageProtocolEntityTest
from yowsup.structs import ProtocolTreeNode
from yowsup.layers.protocol_messages.proto.e2e_pb2 import Message
class MediaMessageProtocolEntityTest(MessageProtocolEntityTest):
def setUp(self):
super(MediaMessageProtocolEntityTest, self).setUp()
self.ProtocolEntity = MediaMessageProtocolEntity
proto_node = ProtocolTreeNode("proto", {"mediatype": "image"}, None, Message().SerializeToString())
self.node.addChild(proto_node)
yowsup-3.2.3/yowsup/layers/protocol_media/protocolentities/test_message_media_contact.py 0000664 0000000 0000000 00000001531 13464333726 0032262 0 ustar 00root root 0000000 0000000 from yowsup.layers.protocol_media.protocolentities.test_message_media import MediaMessageProtocolEntityTest
from yowsup.layers.protocol_media.protocolentities import ContactMediaMessageProtocolEntity
from yowsup.layers.protocol_messages.proto.e2e_pb2 import Message
class ContactMediaMessageProtocolEntityTest(MediaMessageProtocolEntityTest):
def setUp(self):
super(ContactMediaMessageProtocolEntityTest, self).setUp()
self.ProtocolEntity = ContactMediaMessageProtocolEntity
m = Message()
contact_message = Message.ContactMessage()
contact_message.display_name = "abc"
contact_message.vcard = b"VCARD_DATA"
m.contact_message.MergeFrom(contact_message)
proto_node = self.node.getChild("proto")
proto_node["mediatype"] = "contact"
proto_node.setData(m.SerializeToString())
yowsup-3.2.3/yowsup/layers/protocol_media/protocolentities/test_message_media_downloadable_audio.py 0000664 0000000 0000000 00000001776 13464333726 0034456 0 ustar 00root root 0000000 0000000 from yowsup.layers.protocol_media.protocolentities.message_media_downloadable_audio import AudioDownloadableMediaMessageProtocolEntity
from yowsup.layers.protocol_messages.proto.e2e_pb2 import Message
from .test_message_media import MediaMessageProtocolEntityTest
class AudioDownloadableMediaMessageProtocolEntityTest(MediaMessageProtocolEntityTest):
def setUp(self):
super(AudioDownloadableMediaMessageProtocolEntityTest, self).setUp()
self.ProtocolEntity = AudioDownloadableMediaMessageProtocolEntity
proto_node = self.node.getChild("proto")
m = Message()
media_message = Message.AudioMessage()
media_message.url = "url"
media_message.mimetype = "audio/ogg"
media_message.file_sha256 = b"SHA256"
media_message.file_length = 123
media_message.media_key = b"MEDIA_KEY"
media_message.seconds = 24
media_message.ptt = True
m.audio_message.MergeFrom(media_message)
proto_node.setData(m.SerializeToString())
yowsup-3.2.3/yowsup/layers/protocol_media/protocolentities/test_message_media_downloadable_image.py 0000664 0000000 0000000 00000002142 13464333726 0034423 0 ustar 00root root 0000000 0000000 from yowsup.layers.protocol_media.protocolentities.message_media_downloadable_image \
import ImageDownloadableMediaMessageProtocolEntity
from .test_message_media import MediaMessageProtocolEntityTest
from yowsup.layers.protocol_messages.proto.e2e_pb2 import Message
class ImageDownloadableMediaMessageProtocolEntityTest(MediaMessageProtocolEntityTest):
def setUp(self):
super(ImageDownloadableMediaMessageProtocolEntityTest, self).setUp()
self.ProtocolEntity = ImageDownloadableMediaMessageProtocolEntity
proto_node = self.node.getChild("proto")
m = Message()
media_message = Message.ImageMessage()
media_message.url = "url"
media_message.mimetype = "image/jpeg"
media_message.caption = "caption"
media_message.file_sha256 = b"SHA256"
media_message.file_length = 123
media_message.height = 20
media_message.width = 20
media_message.media_key = b"MEDIA_KEY"
media_message.jpeg_thumbnail = b"THUMBNAIL"
m.image_message.MergeFrom(media_message)
proto_node.setData(m.SerializeToString())
yowsup-3.2.3/yowsup/layers/protocol_media/protocolentities/test_message_media_downloadable_video.py 0000664 0000000 0000000 00000002141 13464333726 0034446 0 ustar 00root root 0000000 0000000 from yowsup.layers.protocol_media.protocolentities.message_media_downloadable_video \
import VideoDownloadableMediaMessageProtocolEntity
from yowsup.layers.protocol_messages.proto.e2e_pb2 import Message
from .test_message_media import MediaMessageProtocolEntityTest
class VideoDownloadableMediaMessageProtocolEntityTest(MediaMessageProtocolEntityTest):
def setUp(self):
super(VideoDownloadableMediaMessageProtocolEntityTest, self).setUp()
self.ProtocolEntity = VideoDownloadableMediaMessageProtocolEntity
proto_node = self.node.getChild("proto")
m = Message()
media_message = Message.VideoMessage()
media_message.url = "url"
media_message.mimetype = "video/mp4"
media_message.caption = "caption"
media_message.file_sha256 = b"SHA256"
media_message.file_length = 123
media_message.height = 20
media_message.width = 20
media_message.media_key = b"MEDIA_KEY"
media_message.jpeg_thumbnail = b"THUMBNAIL"
m.video_message.MergeFrom(media_message)
proto_node.setData(m.SerializeToString())
yowsup-3.2.3/yowsup/layers/protocol_media/protocolentities/test_message_media_extendedtext.py 0000664 0000000 0000000 00000003076 13464333726 0033342 0 ustar 00root root 0000000 0000000 from yowsup.layers.protocol_media.protocolentities.test_message_media import MediaMessageProtocolEntityTest
from yowsup.layers.protocol_media.protocolentities import ExtendedTextMediaMessageProtocolEntity
from yowsup.layers.protocol_messages.proto.e2e_pb2 import Message
class ExtendedTextMediaMessageProtocolEntityTest(MediaMessageProtocolEntityTest):
def setUp(self):
super(ExtendedTextMediaMessageProtocolEntityTest, self).setUp()
self.ProtocolEntity = ExtendedTextMediaMessageProtocolEntity
m = Message()
media_message = Message.ExtendedTextMessage()
media_message.canonical_url = "url"
media_message.text = "text"
media_message.matched_text = "matched_text"
media_message.description = "desc"
media_message.title = "title"
media_message.jpeg_thumbnail = b"thumb"
m.extended_text_message.MergeFrom(media_message)
proto_node = self.node.getChild("proto")
proto_node["mediatype"] = "url"
proto_node.setData(m.SerializeToString())
self._entity = ExtendedTextMediaMessageProtocolEntity\
.fromProtocolTreeNode(self.node) # type: ExtendedTextMediaMessageProtocolEntity
def test_properties(self):
self.assertEqual("url", self._entity.canonical_url)
self.assertEqual("text", self._entity.text)
self.assertEqual("matched_text", self._entity.matched_text)
self.assertEqual("desc", self._entity.description)
self.assertEqual("title", self._entity.title)
self.assertEqual(b"thumb", self._entity.jpeg_thumbnail)
yowsup-3.2.3/yowsup/layers/protocol_media/protocolentities/test_message_media_location.py 0000664 0000000 0000000 00000001707 13464333726 0032444 0 ustar 00root root 0000000 0000000 from yowsup.layers.protocol_media.protocolentities.test_message_media import MediaMessageProtocolEntityTest
from yowsup.layers.protocol_media.protocolentities import LocationMediaMessageProtocolEntity
from yowsup.layers.protocol_messages.proto.e2e_pb2 import Message
class LocationMediaMessageProtocolEntityTest(MediaMessageProtocolEntityTest):
def setUp(self):
super(LocationMediaMessageProtocolEntityTest, self).setUp()
self.ProtocolEntity = LocationMediaMessageProtocolEntity
m = Message()
location_message = Message.LocationMessage()
location_message.degrees_latitude = 30.089037
location_message.degrees_longitude = 31.319488
location_message.name = "kaos"
location_message.url = "kaos_url"
m.location_message.MergeFrom(location_message)
proto_node = self.node.getChild("proto")
proto_node["mediatype"] = "location"
proto_node.setData(m.SerializeToString()) yowsup-3.2.3/yowsup/layers/protocol_media/test_mediacipher.py 0000664 0000000 0000000 00000005316 13464333726 0024635 0 ustar 00root root 0000000 0000000 from yowsup.layers.protocol_media.mediacipher import MediaCipher
import base64
import unittest
class MediaCipherTest(unittest.TestCase):
IMAGE = (
b'EOnnZIBu1vTSI51IeJvaKR+8W1FqBETATI2Ikl6nVQ8=',
b'/9j/4AAQSkZJRgABAQAAAQABAAD/2wBDAAMCAgICAgMCAgIDAwMDBAYEBAQEBAgGBgUGCQgKCgkICQkKDA8M'
b'CgsOCwkJDRENDg8QEBEQCgwSExIQEw8QEBD/2wBDAQMDAwQDBAgEBAgQCwkLEBAQEBAQEBAQEBAQEBAQEBAQ'
b'EBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBD/wAARCAABAAEDAREAAhEBAxEB/8QAHwAAAQUBAQEB'
b'AQEAAAAAAAAAAAECAwQFBgcICQoL/8QAtRAAAgEDAwIEAwUFBAQAAAF9AQIDAAQRBRIhMUEGE1FhByJxFDKB'
b'kaEII0KxwRVS0fAkM2JyggkKFhcYGRolJicoKSo0NTY3ODk6Q0RFRkdISUpTVFVWV1hZWmNkZWZnaGlqc3R1'
b'dnd4eXqDhIWGh4iJipKTlJWWl5iZmqKjpKWmp6ipqrKztLW2t7i5usLDxMXGx8jJytLT1NXW19jZ2uHi4+Tl'
b'5ufo6erx8vP09fb3+Pn6/8QAHwEAAwEBAQEBAQEBAQAAAAAAAAECAwQFBgcICQoL/8QAtREAAgECBAQDBAcF'
b'BAQAAQJ3AAECAxEEBSExBhJBUQdhcRMiMoEIFEKRobHBCSMzUvAVYnLRChYkNOEl8RcYGRomJygpKjU2Nzg5'
b'OkNERUZHSElKU1RVVldYWVpjZGVmZ2hpanN0dXZ3eHl6goOEhYaHiImKkpOUlZaXmJmaoqOkpaanqKmqsrO0'
b'tba3uLm6wsPExcbHyMnK0tPU1dbX2Nna4uPk5ebn6Onq8vP09fb3+Pn6/9oADAMBAAIRAxEAPwD9U6AP/9k'
b'==',
b'dT9YPFSz4dprkH6uiXPEVERGZVIZbGYHzwue21WoLP1RCE2wmu11M8n6ysfROPtI39DCRFQhBBEVGFCT/nfV'
b'pt+fouIENBSXY44mR2en4HGvRR//dlM5OBLz2WuEOf01iKPazGtfacy6lnV0X5JagL4r1mKeyuSXJEV81kxj'
b'Vd3OArpLKt13XM36PcnTd/U6DHOV6Vf982Wc1UjR7kMb5JT+HlWrvz9CCGMTX5mqBYWEr3InCFyrmaZu8DXC'
b'60YUZCPLTHJP0hFQA1ooKQks4f3F39tzVL3dbX3io7XPQiSgHN6nuPCD0PF7dWINep+amk+ODjeQd/o2guqx'
b'O/AngNIxfFWq3915jMQWAXeARUFw7x+9Qx93UWC/sfQ72nTqdQaH5W4vsMUKaocZcAJ7YWudKo5Y15uo3ulP'
b'744Cyo54tvxUSV0zLC90LYCe8fJefREjreO73RlVqoynTyFHuVS7/YMnesO5lCHZJ2NpHuzpGKCU08RgCuSr'
b'K/wh4SLXZ1nhZEYX/xY4cDO7swrA3Y3Qt0gjFzNBfUT9aABQaU+WHY8pBS/oVfJsuj2iod2fsW8UoplImoOk'
b'bosYlMkdZSIfwBQ5kt3On2d+HPUNt7HVZWRECFj0C4IHhZCZIJw0wFmPMOiIHyzittXGb45uJA2Sd1gnRbw0'
b'1XFuoIyvS7z0MtW0QUiD6kaJFBkpTo7hxN/HyN8xQwOkeBcKORdpeSp62iPBuRvel9I2p07it7UyYhzas+Jv'
b'tl6i+hIz6Z5nzQEZ+zPAYxDmoy4h9GQuXUivTzU9I0/Sd4QvM3rfewGeXsNSjWI1CLVZG+4wL1TPCbQGaHEB'
b'NF8zmpTMYV+NvCzv/2DwYuYoiUI='
)
def setUp(self):
self._cipher = MediaCipher() # type: MediaCipher
def test_decrypt_image(self):
media_key, media_plaintext, media_ciphertext = map(base64.b64decode, self.IMAGE)
self.assertEqual(media_plaintext, self._cipher.decrypt_image(media_ciphertext, media_key))
def test_encrypt_image(self):
media_key, media_plaintext, media_ciphertext = map(base64.b64decode, self.IMAGE)
encrypted = self._cipher.encrypt(media_plaintext, media_key, MediaCipher.INFO_IMAGE)
self.assertEqual(media_ciphertext, encrypted)
yowsup-3.2.3/yowsup/layers/protocol_messages/ 0000775 0000000 0000000 00000000000 13464333726 0021475 5 ustar 00root root 0000000 0000000 yowsup-3.2.3/yowsup/layers/protocol_messages/__init__.py 0000664 0000000 0000000 00000000054 13464333726 0023605 0 ustar 00root root 0000000 0000000 from .layer import YowMessagesProtocolLayer
yowsup-3.2.3/yowsup/layers/protocol_messages/layer.py 0000664 0000000 0000000 00000001447 13464333726 0023171 0 ustar 00root root 0000000 0000000 from yowsup.layers import 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):
protoNode = node.getChild("proto")
if protoNode:
if protoNode and protoNode["mediatype"] is None:
self.toUpper(TextMessageProtocolEntity.fromProtocolTreeNode(node))
yowsup-3.2.3/yowsup/layers/protocol_messages/proto/ 0000775 0000000 0000000 00000000000 13464333726 0022640 5 ustar 00root root 0000000 0000000 yowsup-3.2.3/yowsup/layers/protocol_messages/proto/__init__.py 0000664 0000000 0000000 00000000000 13464333726 0024737 0 ustar 00root root 0000000 0000000 yowsup-3.2.3/yowsup/layers/protocol_messages/proto/e2e_pb2.py 0000664 0000000 0000000 00000164731 13464333726 0024444 0 ustar 00root root 0000000 0000000 # Generated by the protocol buffer compiler. DO NOT EDIT!
# source: e2e.proto
import sys
_b=sys.version_info[0]<3 and (lambda x:x) or (lambda x:x.encode('latin1'))
from google.protobuf import descriptor as _descriptor
from google.protobuf import message as _message
from google.protobuf import reflection as _reflection
from google.protobuf import symbol_database as _symbol_database
# @@protoc_insertion_point(imports)
_sym_db = _symbol_database.Default()
from . import protocol_pb2 as protocol__pb2
DESCRIPTOR = _descriptor.FileDescriptor(
name='e2e.proto',
package='',
syntax='proto2',
serialized_options=None,
serialized_pb=_b('\n\te2e.proto\x1a\x0eprotocol.proto\"\xb0\x01\n\x0b\x43ontextInfo\x12\x11\n\tstanza_id\x18\x01 \x01(\t\x12\x13\n\x0bparticipant\x18\x02 \x01(\t\x12 \n\x0equoted_message\x18\x03 \x01(\x0b\x32\x08.Message\x12\x12\n\nremote_jid\x18\x04 \x01(\t\x12\x15\n\rmentioned_jid\x18\x0f \x03(\t\x12\x14\n\x0c\x65\x64it_version\x18\x10 \x01(\r\x12\x16\n\x0erevoke_message\x18\x11 \x01(\x08\"\xce\x16\n\x07Message\x12\x14\n\x0c\x63onversation\x18\x01 \x01(\t\x12N\n\x1fsender_key_distribution_message\x18\x02 \x01(\x0b\x32%.Message.SenderKeyDistributionMessage\x12,\n\rimage_message\x18\x03 \x01(\x0b\x32\x15.Message.ImageMessage\x12\x30\n\x0f\x63ontact_message\x18\x04 \x01(\x0b\x32\x17.Message.ContactMessage\x12\x32\n\x10location_message\x18\x05 \x01(\x0b\x32\x18.Message.LocationMessage\x12;\n\x15\x65xtended_text_message\x18\x06 \x01(\x0b\x32\x1c.Message.ExtendedTextMessage\x12\x32\n\x10\x64ocument_message\x18\x07 \x01(\x0b\x32\x18.Message.DocumentMessage\x12,\n\raudio_message\x18\x08 \x01(\x0b\x32\x15.Message.AudioMessage\x12,\n\rvideo_message\x18\t \x01(\x0b\x32\x15.Message.VideoMessage\x12\x1b\n\x04\x63\x61ll\x18\n \x01(\x0b\x32\r.Message.Call\x12\x1b\n\x04\x63hat\x18\x0b \x01(\x0b\x32\r.Message.Chat\x12\x32\n\x10protocol_message\x18\x0c \x01(\x0b\x32\x18.Message.ProtocolMessage\x12=\n\x16\x63ontacts_array_message\x18\r \x01(\x0b\x32\x1d.Message.ContactsArrayMessage\x12\x43\n\x19highly_structured_message\x18\x0e \x01(\x0b\x32 .Message.HighlyStructuredMessage\x1a\x61\n\x1cSenderKeyDistributionMessage\x12\x10\n\x08group_id\x18\x01 \x01(\t\x12/\n\'axolotl_sender_key_distribution_message\x18\x02 \x01(\x0c\x1a\xd6\x01\n\x0cImageMessage\x12\x0b\n\x03url\x18\x01 \x01(\t\x12\x10\n\x08mimetype\x18\x02 \x01(\t\x12\x0f\n\x07\x63\x61ption\x18\x03 \x01(\t\x12\x13\n\x0b\x66ile_sha256\x18\x04 \x01(\x0c\x12\x13\n\x0b\x66ile_length\x18\x05 \x01(\x04\x12\x0e\n\x06height\x18\x06 \x01(\r\x12\r\n\x05width\x18\x07 \x01(\r\x12\x11\n\tmedia_key\x18\x08 \x01(\x0c\x12\x16\n\x0ejpeg_thumbnail\x18\x10 \x01(\x0c\x12\"\n\x0c\x63ontext_info\x18\x11 \x01(\x0b\x32\x0c.ContextInfo\x1aY\n\x0e\x43ontactMessage\x12\x14\n\x0c\x64isplay_name\x18\x01 \x01(\t\x12\r\n\x05vcard\x18\x10 \x01(\x0c\x12\"\n\x0c\x63ontext_info\x18\x11 \x01(\x0b\x32\x0c.ContextInfo\x1a\xd2\x02\n\x0fLocationMessage\x12\x18\n\x10\x64\x65grees_latitude\x18\x01 \x01(\x01\x12\x19\n\x11\x64\x65grees_longitude\x18\x02 \x01(\x01\x12\x0c\n\x04name\x18\x03 \x01(\t\x12\x0f\n\x07\x61\x64\x64ress\x18\x04 \x01(\t\x12\x0b\n\x03url\x18\x05 \x01(\t\x12\x10\n\x08\x64uration\x18\x06 \x01(\x02\x12\x1a\n\x12\x61\x63\x63uracy_in_meters\x18\x07 \x01(\r\x12\x14\n\x0cspeed_in_mps\x18\x08 \x01(\x02\x12-\n%degrees_clockwise_from_magnetic_north\x18\t \x01(\r\x12/\n\'axolotl_sender_key_distribution_message\x18\n \x01(\x0c\x12\x16\n\x0ejpeg_thumbnail\x18\x10 \x01(\x0c\x12\"\n\x0c\x63ontext_info\x18\x11 \x01(\x0b\x32\x0c.ContextInfo\x1a\xb0\x01\n\x13\x45xtendedTextMessage\x12\x0c\n\x04text\x18\x01 \x01(\t\x12\x14\n\x0cmatched_text\x18\x02 \x01(\t\x12\x15\n\rcanonical_url\x18\x04 \x01(\t\x12\x13\n\x0b\x64\x65scription\x18\x05 \x01(\t\x12\r\n\x05title\x18\x06 \x01(\t\x12\x16\n\x0ejpeg_thumbnail\x18\x10 \x01(\x0c\x12\"\n\x0c\x63ontext_info\x18\x11 \x01(\x0b\x32\x0c.ContextInfo\x1a\xdf\x01\n\x0f\x44ocumentMessage\x12\x0b\n\x03url\x18\x01 \x01(\t\x12\x10\n\x08mimetype\x18\x02 \x01(\t\x12\r\n\x05title\x18\x03 \x01(\t\x12\x13\n\x0b\x66ile_sha256\x18\x04 \x01(\x0c\x12\x13\n\x0b\x66ile_length\x18\x05 \x01(\x04\x12\x12\n\npage_count\x18\x06 \x01(\r\x12\x11\n\tmedia_key\x18\x07 \x01(\x0c\x12\x11\n\tfile_name\x18\x08 \x01(\t\x12\x16\n\x0ejpeg_thumbnail\x18\x10 \x01(\x0c\x12\"\n\x0c\x63ontext_info\x18\x11 \x01(\x0b\x32\x0c.ContextInfo\x1a\xc7\x01\n\x0c\x41udioMessage\x12\x0b\n\x03url\x18\x01 \x01(\t\x12\x10\n\x08mimetype\x18\x02 \x01(\t\x12\x13\n\x0b\x66ile_sha256\x18\x03 \x01(\x0c\x12\x13\n\x0b\x66ile_length\x18\x04 \x01(\x04\x12\x0f\n\x07seconds\x18\x05 \x01(\r\x12\x0b\n\x03ptt\x18\x06 \x01(\x08\x12\x11\n\tmedia_key\x18\x07 \x01(\x0c\x12\"\n\x0c\x63ontext_info\x18\x11 \x01(\x0b\x32\x0c.ContextInfo\x12\x19\n\x11streaming_sidecar\x18\x12 \x01(\x0c\x1a\x89\x03\n\x0cVideoMessage\x12\x0b\n\x03url\x18\x01 \x01(\t\x12\x10\n\x08mimetype\x18\x02 \x01(\t\x12\x13\n\x0b\x66ile_sha256\x18\x03 \x01(\x0c\x12\x13\n\x0b\x66ile_length\x18\x04 \x01(\x04\x12\x0f\n\x07seconds\x18\x05 \x01(\r\x12\x11\n\tmedia_key\x18\x06 \x01(\x0c\x12\x0f\n\x07\x63\x61ption\x18\x07 \x01(\t\x12\x14\n\x0cgif_playback\x18\x08 \x01(\x08\x12\x0e\n\x06height\x18\t \x01(\r\x12\r\n\x05width\x18\n \x01(\r\x12\x16\n\x0ejpeg_thumbnail\x18\x10 \x01(\x0c\x12\"\n\x0c\x63ontext_info\x18\x11 \x01(\x0b\x32\x0c.ContextInfo\x12\x19\n\x11streaming_sidecar\x18\x12 \x01(\x0c\x12@\n\x0fgif_attribution\x18\x13 \x01(\x0e\x32!.Message.VideoMessage.Attribution:\x04NONE\"-\n\x0b\x41ttribution\x12\x08\n\x04NONE\x10\x00\x12\t\n\x05GIPHY\x10\x01\x12\t\n\x05TENOR\x10\x02\x1a\x18\n\x04\x43\x61ll\x12\x10\n\x08\x63\x61ll_key\x18\x01 \x01(\x0c\x1a(\n\x04\x43hat\x12\x14\n\x0c\x64isplay_name\x18\x01 \x01(\t\x12\n\n\x02id\x18\x02 \x01(\t\x1at\n\x0fProtocolMessage\x12\x18\n\x03key\x18\x01 \x01(\x0b\x32\x0b.MessageKey\x12\x33\n\x04type\x18\x02 \x01(\x0e\x32\x1d.Message.ProtocolMessage.Type:\x06REVOKE\"\x12\n\x04Type\x12\n\n\x06REVOKE\x10\x00\x1a{\n\x14\x43ontactsArrayMessage\x12\x14\n\x0c\x64isplay_name\x18\x01 \x01(\t\x12)\n\x08\x63ontacts\x18\x02 \x03(\x0b\x32\x17.Message.ContactMessage\x12\"\n\x0c\x63ontext_info\x18\x11 \x01(\x0b\x32\x0c.ContextInfo\x1a|\n\x17HighlyStructuredMessage\x12\x11\n\tnamespace\x18\x01 \x01(\t\x12\x14\n\x0c\x65lement_name\x18\x02 \x01(\t\x12\x0e\n\x06params\x18\x03 \x03(\t\x12\x13\n\x0b\x66\x61llback_lg\x18\x04 \x01(\t\x12\x13\n\x0b\x66\x61llback_lc\x18\x05 \x01(\t')
,
dependencies=[protocol__pb2.DESCRIPTOR,])
_MESSAGE_VIDEOMESSAGE_ATTRIBUTION = _descriptor.EnumDescriptor(
name='Attribution',
full_name='Message.VideoMessage.Attribution',
filename=None,
file=DESCRIPTOR,
values=[
_descriptor.EnumValueDescriptor(
name='NONE', index=0, number=0,
serialized_options=None,
type=None),
_descriptor.EnumValueDescriptor(
name='GIPHY', index=1, number=1,
serialized_options=None,
type=None),
_descriptor.EnumValueDescriptor(
name='TENOR', index=2, number=2,
serialized_options=None,
type=None),
],
containing_type=None,
serialized_options=None,
serialized_start=2621,
serialized_end=2666,
)
_sym_db.RegisterEnumDescriptor(_MESSAGE_VIDEOMESSAGE_ATTRIBUTION)
_MESSAGE_PROTOCOLMESSAGE_TYPE = _descriptor.EnumDescriptor(
name='Type',
full_name='Message.ProtocolMessage.Type',
filename=None,
file=DESCRIPTOR,
values=[
_descriptor.EnumValueDescriptor(
name='REVOKE', index=0, number=0,
serialized_options=None,
type=None),
],
containing_type=None,
serialized_options=None,
serialized_start=2834,
serialized_end=2852,
)
_sym_db.RegisterEnumDescriptor(_MESSAGE_PROTOCOLMESSAGE_TYPE)
_CONTEXTINFO = _descriptor.Descriptor(
name='ContextInfo',
full_name='ContextInfo',
filename=None,
file=DESCRIPTOR,
containing_type=None,
fields=[
_descriptor.FieldDescriptor(
name='stanza_id', full_name='ContextInfo.stanza_id', index=0,
number=1, type=9, cpp_type=9, label=1,
has_default_value=False, default_value=_b("").decode('utf-8'),
message_type=None, enum_type=None, containing_type=None,
is_extension=False, extension_scope=None,
serialized_options=None, file=DESCRIPTOR),
_descriptor.FieldDescriptor(
name='participant', full_name='ContextInfo.participant', index=1,
number=2, type=9, cpp_type=9, label=1,
has_default_value=False, default_value=_b("").decode('utf-8'),
message_type=None, enum_type=None, containing_type=None,
is_extension=False, extension_scope=None,
serialized_options=None, file=DESCRIPTOR),
_descriptor.FieldDescriptor(
name='quoted_message', full_name='ContextInfo.quoted_message', index=2,
number=3, type=11, cpp_type=10, label=1,
has_default_value=False, default_value=None,
message_type=None, enum_type=None, containing_type=None,
is_extension=False, extension_scope=None,
serialized_options=None, file=DESCRIPTOR),
_descriptor.FieldDescriptor(
name='remote_jid', full_name='ContextInfo.remote_jid', index=3,
number=4, type=9, cpp_type=9, label=1,
has_default_value=False, default_value=_b("").decode('utf-8'),
message_type=None, enum_type=None, containing_type=None,
is_extension=False, extension_scope=None,
serialized_options=None, file=DESCRIPTOR),
_descriptor.FieldDescriptor(
name='mentioned_jid', full_name='ContextInfo.mentioned_jid', index=4,
number=15, type=9, cpp_type=9, label=3,
has_default_value=False, default_value=[],
message_type=None, enum_type=None, containing_type=None,
is_extension=False, extension_scope=None,
serialized_options=None, file=DESCRIPTOR),
_descriptor.FieldDescriptor(
name='edit_version', full_name='ContextInfo.edit_version', index=5,
number=16, type=13, cpp_type=3, label=1,
has_default_value=False, default_value=0,
message_type=None, enum_type=None, containing_type=None,
is_extension=False, extension_scope=None,
serialized_options=None, file=DESCRIPTOR),
_descriptor.FieldDescriptor(
name='revoke_message', full_name='ContextInfo.revoke_message', index=6,
number=17, type=8, cpp_type=7, label=1,
has_default_value=False, default_value=False,
message_type=None, enum_type=None, containing_type=None,
is_extension=False, extension_scope=None,
serialized_options=None, file=DESCRIPTOR),
],
extensions=[
],
nested_types=[],
enum_types=[
],
serialized_options=None,
is_extendable=False,
syntax='proto2',
extension_ranges=[],
oneofs=[
],
serialized_start=30,
serialized_end=206,
)
_MESSAGE_SENDERKEYDISTRIBUTIONMESSAGE = _descriptor.Descriptor(
name='SenderKeyDistributionMessage',
full_name='Message.SenderKeyDistributionMessage',
filename=None,
file=DESCRIPTOR,
containing_type=None,
fields=[
_descriptor.FieldDescriptor(
name='group_id', full_name='Message.SenderKeyDistributionMessage.group_id', index=0,
number=1, type=9, cpp_type=9, label=1,
has_default_value=False, default_value=_b("").decode('utf-8'),
message_type=None, enum_type=None, containing_type=None,
is_extension=False, extension_scope=None,
serialized_options=None, file=DESCRIPTOR),
_descriptor.FieldDescriptor(
name='axolotl_sender_key_distribution_message', full_name='Message.SenderKeyDistributionMessage.axolotl_sender_key_distribution_message', index=1,
number=2, type=12, cpp_type=9, label=1,
has_default_value=False, default_value=_b(""),
message_type=None, enum_type=None, containing_type=None,
is_extension=False, extension_scope=None,
serialized_options=None, file=DESCRIPTOR),
],
extensions=[
],
nested_types=[],
enum_types=[
],
serialized_options=None,
is_extendable=False,
syntax='proto2',
extension_ranges=[],
oneofs=[
],
serialized_start=917,
serialized_end=1014,
)
_MESSAGE_IMAGEMESSAGE = _descriptor.Descriptor(
name='ImageMessage',
full_name='Message.ImageMessage',
filename=None,
file=DESCRIPTOR,
containing_type=None,
fields=[
_descriptor.FieldDescriptor(
name='url', full_name='Message.ImageMessage.url', index=0,
number=1, type=9, cpp_type=9, label=1,
has_default_value=False, default_value=_b("").decode('utf-8'),
message_type=None, enum_type=None, containing_type=None,
is_extension=False, extension_scope=None,
serialized_options=None, file=DESCRIPTOR),
_descriptor.FieldDescriptor(
name='mimetype', full_name='Message.ImageMessage.mimetype', index=1,
number=2, type=9, cpp_type=9, label=1,
has_default_value=False, default_value=_b("").decode('utf-8'),
message_type=None, enum_type=None, containing_type=None,
is_extension=False, extension_scope=None,
serialized_options=None, file=DESCRIPTOR),
_descriptor.FieldDescriptor(
name='caption', full_name='Message.ImageMessage.caption', index=2,
number=3, type=9, cpp_type=9, label=1,
has_default_value=False, default_value=_b("").decode('utf-8'),
message_type=None, enum_type=None, containing_type=None,
is_extension=False, extension_scope=None,
serialized_options=None, file=DESCRIPTOR),
_descriptor.FieldDescriptor(
name='file_sha256', full_name='Message.ImageMessage.file_sha256', index=3,
number=4, type=12, cpp_type=9, label=1,
has_default_value=False, default_value=_b(""),
message_type=None, enum_type=None, containing_type=None,
is_extension=False, extension_scope=None,
serialized_options=None, file=DESCRIPTOR),
_descriptor.FieldDescriptor(
name='file_length', full_name='Message.ImageMessage.file_length', index=4,
number=5, type=4, cpp_type=4, label=1,
has_default_value=False, default_value=0,
message_type=None, enum_type=None, containing_type=None,
is_extension=False, extension_scope=None,
serialized_options=None, file=DESCRIPTOR),
_descriptor.FieldDescriptor(
name='height', full_name='Message.ImageMessage.height', index=5,
number=6, type=13, cpp_type=3, label=1,
has_default_value=False, default_value=0,
message_type=None, enum_type=None, containing_type=None,
is_extension=False, extension_scope=None,
serialized_options=None, file=DESCRIPTOR),
_descriptor.FieldDescriptor(
name='width', full_name='Message.ImageMessage.width', index=6,
number=7, type=13, cpp_type=3, label=1,
has_default_value=False, default_value=0,
message_type=None, enum_type=None, containing_type=None,
is_extension=False, extension_scope=None,
serialized_options=None, file=DESCRIPTOR),
_descriptor.FieldDescriptor(
name='media_key', full_name='Message.ImageMessage.media_key', index=7,
number=8, type=12, cpp_type=9, label=1,
has_default_value=False, default_value=_b(""),
message_type=None, enum_type=None, containing_type=None,
is_extension=False, extension_scope=None,
serialized_options=None, file=DESCRIPTOR),
_descriptor.FieldDescriptor(
name='jpeg_thumbnail', full_name='Message.ImageMessage.jpeg_thumbnail', index=8,
number=16, type=12, cpp_type=9, label=1,
has_default_value=False, default_value=_b(""),
message_type=None, enum_type=None, containing_type=None,
is_extension=False, extension_scope=None,
serialized_options=None, file=DESCRIPTOR),
_descriptor.FieldDescriptor(
name='context_info', full_name='Message.ImageMessage.context_info', index=9,
number=17, type=11, cpp_type=10, label=1,
has_default_value=False, default_value=None,
message_type=None, enum_type=None, containing_type=None,
is_extension=False, extension_scope=None,
serialized_options=None, file=DESCRIPTOR),
],
extensions=[
],
nested_types=[],
enum_types=[
],
serialized_options=None,
is_extendable=False,
syntax='proto2',
extension_ranges=[],
oneofs=[
],
serialized_start=1017,
serialized_end=1231,
)
_MESSAGE_CONTACTMESSAGE = _descriptor.Descriptor(
name='ContactMessage',
full_name='Message.ContactMessage',
filename=None,
file=DESCRIPTOR,
containing_type=None,
fields=[
_descriptor.FieldDescriptor(
name='display_name', full_name='Message.ContactMessage.display_name', index=0,
number=1, type=9, cpp_type=9, label=1,
has_default_value=False, default_value=_b("").decode('utf-8'),
message_type=None, enum_type=None, containing_type=None,
is_extension=False, extension_scope=None,
serialized_options=None, file=DESCRIPTOR),
_descriptor.FieldDescriptor(
name='vcard', full_name='Message.ContactMessage.vcard', index=1,
number=16, type=12, cpp_type=9, label=1,
has_default_value=False, default_value=_b(""),
message_type=None, enum_type=None, containing_type=None,
is_extension=False, extension_scope=None,
serialized_options=None, file=DESCRIPTOR),
_descriptor.FieldDescriptor(
name='context_info', full_name='Message.ContactMessage.context_info', index=2,
number=17, type=11, cpp_type=10, label=1,
has_default_value=False, default_value=None,
message_type=None, enum_type=None, containing_type=None,
is_extension=False, extension_scope=None,
serialized_options=None, file=DESCRIPTOR),
],
extensions=[
],
nested_types=[],
enum_types=[
],
serialized_options=None,
is_extendable=False,
syntax='proto2',
extension_ranges=[],
oneofs=[
],
serialized_start=1233,
serialized_end=1322,
)
_MESSAGE_LOCATIONMESSAGE = _descriptor.Descriptor(
name='LocationMessage',
full_name='Message.LocationMessage',
filename=None,
file=DESCRIPTOR,
containing_type=None,
fields=[
_descriptor.FieldDescriptor(
name='degrees_latitude', full_name='Message.LocationMessage.degrees_latitude', index=0,
number=1, type=1, cpp_type=5, label=1,
has_default_value=False, default_value=float(0),
message_type=None, enum_type=None, containing_type=None,
is_extension=False, extension_scope=None,
serialized_options=None, file=DESCRIPTOR),
_descriptor.FieldDescriptor(
name='degrees_longitude', full_name='Message.LocationMessage.degrees_longitude', index=1,
number=2, type=1, cpp_type=5, label=1,
has_default_value=False, default_value=float(0),
message_type=None, enum_type=None, containing_type=None,
is_extension=False, extension_scope=None,
serialized_options=None, file=DESCRIPTOR),
_descriptor.FieldDescriptor(
name='name', full_name='Message.LocationMessage.name', index=2,
number=3, type=9, cpp_type=9, label=1,
has_default_value=False, default_value=_b("").decode('utf-8'),
message_type=None, enum_type=None, containing_type=None,
is_extension=False, extension_scope=None,
serialized_options=None, file=DESCRIPTOR),
_descriptor.FieldDescriptor(
name='address', full_name='Message.LocationMessage.address', index=3,
number=4, type=9, cpp_type=9, label=1,
has_default_value=False, default_value=_b("").decode('utf-8'),
message_type=None, enum_type=None, containing_type=None,
is_extension=False, extension_scope=None,
serialized_options=None, file=DESCRIPTOR),
_descriptor.FieldDescriptor(
name='url', full_name='Message.LocationMessage.url', index=4,
number=5, type=9, cpp_type=9, label=1,
has_default_value=False, default_value=_b("").decode('utf-8'),
message_type=None, enum_type=None, containing_type=None,
is_extension=False, extension_scope=None,
serialized_options=None, file=DESCRIPTOR),
_descriptor.FieldDescriptor(
name='duration', full_name='Message.LocationMessage.duration', index=5,
number=6, type=2, cpp_type=6, label=1,
has_default_value=False, default_value=float(0),
message_type=None, enum_type=None, containing_type=None,
is_extension=False, extension_scope=None,
serialized_options=None, file=DESCRIPTOR),
_descriptor.FieldDescriptor(
name='accuracy_in_meters', full_name='Message.LocationMessage.accuracy_in_meters', index=6,
number=7, type=13, cpp_type=3, label=1,
has_default_value=False, default_value=0,
message_type=None, enum_type=None, containing_type=None,
is_extension=False, extension_scope=None,
serialized_options=None, file=DESCRIPTOR),
_descriptor.FieldDescriptor(
name='speed_in_mps', full_name='Message.LocationMessage.speed_in_mps', index=7,
number=8, type=2, cpp_type=6, label=1,
has_default_value=False, default_value=float(0),
message_type=None, enum_type=None, containing_type=None,
is_extension=False, extension_scope=None,
serialized_options=None, file=DESCRIPTOR),
_descriptor.FieldDescriptor(
name='degrees_clockwise_from_magnetic_north', full_name='Message.LocationMessage.degrees_clockwise_from_magnetic_north', index=8,
number=9, type=13, cpp_type=3, label=1,
has_default_value=False, default_value=0,
message_type=None, enum_type=None, containing_type=None,
is_extension=False, extension_scope=None,
serialized_options=None, file=DESCRIPTOR),
_descriptor.FieldDescriptor(
name='axolotl_sender_key_distribution_message', full_name='Message.LocationMessage.axolotl_sender_key_distribution_message', index=9,
number=10, type=12, cpp_type=9, label=1,
has_default_value=False, default_value=_b(""),
message_type=None, enum_type=None, containing_type=None,
is_extension=False, extension_scope=None,
serialized_options=None, file=DESCRIPTOR),
_descriptor.FieldDescriptor(
name='jpeg_thumbnail', full_name='Message.LocationMessage.jpeg_thumbnail', index=10,
number=16, type=12, cpp_type=9, label=1,
has_default_value=False, default_value=_b(""),
message_type=None, enum_type=None, containing_type=None,
is_extension=False, extension_scope=None,
serialized_options=None, file=DESCRIPTOR),
_descriptor.FieldDescriptor(
name='context_info', full_name='Message.LocationMessage.context_info', index=11,
number=17, type=11, cpp_type=10, label=1,
has_default_value=False, default_value=None,
message_type=None, enum_type=None, containing_type=None,
is_extension=False, extension_scope=None,
serialized_options=None, file=DESCRIPTOR),
],
extensions=[
],
nested_types=[],
enum_types=[
],
serialized_options=None,
is_extendable=False,
syntax='proto2',
extension_ranges=[],
oneofs=[
],
serialized_start=1325,
serialized_end=1663,
)
_MESSAGE_EXTENDEDTEXTMESSAGE = _descriptor.Descriptor(
name='ExtendedTextMessage',
full_name='Message.ExtendedTextMessage',
filename=None,
file=DESCRIPTOR,
containing_type=None,
fields=[
_descriptor.FieldDescriptor(
name='text', full_name='Message.ExtendedTextMessage.text', index=0,
number=1, type=9, cpp_type=9, label=1,
has_default_value=False, default_value=_b("").decode('utf-8'),
message_type=None, enum_type=None, containing_type=None,
is_extension=False, extension_scope=None,
serialized_options=None, file=DESCRIPTOR),
_descriptor.FieldDescriptor(
name='matched_text', full_name='Message.ExtendedTextMessage.matched_text', index=1,
number=2, type=9, cpp_type=9, label=1,
has_default_value=False, default_value=_b("").decode('utf-8'),
message_type=None, enum_type=None, containing_type=None,
is_extension=False, extension_scope=None,
serialized_options=None, file=DESCRIPTOR),
_descriptor.FieldDescriptor(
name='canonical_url', full_name='Message.ExtendedTextMessage.canonical_url', index=2,
number=4, type=9, cpp_type=9, label=1,
has_default_value=False, default_value=_b("").decode('utf-8'),
message_type=None, enum_type=None, containing_type=None,
is_extension=False, extension_scope=None,
serialized_options=None, file=DESCRIPTOR),
_descriptor.FieldDescriptor(
name='description', full_name='Message.ExtendedTextMessage.description', index=3,
number=5, type=9, cpp_type=9, label=1,
has_default_value=False, default_value=_b("").decode('utf-8'),
message_type=None, enum_type=None, containing_type=None,
is_extension=False, extension_scope=None,
serialized_options=None, file=DESCRIPTOR),
_descriptor.FieldDescriptor(
name='title', full_name='Message.ExtendedTextMessage.title', index=4,
number=6, type=9, cpp_type=9, label=1,
has_default_value=False, default_value=_b("").decode('utf-8'),
message_type=None, enum_type=None, containing_type=None,
is_extension=False, extension_scope=None,
serialized_options=None, file=DESCRIPTOR),
_descriptor.FieldDescriptor(
name='jpeg_thumbnail', full_name='Message.ExtendedTextMessage.jpeg_thumbnail', index=5,
number=16, type=12, cpp_type=9, label=1,
has_default_value=False, default_value=_b(""),
message_type=None, enum_type=None, containing_type=None,
is_extension=False, extension_scope=None,
serialized_options=None, file=DESCRIPTOR),
_descriptor.FieldDescriptor(
name='context_info', full_name='Message.ExtendedTextMessage.context_info', index=6,
number=17, type=11, cpp_type=10, label=1,
has_default_value=False, default_value=None,
message_type=None, enum_type=None, containing_type=None,
is_extension=False, extension_scope=None,
serialized_options=None, file=DESCRIPTOR),
],
extensions=[
],
nested_types=[],
enum_types=[
],
serialized_options=None,
is_extendable=False,
syntax='proto2',
extension_ranges=[],
oneofs=[
],
serialized_start=1666,
serialized_end=1842,
)
_MESSAGE_DOCUMENTMESSAGE = _descriptor.Descriptor(
name='DocumentMessage',
full_name='Message.DocumentMessage',
filename=None,
file=DESCRIPTOR,
containing_type=None,
fields=[
_descriptor.FieldDescriptor(
name='url', full_name='Message.DocumentMessage.url', index=0,
number=1, type=9, cpp_type=9, label=1,
has_default_value=False, default_value=_b("").decode('utf-8'),
message_type=None, enum_type=None, containing_type=None,
is_extension=False, extension_scope=None,
serialized_options=None, file=DESCRIPTOR),
_descriptor.FieldDescriptor(
name='mimetype', full_name='Message.DocumentMessage.mimetype', index=1,
number=2, type=9, cpp_type=9, label=1,
has_default_value=False, default_value=_b("").decode('utf-8'),
message_type=None, enum_type=None, containing_type=None,
is_extension=False, extension_scope=None,
serialized_options=None, file=DESCRIPTOR),
_descriptor.FieldDescriptor(
name='title', full_name='Message.DocumentMessage.title', index=2,
number=3, type=9, cpp_type=9, label=1,
has_default_value=False, default_value=_b("").decode('utf-8'),
message_type=None, enum_type=None, containing_type=None,
is_extension=False, extension_scope=None,
serialized_options=None, file=DESCRIPTOR),
_descriptor.FieldDescriptor(
name='file_sha256', full_name='Message.DocumentMessage.file_sha256', index=3,
number=4, type=12, cpp_type=9, label=1,
has_default_value=False, default_value=_b(""),
message_type=None, enum_type=None, containing_type=None,
is_extension=False, extension_scope=None,
serialized_options=None, file=DESCRIPTOR),
_descriptor.FieldDescriptor(
name='file_length', full_name='Message.DocumentMessage.file_length', index=4,
number=5, type=4, cpp_type=4, label=1,
has_default_value=False, default_value=0,
message_type=None, enum_type=None, containing_type=None,
is_extension=False, extension_scope=None,
serialized_options=None, file=DESCRIPTOR),
_descriptor.FieldDescriptor(
name='page_count', full_name='Message.DocumentMessage.page_count', index=5,
number=6, type=13, cpp_type=3, label=1,
has_default_value=False, default_value=0,
message_type=None, enum_type=None, containing_type=None,
is_extension=False, extension_scope=None,
serialized_options=None, file=DESCRIPTOR),
_descriptor.FieldDescriptor(
name='media_key', full_name='Message.DocumentMessage.media_key', index=6,
number=7, type=12, cpp_type=9, label=1,
has_default_value=False, default_value=_b(""),
message_type=None, enum_type=None, containing_type=None,
is_extension=False, extension_scope=None,
serialized_options=None, file=DESCRIPTOR),
_descriptor.FieldDescriptor(
name='file_name', full_name='Message.DocumentMessage.file_name', index=7,
number=8, type=9, cpp_type=9, label=1,
has_default_value=False, default_value=_b("").decode('utf-8'),
message_type=None, enum_type=None, containing_type=None,
is_extension=False, extension_scope=None,
serialized_options=None, file=DESCRIPTOR),
_descriptor.FieldDescriptor(
name='jpeg_thumbnail', full_name='Message.DocumentMessage.jpeg_thumbnail', index=8,
number=16, type=12, cpp_type=9, label=1,
has_default_value=False, default_value=_b(""),
message_type=None, enum_type=None, containing_type=None,
is_extension=False, extension_scope=None,
serialized_options=None, file=DESCRIPTOR),
_descriptor.FieldDescriptor(
name='context_info', full_name='Message.DocumentMessage.context_info', index=9,
number=17, type=11, cpp_type=10, label=1,
has_default_value=False, default_value=None,
message_type=None, enum_type=None, containing_type=None,
is_extension=False, extension_scope=None,
serialized_options=None, file=DESCRIPTOR),
],
extensions=[
],
nested_types=[],
enum_types=[
],
serialized_options=None,
is_extendable=False,
syntax='proto2',
extension_ranges=[],
oneofs=[
],
serialized_start=1845,
serialized_end=2068,
)
_MESSAGE_AUDIOMESSAGE = _descriptor.Descriptor(
name='AudioMessage',
full_name='Message.AudioMessage',
filename=None,
file=DESCRIPTOR,
containing_type=None,
fields=[
_descriptor.FieldDescriptor(
name='url', full_name='Message.AudioMessage.url', index=0,
number=1, type=9, cpp_type=9, label=1,
has_default_value=False, default_value=_b("").decode('utf-8'),
message_type=None, enum_type=None, containing_type=None,
is_extension=False, extension_scope=None,
serialized_options=None, file=DESCRIPTOR),
_descriptor.FieldDescriptor(
name='mimetype', full_name='Message.AudioMessage.mimetype', index=1,
number=2, type=9, cpp_type=9, label=1,
has_default_value=False, default_value=_b("").decode('utf-8'),
message_type=None, enum_type=None, containing_type=None,
is_extension=False, extension_scope=None,
serialized_options=None, file=DESCRIPTOR),
_descriptor.FieldDescriptor(
name='file_sha256', full_name='Message.AudioMessage.file_sha256', index=2,
number=3, type=12, cpp_type=9, label=1,
has_default_value=False, default_value=_b(""),
message_type=None, enum_type=None, containing_type=None,
is_extension=False, extension_scope=None,
serialized_options=None, file=DESCRIPTOR),
_descriptor.FieldDescriptor(
name='file_length', full_name='Message.AudioMessage.file_length', index=3,
number=4, type=4, cpp_type=4, label=1,
has_default_value=False, default_value=0,
message_type=None, enum_type=None, containing_type=None,
is_extension=False, extension_scope=None,
serialized_options=None, file=DESCRIPTOR),
_descriptor.FieldDescriptor(
name='seconds', full_name='Message.AudioMessage.seconds', index=4,
number=5, type=13, cpp_type=3, label=1,
has_default_value=False, default_value=0,
message_type=None, enum_type=None, containing_type=None,
is_extension=False, extension_scope=None,
serialized_options=None, file=DESCRIPTOR),
_descriptor.FieldDescriptor(
name='ptt', full_name='Message.AudioMessage.ptt', index=5,
number=6, type=8, cpp_type=7, label=1,
has_default_value=False, default_value=False,
message_type=None, enum_type=None, containing_type=None,
is_extension=False, extension_scope=None,
serialized_options=None, file=DESCRIPTOR),
_descriptor.FieldDescriptor(
name='media_key', full_name='Message.AudioMessage.media_key', index=6,
number=7, type=12, cpp_type=9, label=1,
has_default_value=False, default_value=_b(""),
message_type=None, enum_type=None, containing_type=None,
is_extension=False, extension_scope=None,
serialized_options=None, file=DESCRIPTOR),
_descriptor.FieldDescriptor(
name='context_info', full_name='Message.AudioMessage.context_info', index=7,
number=17, type=11, cpp_type=10, label=1,
has_default_value=False, default_value=None,
message_type=None, enum_type=None, containing_type=None,
is_extension=False, extension_scope=None,
serialized_options=None, file=DESCRIPTOR),
_descriptor.FieldDescriptor(
name='streaming_sidecar', full_name='Message.AudioMessage.streaming_sidecar', index=8,
number=18, type=12, cpp_type=9, label=1,
has_default_value=False, default_value=_b(""),
message_type=None, enum_type=None, containing_type=None,
is_extension=False, extension_scope=None,
serialized_options=None, file=DESCRIPTOR),
],
extensions=[
],
nested_types=[],
enum_types=[
],
serialized_options=None,
is_extendable=False,
syntax='proto2',
extension_ranges=[],
oneofs=[
],
serialized_start=2071,
serialized_end=2270,
)
_MESSAGE_VIDEOMESSAGE = _descriptor.Descriptor(
name='VideoMessage',
full_name='Message.VideoMessage',
filename=None,
file=DESCRIPTOR,
containing_type=None,
fields=[
_descriptor.FieldDescriptor(
name='url', full_name='Message.VideoMessage.url', index=0,
number=1, type=9, cpp_type=9, label=1,
has_default_value=False, default_value=_b("").decode('utf-8'),
message_type=None, enum_type=None, containing_type=None,
is_extension=False, extension_scope=None,
serialized_options=None, file=DESCRIPTOR),
_descriptor.FieldDescriptor(
name='mimetype', full_name='Message.VideoMessage.mimetype', index=1,
number=2, type=9, cpp_type=9, label=1,
has_default_value=False, default_value=_b("").decode('utf-8'),
message_type=None, enum_type=None, containing_type=None,
is_extension=False, extension_scope=None,
serialized_options=None, file=DESCRIPTOR),
_descriptor.FieldDescriptor(
name='file_sha256', full_name='Message.VideoMessage.file_sha256', index=2,
number=3, type=12, cpp_type=9, label=1,
has_default_value=False, default_value=_b(""),
message_type=None, enum_type=None, containing_type=None,
is_extension=False, extension_scope=None,
serialized_options=None, file=DESCRIPTOR),
_descriptor.FieldDescriptor(
name='file_length', full_name='Message.VideoMessage.file_length', index=3,
number=4, type=4, cpp_type=4, label=1,
has_default_value=False, default_value=0,
message_type=None, enum_type=None, containing_type=None,
is_extension=False, extension_scope=None,
serialized_options=None, file=DESCRIPTOR),
_descriptor.FieldDescriptor(
name='seconds', full_name='Message.VideoMessage.seconds', index=4,
number=5, type=13, cpp_type=3, label=1,
has_default_value=False, default_value=0,
message_type=None, enum_type=None, containing_type=None,
is_extension=False, extension_scope=None,
serialized_options=None, file=DESCRIPTOR),
_descriptor.FieldDescriptor(
name='media_key', full_name='Message.VideoMessage.media_key', index=5,
number=6, type=12, cpp_type=9, label=1,
has_default_value=False, default_value=_b(""),
message_type=None, enum_type=None, containing_type=None,
is_extension=False, extension_scope=None,
serialized_options=None, file=DESCRIPTOR),
_descriptor.FieldDescriptor(
name='caption', full_name='Message.VideoMessage.caption', index=6,
number=7, type=9, cpp_type=9, label=1,
has_default_value=False, default_value=_b("").decode('utf-8'),
message_type=None, enum_type=None, containing_type=None,
is_extension=False, extension_scope=None,
serialized_options=None, file=DESCRIPTOR),
_descriptor.FieldDescriptor(
name='gif_playback', full_name='Message.VideoMessage.gif_playback', index=7,
number=8, type=8, cpp_type=7, label=1,
has_default_value=False, default_value=False,
message_type=None, enum_type=None, containing_type=None,
is_extension=False, extension_scope=None,
serialized_options=None, file=DESCRIPTOR),
_descriptor.FieldDescriptor(
name='height', full_name='Message.VideoMessage.height', index=8,
number=9, type=13, cpp_type=3, label=1,
has_default_value=False, default_value=0,
message_type=None, enum_type=None, containing_type=None,
is_extension=False, extension_scope=None,
serialized_options=None, file=DESCRIPTOR),
_descriptor.FieldDescriptor(
name='width', full_name='Message.VideoMessage.width', index=9,
number=10, type=13, cpp_type=3, label=1,
has_default_value=False, default_value=0,
message_type=None, enum_type=None, containing_type=None,
is_extension=False, extension_scope=None,
serialized_options=None, file=DESCRIPTOR),
_descriptor.FieldDescriptor(
name='jpeg_thumbnail', full_name='Message.VideoMessage.jpeg_thumbnail', index=10,
number=16, type=12, cpp_type=9, label=1,
has_default_value=False, default_value=_b(""),
message_type=None, enum_type=None, containing_type=None,
is_extension=False, extension_scope=None,
serialized_options=None, file=DESCRIPTOR),
_descriptor.FieldDescriptor(
name='context_info', full_name='Message.VideoMessage.context_info', index=11,
number=17, type=11, cpp_type=10, label=1,
has_default_value=False, default_value=None,
message_type=None, enum_type=None, containing_type=None,
is_extension=False, extension_scope=None,
serialized_options=None, file=DESCRIPTOR),
_descriptor.FieldDescriptor(
name='streaming_sidecar', full_name='Message.VideoMessage.streaming_sidecar', index=12,
number=18, type=12, cpp_type=9, label=1,
has_default_value=False, default_value=_b(""),
message_type=None, enum_type=None, containing_type=None,
is_extension=False, extension_scope=None,
serialized_options=None, file=DESCRIPTOR),
_descriptor.FieldDescriptor(
name='gif_attribution', full_name='Message.VideoMessage.gif_attribution', index=13,
number=19, type=14, cpp_type=8, label=1,
has_default_value=True, default_value=0,
message_type=None, enum_type=None, containing_type=None,
is_extension=False, extension_scope=None,
serialized_options=None, file=DESCRIPTOR),
],
extensions=[
],
nested_types=[],
enum_types=[
_MESSAGE_VIDEOMESSAGE_ATTRIBUTION,
],
serialized_options=None,
is_extendable=False,
syntax='proto2',
extension_ranges=[],
oneofs=[
],
serialized_start=2273,
serialized_end=2666,
)
_MESSAGE_CALL = _descriptor.Descriptor(
name='Call',
full_name='Message.Call',
filename=None,
file=DESCRIPTOR,
containing_type=None,
fields=[
_descriptor.FieldDescriptor(
name='call_key', full_name='Message.Call.call_key', index=0,
number=1, type=12, cpp_type=9, label=1,
has_default_value=False, default_value=_b(""),
message_type=None, enum_type=None, containing_type=None,
is_extension=False, extension_scope=None,
serialized_options=None, file=DESCRIPTOR),
],
extensions=[
],
nested_types=[],
enum_types=[
],
serialized_options=None,
is_extendable=False,
syntax='proto2',
extension_ranges=[],
oneofs=[
],
serialized_start=2668,
serialized_end=2692,
)
_MESSAGE_CHAT = _descriptor.Descriptor(
name='Chat',
full_name='Message.Chat',
filename=None,
file=DESCRIPTOR,
containing_type=None,
fields=[
_descriptor.FieldDescriptor(
name='display_name', full_name='Message.Chat.display_name', index=0,
number=1, type=9, cpp_type=9, label=1,
has_default_value=False, default_value=_b("").decode('utf-8'),
message_type=None, enum_type=None, containing_type=None,
is_extension=False, extension_scope=None,
serialized_options=None, file=DESCRIPTOR),
_descriptor.FieldDescriptor(
name='id', full_name='Message.Chat.id', index=1,
number=2, type=9, cpp_type=9, label=1,
has_default_value=False, default_value=_b("").decode('utf-8'),
message_type=None, enum_type=None, containing_type=None,
is_extension=False, extension_scope=None,
serialized_options=None, file=DESCRIPTOR),
],
extensions=[
],
nested_types=[],
enum_types=[
],
serialized_options=None,
is_extendable=False,
syntax='proto2',
extension_ranges=[],
oneofs=[
],
serialized_start=2694,
serialized_end=2734,
)
_MESSAGE_PROTOCOLMESSAGE = _descriptor.Descriptor(
name='ProtocolMessage',
full_name='Message.ProtocolMessage',
filename=None,
file=DESCRIPTOR,
containing_type=None,
fields=[
_descriptor.FieldDescriptor(
name='key', full_name='Message.ProtocolMessage.key', index=0,
number=1, type=11, cpp_type=10, label=1,
has_default_value=False, default_value=None,
message_type=None, enum_type=None, containing_type=None,
is_extension=False, extension_scope=None,
serialized_options=None, file=DESCRIPTOR),
_descriptor.FieldDescriptor(
name='type', full_name='Message.ProtocolMessage.type', index=1,
number=2, type=14, cpp_type=8, label=1,
has_default_value=True, default_value=0,
message_type=None, enum_type=None, containing_type=None,
is_extension=False, extension_scope=None,
serialized_options=None, file=DESCRIPTOR),
],
extensions=[
],
nested_types=[],
enum_types=[
_MESSAGE_PROTOCOLMESSAGE_TYPE,
],
serialized_options=None,
is_extendable=False,
syntax='proto2',
extension_ranges=[],
oneofs=[
],
serialized_start=2736,
serialized_end=2852,
)
_MESSAGE_CONTACTSARRAYMESSAGE = _descriptor.Descriptor(
name='ContactsArrayMessage',
full_name='Message.ContactsArrayMessage',
filename=None,
file=DESCRIPTOR,
containing_type=None,
fields=[
_descriptor.FieldDescriptor(
name='display_name', full_name='Message.ContactsArrayMessage.display_name', index=0,
number=1, type=9, cpp_type=9, label=1,
has_default_value=False, default_value=_b("").decode('utf-8'),
message_type=None, enum_type=None, containing_type=None,
is_extension=False, extension_scope=None,
serialized_options=None, file=DESCRIPTOR),
_descriptor.FieldDescriptor(
name='contacts', full_name='Message.ContactsArrayMessage.contacts', index=1,
number=2, type=11, cpp_type=10, label=3,
has_default_value=False, default_value=[],
message_type=None, enum_type=None, containing_type=None,
is_extension=False, extension_scope=None,
serialized_options=None, file=DESCRIPTOR),
_descriptor.FieldDescriptor(
name='context_info', full_name='Message.ContactsArrayMessage.context_info', index=2,
number=17, type=11, cpp_type=10, label=1,
has_default_value=False, default_value=None,
message_type=None, enum_type=None, containing_type=None,
is_extension=False, extension_scope=None,
serialized_options=None, file=DESCRIPTOR),
],
extensions=[
],
nested_types=[],
enum_types=[
],
serialized_options=None,
is_extendable=False,
syntax='proto2',
extension_ranges=[],
oneofs=[
],
serialized_start=2854,
serialized_end=2977,
)
_MESSAGE_HIGHLYSTRUCTUREDMESSAGE = _descriptor.Descriptor(
name='HighlyStructuredMessage',
full_name='Message.HighlyStructuredMessage',
filename=None,
file=DESCRIPTOR,
containing_type=None,
fields=[
_descriptor.FieldDescriptor(
name='namespace', full_name='Message.HighlyStructuredMessage.namespace', index=0,
number=1, type=9, cpp_type=9, label=1,
has_default_value=False, default_value=_b("").decode('utf-8'),
message_type=None, enum_type=None, containing_type=None,
is_extension=False, extension_scope=None,
serialized_options=None, file=DESCRIPTOR),
_descriptor.FieldDescriptor(
name='element_name', full_name='Message.HighlyStructuredMessage.element_name', index=1,
number=2, type=9, cpp_type=9, label=1,
has_default_value=False, default_value=_b("").decode('utf-8'),
message_type=None, enum_type=None, containing_type=None,
is_extension=False, extension_scope=None,
serialized_options=None, file=DESCRIPTOR),
_descriptor.FieldDescriptor(
name='params', full_name='Message.HighlyStructuredMessage.params', index=2,
number=3, type=9, cpp_type=9, label=3,
has_default_value=False, default_value=[],
message_type=None, enum_type=None, containing_type=None,
is_extension=False, extension_scope=None,
serialized_options=None, file=DESCRIPTOR),
_descriptor.FieldDescriptor(
name='fallback_lg', full_name='Message.HighlyStructuredMessage.fallback_lg', index=3,
number=4, type=9, cpp_type=9, label=1,
has_default_value=False, default_value=_b("").decode('utf-8'),
message_type=None, enum_type=None, containing_type=None,
is_extension=False, extension_scope=None,
serialized_options=None, file=DESCRIPTOR),
_descriptor.FieldDescriptor(
name='fallback_lc', full_name='Message.HighlyStructuredMessage.fallback_lc', index=4,
number=5, type=9, cpp_type=9, label=1,
has_default_value=False, default_value=_b("").decode('utf-8'),
message_type=None, enum_type=None, containing_type=None,
is_extension=False, extension_scope=None,
serialized_options=None, file=DESCRIPTOR),
],
extensions=[
],
nested_types=[],
enum_types=[
],
serialized_options=None,
is_extendable=False,
syntax='proto2',
extension_ranges=[],
oneofs=[
],
serialized_start=2979,
serialized_end=3103,
)
_MESSAGE = _descriptor.Descriptor(
name='Message',
full_name='Message',
filename=None,
file=DESCRIPTOR,
containing_type=None,
fields=[
_descriptor.FieldDescriptor(
name='conversation', full_name='Message.conversation', index=0,
number=1, type=9, cpp_type=9, label=1,
has_default_value=False, default_value=_b("").decode('utf-8'),
message_type=None, enum_type=None, containing_type=None,
is_extension=False, extension_scope=None,
serialized_options=None, file=DESCRIPTOR),
_descriptor.FieldDescriptor(
name='sender_key_distribution_message', full_name='Message.sender_key_distribution_message', index=1,
number=2, type=11, cpp_type=10, label=1,
has_default_value=False, default_value=None,
message_type=None, enum_type=None, containing_type=None,
is_extension=False, extension_scope=None,
serialized_options=None, file=DESCRIPTOR),
_descriptor.FieldDescriptor(
name='image_message', full_name='Message.image_message', index=2,
number=3, type=11, cpp_type=10, label=1,
has_default_value=False, default_value=None,
message_type=None, enum_type=None, containing_type=None,
is_extension=False, extension_scope=None,
serialized_options=None, file=DESCRIPTOR),
_descriptor.FieldDescriptor(
name='contact_message', full_name='Message.contact_message', index=3,
number=4, type=11, cpp_type=10, label=1,
has_default_value=False, default_value=None,
message_type=None, enum_type=None, containing_type=None,
is_extension=False, extension_scope=None,
serialized_options=None, file=DESCRIPTOR),
_descriptor.FieldDescriptor(
name='location_message', full_name='Message.location_message', index=4,
number=5, type=11, cpp_type=10, label=1,
has_default_value=False, default_value=None,
message_type=None, enum_type=None, containing_type=None,
is_extension=False, extension_scope=None,
serialized_options=None, file=DESCRIPTOR),
_descriptor.FieldDescriptor(
name='extended_text_message', full_name='Message.extended_text_message', index=5,
number=6, type=11, cpp_type=10, label=1,
has_default_value=False, default_value=None,
message_type=None, enum_type=None, containing_type=None,
is_extension=False, extension_scope=None,
serialized_options=None, file=DESCRIPTOR),
_descriptor.FieldDescriptor(
name='document_message', full_name='Message.document_message', index=6,
number=7, type=11, cpp_type=10, label=1,
has_default_value=False, default_value=None,
message_type=None, enum_type=None, containing_type=None,
is_extension=False, extension_scope=None,
serialized_options=None, file=DESCRIPTOR),
_descriptor.FieldDescriptor(
name='audio_message', full_name='Message.audio_message', index=7,
number=8, type=11, cpp_type=10, label=1,
has_default_value=False, default_value=None,
message_type=None, enum_type=None, containing_type=None,
is_extension=False, extension_scope=None,
serialized_options=None, file=DESCRIPTOR),
_descriptor.FieldDescriptor(
name='video_message', full_name='Message.video_message', index=8,
number=9, type=11, cpp_type=10, label=1,
has_default_value=False, default_value=None,
message_type=None, enum_type=None, containing_type=None,
is_extension=False, extension_scope=None,
serialized_options=None, file=DESCRIPTOR),
_descriptor.FieldDescriptor(
name='call', full_name='Message.call', index=9,
number=10, type=11, cpp_type=10, label=1,
has_default_value=False, default_value=None,
message_type=None, enum_type=None, containing_type=None,
is_extension=False, extension_scope=None,
serialized_options=None, file=DESCRIPTOR),
_descriptor.FieldDescriptor(
name='chat', full_name='Message.chat', index=10,
number=11, type=11, cpp_type=10, label=1,
has_default_value=False, default_value=None,
message_type=None, enum_type=None, containing_type=None,
is_extension=False, extension_scope=None,
serialized_options=None, file=DESCRIPTOR),
_descriptor.FieldDescriptor(
name='protocol_message', full_name='Message.protocol_message', index=11,
number=12, type=11, cpp_type=10, label=1,
has_default_value=False, default_value=None,
message_type=None, enum_type=None, containing_type=None,
is_extension=False, extension_scope=None,
serialized_options=None, file=DESCRIPTOR),
_descriptor.FieldDescriptor(
name='contacts_array_message', full_name='Message.contacts_array_message', index=12,
number=13, type=11, cpp_type=10, label=1,
has_default_value=False, default_value=None,
message_type=None, enum_type=None, containing_type=None,
is_extension=False, extension_scope=None,
serialized_options=None, file=DESCRIPTOR),
_descriptor.FieldDescriptor(
name='highly_structured_message', full_name='Message.highly_structured_message', index=13,
number=14, type=11, cpp_type=10, label=1,
has_default_value=False, default_value=None,
message_type=None, enum_type=None, containing_type=None,
is_extension=False, extension_scope=None,
serialized_options=None, file=DESCRIPTOR),
],
extensions=[
],
nested_types=[_MESSAGE_SENDERKEYDISTRIBUTIONMESSAGE, _MESSAGE_IMAGEMESSAGE, _MESSAGE_CONTACTMESSAGE, _MESSAGE_LOCATIONMESSAGE, _MESSAGE_EXTENDEDTEXTMESSAGE, _MESSAGE_DOCUMENTMESSAGE, _MESSAGE_AUDIOMESSAGE, _MESSAGE_VIDEOMESSAGE, _MESSAGE_CALL, _MESSAGE_CHAT, _MESSAGE_PROTOCOLMESSAGE, _MESSAGE_CONTACTSARRAYMESSAGE, _MESSAGE_HIGHLYSTRUCTUREDMESSAGE, ],
enum_types=[
],
serialized_options=None,
is_extendable=False,
syntax='proto2',
extension_ranges=[],
oneofs=[
],
serialized_start=209,
serialized_end=3103,
)
_CONTEXTINFO.fields_by_name['quoted_message'].message_type = _MESSAGE
_MESSAGE_SENDERKEYDISTRIBUTIONMESSAGE.containing_type = _MESSAGE
_MESSAGE_IMAGEMESSAGE.fields_by_name['context_info'].message_type = _CONTEXTINFO
_MESSAGE_IMAGEMESSAGE.containing_type = _MESSAGE
_MESSAGE_CONTACTMESSAGE.fields_by_name['context_info'].message_type = _CONTEXTINFO
_MESSAGE_CONTACTMESSAGE.containing_type = _MESSAGE
_MESSAGE_LOCATIONMESSAGE.fields_by_name['context_info'].message_type = _CONTEXTINFO
_MESSAGE_LOCATIONMESSAGE.containing_type = _MESSAGE
_MESSAGE_EXTENDEDTEXTMESSAGE.fields_by_name['context_info'].message_type = _CONTEXTINFO
_MESSAGE_EXTENDEDTEXTMESSAGE.containing_type = _MESSAGE
_MESSAGE_DOCUMENTMESSAGE.fields_by_name['context_info'].message_type = _CONTEXTINFO
_MESSAGE_DOCUMENTMESSAGE.containing_type = _MESSAGE
_MESSAGE_AUDIOMESSAGE.fields_by_name['context_info'].message_type = _CONTEXTINFO
_MESSAGE_AUDIOMESSAGE.containing_type = _MESSAGE
_MESSAGE_VIDEOMESSAGE.fields_by_name['context_info'].message_type = _CONTEXTINFO
_MESSAGE_VIDEOMESSAGE.fields_by_name['gif_attribution'].enum_type = _MESSAGE_VIDEOMESSAGE_ATTRIBUTION
_MESSAGE_VIDEOMESSAGE.containing_type = _MESSAGE
_MESSAGE_VIDEOMESSAGE_ATTRIBUTION.containing_type = _MESSAGE_VIDEOMESSAGE
_MESSAGE_CALL.containing_type = _MESSAGE
_MESSAGE_CHAT.containing_type = _MESSAGE
_MESSAGE_PROTOCOLMESSAGE.fields_by_name['key'].message_type = protocol__pb2._MESSAGEKEY
_MESSAGE_PROTOCOLMESSAGE.fields_by_name['type'].enum_type = _MESSAGE_PROTOCOLMESSAGE_TYPE
_MESSAGE_PROTOCOLMESSAGE.containing_type = _MESSAGE
_MESSAGE_PROTOCOLMESSAGE_TYPE.containing_type = _MESSAGE_PROTOCOLMESSAGE
_MESSAGE_CONTACTSARRAYMESSAGE.fields_by_name['contacts'].message_type = _MESSAGE_CONTACTMESSAGE
_MESSAGE_CONTACTSARRAYMESSAGE.fields_by_name['context_info'].message_type = _CONTEXTINFO
_MESSAGE_CONTACTSARRAYMESSAGE.containing_type = _MESSAGE
_MESSAGE_HIGHLYSTRUCTUREDMESSAGE.containing_type = _MESSAGE
_MESSAGE.fields_by_name['sender_key_distribution_message'].message_type = _MESSAGE_SENDERKEYDISTRIBUTIONMESSAGE
_MESSAGE.fields_by_name['image_message'].message_type = _MESSAGE_IMAGEMESSAGE
_MESSAGE.fields_by_name['contact_message'].message_type = _MESSAGE_CONTACTMESSAGE
_MESSAGE.fields_by_name['location_message'].message_type = _MESSAGE_LOCATIONMESSAGE
_MESSAGE.fields_by_name['extended_text_message'].message_type = _MESSAGE_EXTENDEDTEXTMESSAGE
_MESSAGE.fields_by_name['document_message'].message_type = _MESSAGE_DOCUMENTMESSAGE
_MESSAGE.fields_by_name['audio_message'].message_type = _MESSAGE_AUDIOMESSAGE
_MESSAGE.fields_by_name['video_message'].message_type = _MESSAGE_VIDEOMESSAGE
_MESSAGE.fields_by_name['call'].message_type = _MESSAGE_CALL
_MESSAGE.fields_by_name['chat'].message_type = _MESSAGE_CHAT
_MESSAGE.fields_by_name['protocol_message'].message_type = _MESSAGE_PROTOCOLMESSAGE
_MESSAGE.fields_by_name['contacts_array_message'].message_type = _MESSAGE_CONTACTSARRAYMESSAGE
_MESSAGE.fields_by_name['highly_structured_message'].message_type = _MESSAGE_HIGHLYSTRUCTUREDMESSAGE
DESCRIPTOR.message_types_by_name['ContextInfo'] = _CONTEXTINFO
DESCRIPTOR.message_types_by_name['Message'] = _MESSAGE
_sym_db.RegisterFileDescriptor(DESCRIPTOR)
ContextInfo = _reflection.GeneratedProtocolMessageType('ContextInfo', (_message.Message,), dict(
DESCRIPTOR = _CONTEXTINFO,
__module__ = 'e2e_pb2'
# @@protoc_insertion_point(class_scope:ContextInfo)
))
_sym_db.RegisterMessage(ContextInfo)
Message = _reflection.GeneratedProtocolMessageType('Message', (_message.Message,), dict(
SenderKeyDistributionMessage = _reflection.GeneratedProtocolMessageType('SenderKeyDistributionMessage', (_message.Message,), dict(
DESCRIPTOR = _MESSAGE_SENDERKEYDISTRIBUTIONMESSAGE,
__module__ = 'e2e_pb2'
# @@protoc_insertion_point(class_scope:Message.SenderKeyDistributionMessage)
))
,
ImageMessage = _reflection.GeneratedProtocolMessageType('ImageMessage', (_message.Message,), dict(
DESCRIPTOR = _MESSAGE_IMAGEMESSAGE,
__module__ = 'e2e_pb2'
# @@protoc_insertion_point(class_scope:Message.ImageMessage)
))
,
ContactMessage = _reflection.GeneratedProtocolMessageType('ContactMessage', (_message.Message,), dict(
DESCRIPTOR = _MESSAGE_CONTACTMESSAGE,
__module__ = 'e2e_pb2'
# @@protoc_insertion_point(class_scope:Message.ContactMessage)
))
,
LocationMessage = _reflection.GeneratedProtocolMessageType('LocationMessage', (_message.Message,), dict(
DESCRIPTOR = _MESSAGE_LOCATIONMESSAGE,
__module__ = 'e2e_pb2'
# @@protoc_insertion_point(class_scope:Message.LocationMessage)
))
,
ExtendedTextMessage = _reflection.GeneratedProtocolMessageType('ExtendedTextMessage', (_message.Message,), dict(
DESCRIPTOR = _MESSAGE_EXTENDEDTEXTMESSAGE,
__module__ = 'e2e_pb2'
# @@protoc_insertion_point(class_scope:Message.ExtendedTextMessage)
))
,
DocumentMessage = _reflection.GeneratedProtocolMessageType('DocumentMessage', (_message.Message,), dict(
DESCRIPTOR = _MESSAGE_DOCUMENTMESSAGE,
__module__ = 'e2e_pb2'
# @@protoc_insertion_point(class_scope:Message.DocumentMessage)
))
,
AudioMessage = _reflection.GeneratedProtocolMessageType('AudioMessage', (_message.Message,), dict(
DESCRIPTOR = _MESSAGE_AUDIOMESSAGE,
__module__ = 'e2e_pb2'
# @@protoc_insertion_point(class_scope:Message.AudioMessage)
))
,
VideoMessage = _reflection.GeneratedProtocolMessageType('VideoMessage', (_message.Message,), dict(
DESCRIPTOR = _MESSAGE_VIDEOMESSAGE,
__module__ = 'e2e_pb2'
# @@protoc_insertion_point(class_scope:Message.VideoMessage)
))
,
Call = _reflection.GeneratedProtocolMessageType('Call', (_message.Message,), dict(
DESCRIPTOR = _MESSAGE_CALL,
__module__ = 'e2e_pb2'
# @@protoc_insertion_point(class_scope:Message.Call)
))
,
Chat = _reflection.GeneratedProtocolMessageType('Chat', (_message.Message,), dict(
DESCRIPTOR = _MESSAGE_CHAT,
__module__ = 'e2e_pb2'
# @@protoc_insertion_point(class_scope:Message.Chat)
))
,
ProtocolMessage = _reflection.GeneratedProtocolMessageType('ProtocolMessage', (_message.Message,), dict(
DESCRIPTOR = _MESSAGE_PROTOCOLMESSAGE,
__module__ = 'e2e_pb2'
# @@protoc_insertion_point(class_scope:Message.ProtocolMessage)
))
,
ContactsArrayMessage = _reflection.GeneratedProtocolMessageType('ContactsArrayMessage', (_message.Message,), dict(
DESCRIPTOR = _MESSAGE_CONTACTSARRAYMESSAGE,
__module__ = 'e2e_pb2'
# @@protoc_insertion_point(class_scope:Message.ContactsArrayMessage)
))
,
HighlyStructuredMessage = _reflection.GeneratedProtocolMessageType('HighlyStructuredMessage', (_message.Message,), dict(
DESCRIPTOR = _MESSAGE_HIGHLYSTRUCTUREDMESSAGE,
__module__ = 'e2e_pb2'
# @@protoc_insertion_point(class_scope:Message.HighlyStructuredMessage)
))
,
DESCRIPTOR = _MESSAGE,
__module__ = 'e2e_pb2'
# @@protoc_insertion_point(class_scope:Message)
))
_sym_db.RegisterMessage(Message)
_sym_db.RegisterMessage(Message.SenderKeyDistributionMessage)
_sym_db.RegisterMessage(Message.ImageMessage)
_sym_db.RegisterMessage(Message.ContactMessage)
_sym_db.RegisterMessage(Message.LocationMessage)
_sym_db.RegisterMessage(Message.ExtendedTextMessage)
_sym_db.RegisterMessage(Message.DocumentMessage)
_sym_db.RegisterMessage(Message.AudioMessage)
_sym_db.RegisterMessage(Message.VideoMessage)
_sym_db.RegisterMessage(Message.Call)
_sym_db.RegisterMessage(Message.Chat)
_sym_db.RegisterMessage(Message.ProtocolMessage)
_sym_db.RegisterMessage(Message.ContactsArrayMessage)
_sym_db.RegisterMessage(Message.HighlyStructuredMessage)
# @@protoc_insertion_point(module_scope)
yowsup-3.2.3/yowsup/layers/protocol_messages/proto/protocol_pb2.py 0000664 0000000 0000000 00000005752 13464333726 0025627 0 ustar 00root root 0000000 0000000 # Generated by the protocol buffer compiler. DO NOT EDIT!
# source: protocol.proto
import sys
_b=sys.version_info[0]<3 and (lambda x:x) or (lambda x:x.encode('latin1'))
from google.protobuf import descriptor as _descriptor
from google.protobuf import message as _message
from google.protobuf import reflection as _reflection
from google.protobuf import symbol_database as _symbol_database
# @@protoc_insertion_point(imports)
_sym_db = _symbol_database.Default()
DESCRIPTOR = _descriptor.FileDescriptor(
name='protocol.proto',
package='',
syntax='proto2',
serialized_options=None,
serialized_pb=_b('\n\x0eprotocol.proto\"R\n\nMessageKey\x12\x12\n\nremote_jid\x18\x01 \x01(\t\x12\x0f\n\x07\x66rom_me\x18\x02 \x01(\x08\x12\n\n\x02id\x18\x03 \x01(\t\x12\x13\n\x0bparticipant\x18\x04 \x01(\t')
)
_MESSAGEKEY = _descriptor.Descriptor(
name='MessageKey',
full_name='MessageKey',
filename=None,
file=DESCRIPTOR,
containing_type=None,
fields=[
_descriptor.FieldDescriptor(
name='remote_jid', full_name='MessageKey.remote_jid', index=0,
number=1, type=9, cpp_type=9, label=1,
has_default_value=False, default_value=_b("").decode('utf-8'),
message_type=None, enum_type=None, containing_type=None,
is_extension=False, extension_scope=None,
serialized_options=None, file=DESCRIPTOR),
_descriptor.FieldDescriptor(
name='from_me', full_name='MessageKey.from_me', index=1,
number=2, type=8, cpp_type=7, label=1,
has_default_value=False, default_value=False,
message_type=None, enum_type=None, containing_type=None,
is_extension=False, extension_scope=None,
serialized_options=None, file=DESCRIPTOR),
_descriptor.FieldDescriptor(
name='id', full_name='MessageKey.id', index=2,
number=3, type=9, cpp_type=9, label=1,
has_default_value=False, default_value=_b("").decode('utf-8'),
message_type=None, enum_type=None, containing_type=None,
is_extension=False, extension_scope=None,
serialized_options=None, file=DESCRIPTOR),
_descriptor.FieldDescriptor(
name='participant', full_name='MessageKey.participant', index=3,
number=4, type=9, cpp_type=9, label=1,
has_default_value=False, default_value=_b("").decode('utf-8'),
message_type=None, enum_type=None, containing_type=None,
is_extension=False, extension_scope=None,
serialized_options=None, file=DESCRIPTOR),
],
extensions=[
],
nested_types=[],
enum_types=[
],
serialized_options=None,
is_extendable=False,
syntax='proto2',
extension_ranges=[],
oneofs=[
],
serialized_start=18,
serialized_end=100,
)
DESCRIPTOR.message_types_by_name['MessageKey'] = _MESSAGEKEY
_sym_db.RegisterFileDescriptor(DESCRIPTOR)
MessageKey = _reflection.GeneratedProtocolMessageType('MessageKey', (_message.Message,), dict(
DESCRIPTOR = _MESSAGEKEY,
__module__ = 'protocol_pb2'
# @@protoc_insertion_point(class_scope:MessageKey)
))
_sym_db.RegisterMessage(MessageKey)
# @@protoc_insertion_point(module_scope)
yowsup-3.2.3/yowsup/layers/protocol_messages/protocolentities/ 0000775 0000000 0000000 00000000000 13464333726 0025103 5 ustar 00root root 0000000 0000000 yowsup-3.2.3/yowsup/layers/protocol_messages/protocolentities/__init__.py 0000664 0000000 0000000 00000000230 13464333726 0027207 0 ustar 00root root 0000000 0000000 from .message_text import TextMessageProtocolEntity
from .message import MessageProtocolEntity
from .message_text_broadcast import BroadcastTextMessage
yowsup-3.2.3/yowsup/layers/protocol_messages/protocolentities/attributes/ 0000775 0000000 0000000 00000000000 13464333726 0027271 5 ustar 00root root 0000000 0000000 yowsup-3.2.3/yowsup/layers/protocol_messages/protocolentities/attributes/__init__.py 0000664 0000000 0000000 00000000000 13464333726 0031370 0 ustar 00root root 0000000 0000000 yowsup-3.2.3/yowsup/layers/protocol_messages/protocolentities/attributes/attributes_message.py 0000664 0000000 0000000 00000002062 13464333726 0033535 0 ustar 00root root 0000000 0000000 class MessageAttributes(object):
def __init__(
self, id=None, sender=None, recipient=None, notify=None, timestamp=None, participant=None, offline=None,
retry=None
):
assert (sender or recipient), "Must specify either sender or recipient " \
"jid to create the message "
assert not (sender and recipient), "Can't set both attributes to message at same " \
"time (sender, recipient) "
self.id = id
self.sender = sender
self.recipient = recipient
self.notify = notify
self.timestamp = int(timestamp) if timestamp else None
self.participant = participant
self.offline = offline in ("1", True)
self.retry = int(retry) if retry else None
@staticmethod
def from_message_protocoltreenode(node):
return MessageAttributes(
node["id"], node["from"], node["to"], node["notify"], node["t"], node["participant"], node["offline"],
node["retry"]
)
yowsup-3.2.3/yowsup/layers/protocol_messages/protocolentities/message.py 0000664 0000000 0000000 00000007573 13464333726 0027115 0 ustar 00root root 0000000 0000000 from yowsup.structs import ProtocolEntity
from yowsup.layers.protocol_receipts.protocolentities import OutgoingReceiptProtocolEntity
from yowsup.layers.protocol_messages.protocolentities.attributes.attributes_message import MessageAttributes
from copy import deepcopy
class MessageProtocolEntity(ProtocolEntity):
MESSAGE_TYPE_TEXT = "text"
MESSAGE_TYPE_MEDIA = "media"
def __init__(self, messageType, messageAttributes):
"""
:type messageType: str
:type messageAttributes: MessageAttributes
"""
super(MessageProtocolEntity, self).__init__("message")
assert type(messageAttributes) is MessageAttributes
self._type = messageType
self._id = messageAttributes.id or self._generateId()
self._from = messageAttributes.sender
self.to = messageAttributes.recipient
self.timestamp = messageAttributes.timestamp or self._getCurrentTimestamp()
self.notify = messageAttributes.notify
self.offline = messageAttributes.offline
self.retry = messageAttributes.retry
self.participant= messageAttributes.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 getAuthor(self, full = True):
return self.getParticipant(full) if self.isGroupMessage() else self.getFrom(full)
def getNotify(self):
return self.notify
def toProtocolTreeNode(self):
attribs = {
"type" : self._type,
"id" : self._id,
}
if self.participant:
attribs["participant"] = self.participant
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)
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["type"],
MessageAttributes.from_message_protocoltreenode(node)
)
yowsup-3.2.3/yowsup/layers/protocol_messages/protocolentities/message_text.py 0000664 0000000 0000000 00000001607 13464333726 0030151 0 ustar 00root root 0000000 0000000 from .protomessage import ProtomessageProtocolEntity
from .message import MessageAttributes
class TextMessageProtocolEntity(ProtomessageProtocolEntity):
def __init__(self, body, messageAttributes=None, to=None):
#flexible attributes for temp backwards compat
assert(bool(messageAttributes) ^ bool(to)), "Either set messageAttributes, or to, and not both"
if to:
messageAttributes = MessageAttributes(recipient=to)
super(TextMessageProtocolEntity, self).__init__("text", messageAttributes)
self.setBody(body)
@property
def conversation(self):
return self.proto.conversation
@conversation.setter
def conversation(self, value):
self.proto.conversation = value
def getBody(self):
#obsolete
return self.conversation
def setBody(self, body):
#obsolete
self.conversation = body
yowsup-3.2.3/yowsup/layers/protocol_messages/protocolentities/message_text_broadcast.py 0000664 0000000 0000000 00000002241 13464333726 0032166 0 ustar 00root root 0000000 0000000 from .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-3.2.3/yowsup/layers/protocol_messages/protocolentities/proto.py 0000664 0000000 0000000 00000001327 13464333726 0026623 0 ustar 00root root 0000000 0000000 from yowsup.structs import ProtocolEntity, ProtocolTreeNode
class ProtoProtocolEntity(ProtocolEntity):
def __init__(self, protoData, mediaType = None):
super(ProtoProtocolEntity, self).__init__("proto")
self.mediaType = mediaType
self.protoData = protoData
def getProtoData(self):
return self.protoData
def getMediaType(self):
return self.mediaType
def toProtocolTreeNode(self):
attribs = {}
if self.mediaType:
attribs["mediatype"] = self.mediaType
return ProtocolTreeNode("proto", attribs, data=self.protoData)
@staticmethod
def fromProtocolTreeNode(node):
return ProtoProtocolEntity(node.data, node["mediatype"]) yowsup-3.2.3/yowsup/layers/protocol_messages/protocolentities/protomessage.py 0000664 0000000 0000000 00000003071 13464333726 0030166 0 ustar 00root root 0000000 0000000 from .message import MessageProtocolEntity
from .proto import ProtoProtocolEntity
from yowsup.layers.protocol_messages.proto.e2e_pb2 import Message
import logging
logger = logging.getLogger(__name__)
class ProtomessageProtocolEntity(MessageProtocolEntity):
'''
{{SERIALIZE_PROTO_DATA}}
'''
def __init__(self, messageType, messageAttributes):
super(ProtomessageProtocolEntity, self).__init__(messageType, messageAttributes)
self._proto = Message()
def __str__(self):
out = super(ProtomessageProtocolEntity, self).__str__()
return "%s\nproto=%s" % (out, self._proto)
@property
def proto(self):
return self._proto
def deserializeProtoData(self, protoData):
m = Message()
m.ParseFromString(protoData)
return m
def toProtocolTreeNode(self):
node = super(ProtomessageProtocolEntity, self).toProtocolTreeNode()
node.addChild(ProtoProtocolEntity(self._proto.SerializeToString()).toProtocolTreeNode())
return node
def setProtoFromData(self, protoData):
self._proto = self.deserializeProtoData(protoData)
@classmethod
def fromProtocolTreeNode(cls, node):
entity = MessageProtocolEntity.fromProtocolTreeNode(node)
entity.__class__= cls
entity.setProtoFromData(node.getChild("proto").getData())
return entity yowsup-3.2.3/yowsup/layers/protocol_messages/protocolentities/test_message.py 0000664 0000000 0000000 00000001317 13464333726 0030142 0 ustar 00root root 0000000 0000000 from 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-3.2.3/yowsup/layers/protocol_messages/protocolentities/test_message_text.py 0000664 0000000 0000000 00000001262 13464333726 0031205 0 ustar 00root root 0000000 0000000 from yowsup.layers.protocol_messages.protocolentities.message_text import TextMessageProtocolEntity
from yowsup.structs import ProtocolTreeNode
from yowsup.layers.protocol_messages.protocolentities.test_message import MessageProtocolEntityTest
from yowsup.layers.protocol_messages.proto.e2e_pb2 import Message
class TextMessageProtocolEntityTest(MessageProtocolEntityTest):
def setUp(self):
super(TextMessageProtocolEntityTest, self).setUp()
self.ProtocolEntity = TextMessageProtocolEntity
m = Message()
m.conversation = "body_data"
proto_node = ProtocolTreeNode("proto", {}, None, m.SerializeToString())
self.node.addChild(proto_node)
yowsup-3.2.3/yowsup/layers/protocol_messages/protocolentities/test_message_text_broadcast.py 0000664 0000000 0000000 00000001266 13464333726 0033233 0 ustar 00root root 0000000 0000000 from 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-3.2.3/yowsup/layers/protocol_notifications/ 0000775 0000000 0000000 00000000000 13464333726 0022537 5 ustar 00root root 0000000 0000000 yowsup-3.2.3/yowsup/layers/protocol_notifications/__init__.py 0000664 0000000 0000000 00000000060 13464333726 0024644 0 ustar 00root root 0000000 0000000 from .layer import YowNotificationsProtocolLayer yowsup-3.2.3/yowsup/layers/protocol_notifications/layer.py 0000664 0000000 0000000 00000003325 13464333726 0024230 0 ustar 00root root 0000000 0000000 from yowsup.layers import YowLayer, YowLayerEvent, YowProtocolLayer
from .protocolentities import *
from yowsup.layers.protocol_acks.protocolentities import OutgoingAckProtocolEntity
import logging
logger = logging.getLogger(__name__)
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"] in ["contacts", "subject", "w:gp2"]:
# Implemented in respectively the protocol_contacts and protocol_groups layer
pass
else:
logger.warn("Unsupported notification type: %s " % node["type"])
logger.debug("Unsupported notification node: %s" % node)
ack = OutgoingAckProtocolEntity(node["id"], "notification", node["type"], node["from"], participant=node["participant"])
self.toLower(ack.toProtocolTreeNode())
yowsup-3.2.3/yowsup/layers/protocol_notifications/protocolentities/ 0000775 0000000 0000000 00000000000 13464333726 0026145 5 ustar 00root root 0000000 0000000 yowsup-3.2.3/yowsup/layers/protocol_notifications/protocolentities/__init__.py 0000664 0000000 0000000 00000000605 13464333726 0030257 0 ustar 00root root 0000000 0000000 from .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-3.2.3/yowsup/layers/protocol_notifications/protocolentities/notification.py 0000664 0000000 0000000 00000003661 13464333726 0031213 0 ustar 00root root 0000000 0000000 from 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)
@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-3.2.3/yowsup/layers/protocol_notifications/protocolentities/notification_picture.py 0000664 0000000 0000000 00000001457 13464333726 0032747 0 ustar 00root root 0000000 0000000 from 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 entity yowsup-3.2.3/yowsup/layers/protocol_notifications/protocolentities/notification_picture_delete.py 0000664 0000000 0000000 00000002726 13464333726 0034271 0 ustar 00root root 0000000 0000000 from 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-3.2.3/yowsup/layers/protocol_notifications/protocolentities/notification_picture_set.py 0000664 0000000 0000000 00000002575 13464333726 0033624 0 ustar 00root root 0000000 0000000 from 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 entity yowsup-3.2.3/yowsup/layers/protocol_notifications/protocolentities/notification_status.py 0000664 0000000 0000000 00000002303 13464333726 0032606 0 ustar 00root root 0000000 0000000 from 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 entity yowsup-3.2.3/yowsup/layers/protocol_notifications/protocolentities/test_notification.py 0000664 0000000 0000000 00000001226 13464333726 0032245 0 ustar 00root root 0000000 0000000 from 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-3.2.3/yowsup/layers/protocol_notifications/protocolentities/test_notification_picture.py 0000664 0000000 0000000 00000000722 13464333726 0034000 0 ustar 00root root 0000000 0000000 from 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.py 0000664 0000000 0000000 00000001255 13464333726 0035245 0 ustar 00root root 0000000 0000000 yowsup-3.2.3/yowsup/layers/protocol_notifications/protocolentities from 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-3.2.3/yowsup/layers/protocol_notifications/protocolentities/test_notification_picture_set.py 0000664 0000000 0000000 00000001237 13464333726 0034655 0 ustar 00root root 0000000 0000000 from 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-3.2.3/yowsup/layers/protocol_notifications/protocolentities/test_notification_status.py 0000664 0000000 0000000 00000001136 13464333726 0033650 0 ustar 00root root 0000000 0000000 from 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-3.2.3/yowsup/layers/protocol_presence/ 0000775 0000000 0000000 00000000000 13464333726 0021472 5 ustar 00root root 0000000 0000000 yowsup-3.2.3/yowsup/layers/protocol_presence/__init__.py 0000664 0000000 0000000 00000000054 13464333726 0023602 0 ustar 00root root 0000000 0000000 from .layer import YowPresenceProtocolLayer
yowsup-3.2.3/yowsup/layers/protocol_presence/layer.py 0000664 0000000 0000000 00000002227 13464333726 0023163 0 ustar 00root root 0000000 0000000 from 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-3.2.3/yowsup/layers/protocol_presence/protocolentities/ 0000775 0000000 0000000 00000000000 13464333726 0025100 5 ustar 00root root 0000000 0000000 yowsup-3.2.3/yowsup/layers/protocol_presence/protocolentities/__init__.py 0000664 0000000 0000000 00000000710 13464333726 0027207 0 ustar 00root root 0000000 0000000 from .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-3.2.3/yowsup/layers/protocol_presence/protocolentities/iq_lastseen.py 0000664 0000000 0000000 00000001307 13464333726 0027762 0 ustar 00root root 0000000 0000000 from 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-3.2.3/yowsup/layers/protocol_presence/protocolentities/iq_lastseen_result.py 0000664 0000000 0000000 00000002004 13464333726 0031353 0 ustar 00root root 0000000 0000000 from 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-3.2.3/yowsup/layers/protocol_presence/protocolentities/presence.py 0000664 0000000 0000000 00000003611 13464333726 0027257 0 ustar 00root root 0000000 0000000 from 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-3.2.3/yowsup/layers/protocol_presence/protocolentities/presence_available.py 0000664 0000000 0000000 00000000603 13464333726 0031255 0 ustar 00root root 0000000 0000000 from yowsup.structs import ProtocolEntity, ProtocolTreeNode
from .presence import PresenceProtocolEntity
class AvailablePresenceProtocolEntity(PresenceProtocolEntity):
'''
response:
'''
def __init__(self):
super(AvailablePresenceProtocolEntity, self).__init__("available") yowsup-3.2.3/yowsup/layers/protocol_presence/protocolentities/presence_subscribe.py 0000664 0000000 0000000 00000002011 13464333726 0031311 0 ustar 00root root 0000000 0000000 from 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-3.2.3/yowsup/layers/protocol_presence/protocolentities/presence_unavailable.py 0000664 0000000 0000000 00000000635 13464333726 0031625 0 ustar 00root root 0000000 0000000 from yowsup.structs import ProtocolEntity, ProtocolTreeNode
from .presence import PresenceProtocolEntity
class UnavailablePresenceProtocolEntity(PresenceProtocolEntity):
'''
response:
'''
def __init__(self):
super(UnavailablePresenceProtocolEntity, self).__init__("unavailable") yowsup-3.2.3/yowsup/layers/protocol_presence/protocolentities/presence_unsubscribe.py 0000664 0000000 0000000 00000002027 13464333726 0031663 0 ustar 00root root 0000000 0000000 from 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-3.2.3/yowsup/layers/protocol_presence/protocolentities/test_presence.py 0000664 0000000 0000000 00000000733 13464333726 0030320 0 ustar 00root root 0000000 0000000 from 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-3.2.3/yowsup/layers/protocol_presence/protocolentities/test_presence_available.py 0000664 0000000 0000000 00000000746 13464333726 0032324 0 ustar 00root root 0000000 0000000 from 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-3.2.3/yowsup/layers/protocol_presence/protocolentities/test_presence_subscribe.py 0000664 0000000 0000000 00000001033 13464333726 0032353 0 ustar 00root root 0000000 0000000 from 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-3.2.3/yowsup/layers/protocol_presence/protocolentities/test_presence_unavailable.py 0000664 0000000 0000000 00000000762 13464333726 0032665 0 ustar 00root root 0000000 0000000 from 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-3.2.3/yowsup/layers/protocol_presence/protocolentities/test_presence_unsubscribe.py 0000664 0000000 0000000 00000001042 13464333726 0032716 0 ustar 00root root 0000000 0000000 from 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-3.2.3/yowsup/layers/protocol_privacy/ 0000775 0000000 0000000 00000000000 13464333726 0021343 5 ustar 00root root 0000000 0000000 yowsup-3.2.3/yowsup/layers/protocol_privacy/__init__.py 0000664 0000000 0000000 00000000052 13464333726 0023451 0 ustar 00root root 0000000 0000000 from .layer import YowPrivacyProtocolLayer yowsup-3.2.3/yowsup/layers/protocol_privacy/layer.py 0000664 0000000 0000000 00000001027 13464333726 0023031 0 ustar 00root root 0000000 0000000 from 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-3.2.3/yowsup/layers/protocol_privacy/protocolentities/ 0000775 0000000 0000000 00000000000 13464333726 0024751 5 ustar 00root root 0000000 0000000 yowsup-3.2.3/yowsup/layers/protocol_privacy/protocolentities/__init__.py 0000664 0000000 0000000 00000000067 13464333726 0027065 0 ustar 00root root 0000000 0000000 from .privacylist_iq import PrivacyListIqProtocolEntity yowsup-3.2.3/yowsup/layers/protocol_privacy/protocolentities/privacylist_iq.py 0000664 0000000 0000000 00000001727 13464333726 0030374 0 ustar 00root root 0000000 0000000 from 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-3.2.3/yowsup/layers/protocol_profiles/ 0000775 0000000 0000000 00000000000 13464333726 0021511 5 ustar 00root root 0000000 0000000 yowsup-3.2.3/yowsup/layers/protocol_profiles/__init__.py 0000664 0000000 0000000 00000000053 13464333726 0023620 0 ustar 00root root 0000000 0000000 from .layer import YowProfilesProtocolLayer yowsup-3.2.3/yowsup/layers/protocol_profiles/layer.py 0000664 0000000 0000000 00000005237 13464333726 0023206 0 ustar 00root root 0000000 0000000 from 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-3.2.3/yowsup/layers/protocol_profiles/protocolentities/ 0000775 0000000 0000000 00000000000 13464333726 0025117 5 ustar 00root root 0000000 0000000 yowsup-3.2.3/yowsup/layers/protocol_profiles/protocolentities/__init__.py 0000664 0000000 0000000 00000001003 13464333726 0027222 0 ustar 00root root 0000000 0000000 from .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-3.2.3/yowsup/layers/protocol_profiles/protocolentities/iq_picture.py 0000664 0000000 0000000 00000001036 13464333726 0027635 0 ustar 00root root 0000000 0000000 from 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-3.2.3/yowsup/layers/protocol_profiles/protocolentities/iq_picture_get.py 0000664 0000000 0000000 00000002216 13464333726 0030475 0 ustar 00root root 0000000 0000000 from .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 entity yowsup-3.2.3/yowsup/layers/protocol_profiles/protocolentities/iq_picture_get_result.py 0000664 0000000 0000000 00000003346 13464333726 0032100 0 ustar 00root root 0000000 0000000 from .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 entity yowsup-3.2.3/yowsup/layers/protocol_profiles/protocolentities/iq_picture_set.py 0000664 0000000 0000000 00000004440 13464333726 0030512 0 ustar 00root root 0000000 0000000 from .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 entity yowsup-3.2.3/yowsup/layers/protocol_profiles/protocolentities/iq_pictures_list.py 0000664 0000000 0000000 00000002502 13464333726 0031052 0 ustar 00root root 0000000 0000000 from 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 entity yowsup-3.2.3/yowsup/layers/protocol_profiles/protocolentities/iq_privacy_get.py 0000664 0000000 0000000 00000001627 13464333726 0030504 0 ustar 00root root 0000000 0000000 from 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-3.2.3/yowsup/layers/protocol_profiles/protocolentities/iq_privacy_result.py 0000664 0000000 0000000 00000003267 13464333726 0031245 0 ustar 00root root 0000000 0000000 from 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-3.2.3/yowsup/layers/protocol_profiles/protocolentities/iq_privacy_set.py 0000664 0000000 0000000 00000005002 13464333726 0030507 0 ustar 00root root 0000000 0000000 from 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-3.2.3/yowsup/layers/protocol_profiles/protocolentities/iq_status_set.py 0000664 0000000 0000000 00000002177 13464333726 0030367 0 ustar 00root root 0000000 0000000 from yowsup.common import YowConstants
from 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 = YowConstants.WHATSAPP_SERVER)
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-3.2.3/yowsup/layers/protocol_profiles/protocolentities/iq_unregister.py 0000664 0000000 0000000 00000001734 13464333726 0030356 0 ustar 00root root 0000000 0000000 from yowsup.common import YowConstants
from 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 = YowConstants.WHATSAPP_SERVER)
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 entity yowsup-3.2.3/yowsup/layers/protocol_profiles/protocolentities/test_iq_privacy_get.py 0000664 0000000 0000000 00000000766 13464333726 0031546 0 ustar 00root root 0000000 0000000 from 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-3.2.3/yowsup/layers/protocol_profiles/protocolentities/test_iq_privacy_result.py 0000664 0000000 0000000 00000001070 13464333726 0032272 0 ustar 00root root 0000000 0000000 from 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-3.2.3/yowsup/layers/protocol_profiles/protocolentities/test_iq_privacy_set.py 0000664 0000000 0000000 00000001030 13464333726 0031543 0 ustar 00root root 0000000 0000000 from 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-3.2.3/yowsup/layers/protocol_profiles/protocolentities/test_iq_status_set.py 0000664 0000000 0000000 00000001033 13464333726 0031414 0 ustar 00root root 0000000 0000000 from 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-3.2.3/yowsup/layers/protocol_profiles/protocolentities/test_iq_unregister.py 0000664 0000000 0000000 00000000775 13464333726 0031421 0 ustar 00root root 0000000 0000000 from 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-3.2.3/yowsup/layers/protocol_receipts/ 0000775 0000000 0000000 00000000000 13464333726 0021504 5 ustar 00root root 0000000 0000000 yowsup-3.2.3/yowsup/layers/protocol_receipts/__init__.py 0000664 0000000 0000000 00000000054 13464333726 0023614 0 ustar 00root root 0000000 0000000 from .layer import YowReceiptProtocolLayer
yowsup-3.2.3/yowsup/layers/protocol_receipts/layer.py 0000664 0000000 0000000 00000001117 13464333726 0023172 0 ustar 00root root 0000000 0000000 from 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-3.2.3/yowsup/layers/protocol_receipts/protocolentities/ 0000775 0000000 0000000 00000000000 13464333726 0025112 5 ustar 00root root 0000000 0000000 yowsup-3.2.3/yowsup/layers/protocol_receipts/protocolentities/__init__.py 0000664 0000000 0000000 00000000242 13464333726 0027221 0 ustar 00root root 0000000 0000000 from .receipt import ReceiptProtocolEntity
from .receipt_incoming import IncomingReceiptProtocolEntity
from .receipt_outgoing import OutgoingReceiptProtocolEntity yowsup-3.2.3/yowsup/layers/protocol_receipts/protocolentities/receipt.py 0000664 0000000 0000000 00000002033 13464333726 0027115 0 ustar 00root root 0000000 0000000 from 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-3.2.3/yowsup/layers/protocol_receipts/protocolentities/receipt_incoming.py 0000664 0000000 0000000 00000011122 13464333726 0030777 0 ustar 00root root 0000000 0000000 from 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, full=True):
if self.participant:
return self.participant if full else self.participant.split('@')[0]
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(), participant = self.participant)
@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-3.2.3/yowsup/layers/protocol_receipts/protocolentities/receipt_outgoing.py 0000664 0000000 0000000 00000005574 13464333726 0031045 0 ustar 00root root 0000000 0000000 import 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-3.2.3/yowsup/layers/protocol_receipts/protocolentities/test_receipt_incoming.py 0000664 0000000 0000000 00000000700 13464333726 0032036 0 ustar 00root root 0000000 0000000 from 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-3.2.3/yowsup/layers/protocol_receipts/protocolentities/test_receipt_outgoing.py 0000664 0000000 0000000 00000000651 13464333726 0032073 0 ustar 00root root 0000000 0000000 from 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-3.2.3/yowsup/registration/ 0000775 0000000 0000000 00000000000 13464333726 0017160 5 ustar 00root root 0000000 0000000 yowsup-3.2.3/yowsup/registration/__init__.py 0000664 0000000 0000000 00000000166 13464333726 0021274 0 ustar 00root root 0000000 0000000 from .coderequest import WACodeRequest
from .existsrequest import WAExistsRequest
from .regrequest import WARegRequest yowsup-3.2.3/yowsup/registration/coderequest.py 0000664 0000000 0000000 00000003501 13464333726 0022054 0 ustar 00root root 0000000 0000000 from yowsup.common.http.warequest import WARequest
from yowsup.common.http.waresponseparser import JSONResponseParser
from yowsup.common.tools import WATools
from yowsup.registration.existsrequest import WAExistsRequest
from yowsup.env import YowsupEnv
class WACodeRequest(WARequest):
def __init__(self, method, config):
"""
:type method: str
:param config:
:type config: yowsup.config.v1.config.Config
"""
super(WACodeRequest,self).__init__(config)
self.addParam("mcc", config.mcc.zfill(3))
self.addParam("mnc", config.mnc.zfill(3))
self.addParam("sim_mcc", config.sim_mcc.zfill(3))
self.addParam("sim_mnc", config.sim_mnc.zfill(3))
self.addParam("method", method)
self.addParam("reason", "")
self.addParam("token", YowsupEnv.getCurrent().getToken(self._p_in))
self.addParam("hasav", "1")
self.url = "v.whatsapp.net/v2/code"
self.pvars = ["status","reason","length", "method", "retry_after", "code", "param"] +\
["login", "type", "sms_wait", "voice_wait"]
self.setParser(JSONResponseParser())
def send(self, parser = None, encrypt=True, preview=False):
if self. _config.id is not None:
request = WAExistsRequest(self._config)
result = request.send(encrypt=encrypt, preview=preview)
if result:
if result["status"] == "ok":
return result
elif result["status"] == "fail" and "reason" in result and result["reason"] == "blocked":
return result
else:
self._config.id = WATools.generateIdentity()
self.addParam("id", self._config.id)
res = super(WACodeRequest, self).send(parser, encrypt=encrypt, preview=preview)
return res
yowsup-3.2.3/yowsup/registration/existsrequest.py 0000664 0000000 0000000 00000001465 13464333726 0022470 0 ustar 00root root 0000000 0000000 from yowsup.common.http.warequest import WARequest
from yowsup.common.http.waresponseparser import JSONResponseParser
from yowsup.env import YowsupEnv
class WAExistsRequest(WARequest):
def __init__(self, config):
"""
:param config:
:type config: yowsup.config.v1.config.Config
"""
super(WAExistsRequest,self).__init__(config)
if config.id is None:
raise ValueError("Config does not contain id")
self.url = "v.whatsapp.net/v2/exist"
self.pvars = ["status", "reason", "sms_length", "voice_length", "result","param", "login", "type",
"chat_dns_domain", "edge_routing_info"
]
self.setParser(JSONResponseParser())
self.addParam("token", YowsupEnv.getCurrent().getToken(self._p_in))
yowsup-3.2.3/yowsup/registration/regrequest.py 0000664 0000000 0000000 00000003443 13464333726 0021724 0 ustar 00root root 0000000 0000000 '''
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
class WARegRequest(WARequest):
def __init__(self, config, code):
"""
:param config:
:type config: yowsup.config.vx.config.Config
:param code:
:type code: str
"""
super(WARegRequest,self).__init__(config)
if config.id is None:
raise ValueError("config.id is not set.")
self.addParam("code", code)
self.url = "v.whatsapp.net/v2/register"
self.pvars = ["status", "login", "type", "edge_routing_info", "chat_dns_domain"
"reason","retry_after"]
self.setParser(JSONResponseParser())
yowsup-3.2.3/yowsup/stacks/ 0000775 0000000 0000000 00000000000 13464333726 0015736 5 ustar 00root root 0000000 0000000 yowsup-3.2.3/yowsup/stacks/__init__.py 0000664 0000000 0000000 00000005174 13464333726 0020056 0 ustar 00root root 0000000 0000000 from .yowstack import YowStack, YowStackBuilder
from yowsup.layers.auth import 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.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.layers.noise.layer import YowNoiseLayer
from yowsup.layers.noise.layer_noise_segments import YowNoiseSegmentsLayer
YOWSUP_CORE_LAYERS = (
YowLoggerLayer,
YowCoderLayer,
YowNoiseLayer,
YowNoiseSegmentsLayer,
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-3.2.3/yowsup/stacks/yowstack.py 0000664 0000000 0000000 00000020076 13464333726 0020161 0 ustar 00root root 0000000 0000000 from yowsup.layers import YowParallelLayer
import time, logging, random
from yowsup.layers import YowLayer
from yowsup.layers.noise.layer import YowNoiseLayer
from yowsup.layers.noise.layer_noise_segments import YowNoiseSegmentsLayer
from yowsup.layers.auth import 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.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.env import YowsupEnv
from yowsup.common.constants import YowConstants
from yowsup.layers.axolotl import AxolotlSendLayer, AxolotlControlLayer, AxolotlReceivelayer
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
return self
def pushDefaultLayers(self):
defaultLayers = YowStackBuilder.getDefaultLayers()
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(groups = True, media = True, privacy = True, profiles = True):
coreLayers = YowStackBuilder.getCoreLayers()
protocolLayers = YowStackBuilder.getProtocolLayers(groups = groups, media=media, privacy=privacy, profiles=profiles)
allLayers = coreLayers
allLayers += (AxolotlControlLayer,)
allLayers += (YowParallelLayer((AxolotlSendLayer, AxolotlReceivelayer)),)
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,
YowNoiseLayer,
YowNoiseSegmentsLayer,
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._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):
while True:
try:
callback = self.__class__.__detachedQueue.get(False) #doesn't block
callback()
except Queue.Empty:
pass
time.sleep(0.1)
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-3.2.3/yowsup/structs/ 0000775 0000000 0000000 00000000000 13464333726 0016155 5 ustar 00root root 0000000 0000000 yowsup-3.2.3/yowsup/structs/__init__.py 0000664 0000000 0000000 00000000131 13464333726 0020261 0 ustar 00root root 0000000 0000000 from .protocolentity import ProtocolEntity
from .protocoltreenode import ProtocolTreeNode yowsup-3.2.3/yowsup/structs/protocolentity.py 0000664 0000000 0000000 00000002702 13464333726 0021626 0 ustar 00root root 0000000 0000000 from .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-3.2.3/yowsup/structs/protocoltreenode.py 0000664 0000000 0000000 00000011262 13464333726 0022120 0 ustar 00root root 0000000 0000000 import 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():
if val is None:
raise ValueError("value is none for attr %s" % key)
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+= ""+self.tag+">\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