Skip to content

Commit

Permalink
Merge branch 'release/2.4.48'
Browse files Browse the repository at this point in the history
  • Loading branch information
tgalal committed Dec 14, 2015
2 parents 4007ee5 + f64e6f4 commit a59ac41
Show file tree
Hide file tree
Showing 29 changed files with 414 additions and 140 deletions.
91 changes: 12 additions & 79 deletions README.md
Expand Up @@ -2,93 +2,26 @@

<a href="https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=Z9KKEUVYEY6BN" target="_blank"><img src="https://www.paypalobjects.com/en_US/i/btn/btn_donate_LG.gif" /></a>

## Updates (September 07, 2015)
Yowsup v2.4 is out, See [release notes](https://github.com/tgalal/yowsup/releases/tag/v2.4)
## Updates (December 14, 2015)
Yowsup v2.4.48 is out, See [release notes](https://github.com/tgalal/yowsup/releases/tag/v2.4.48)

### Updates (August 01, 2015)
Yowsup v2.3.185 is out, contains fixes in axolotl integration. See [release notes](https://github.com/tgalal/yowsup/releases/tag/v2.3.185)

### Updates (July 27, 2015)
Yowsup v2.3.183, see [release notes](https://github.com/tgalal/yowsup/releases/tag/v2.3.183)

### Updates (July 21, 2015)
Yowsup v2.3.167, see [release notes](https://github.com/tgalal/yowsup/releases/tag/v2.3.167)

### Updates (June 23, 2015)
Yowsup v2.3.123, see [release notes](https://github.com/tgalal/yowsup/releases/tag/v2.3.123)

### Updates (May 29, 2015)

Yowsup v2.3.84, see [release notes](https://github.com/tgalal/yowsup/releases/tag/v2.3.84)

### Updates (February 17, 2015)

Yowsup 2.2.78 is out, see [release notes](https://github.com/tgalal/yowsup/releases/tag/v2.2.78).

### Updates (January 12, 2015)

Yowsup 2.2.15 is out.

Image upload and send is now implemented. [Read here](https://github.com/tgalal/yowsup/wiki/Upload-and-send-Media) how to integrate in your code, or try it out with yowsup-cli

[Read full release notes](https://github.com/tgalal/yowsup/releases/tag/v2.2.15)

### Updates (January 1, 2015)

Happy new year!

P.S: Yowsup's [license changed](https://github.com/tgalal/yowsup#license) to GPLv3 (previously the MIT License was used).

### (December 31, 2014)

New features land in yowsup. You will need to re-install to pull new dependencies. Follow the [updated install instructions for your OS](#installation-updated-dec-31-2014).

A couple of highlights:

### End-to-End encryption

Yowsup now implements the new end-to-end encryption recently introduced in WhatsApp (AKA axolotl) (AKA textsecure). To activate in demos pass in '--moxie' switch.
Example:

> yowsup-cli demos --config /path/to/config --yowsup --moxie
This will make messages communication with WhatsApp platforms which support this feature encrypted. At the moment it's only Android, which means yowsup got this feature even before official WhatsApp clients on other platforms.

For platforms which do not support encryption, they will get plaintext messages as usual.

More technical details about axolotl in yowsup [here](https://github.com/tgalal/yowsup/wiki/End-to-End-encryption)

### New Send client demo

Use the send client demo in yowsup-cli to login, send a message and exit.

> yowsup-cli demos --config /path/to/config --send NUMBER "Hello world"
==========================================================

## Yowsup opened WhatsApp service under platforms!

Yowsup is a python library that enables you build application which use WhatsApp service. Yowsup has been used to create an unofficial WhatsApp client Nokia N9 through the Wazapp project which was in use by 200K + users as well as another fully featured unofficial client for Blackberry 10

## What's new in Yowsup 2

Everything! The old library code was so messed up that I was disgusted just by looking at it. I rewrote the library from ground up with a much more robust, extensible architecture and a much simpler and easier to read code.

__For devs, the update is breaking for any old code. While old code will stay in "legacy" branch for a while, it's advised that you upgrade your code. Unless your code is a full fledged WhatsApp application, migrating won't be a hard task.__
## Quickstart

Here is what you need to know about Yowsup 2.0 to get started: (Or quickly [jump to installation](#installation)):

* **[The new architecture](https://github.com/tgalal/yowsup/wiki/Architecture)**
* **[yowsup's architecture](https://github.com/tgalal/yowsup/wiki/Architecture)**
* **[Create a sample app](https://github.com/tgalal/yowsup/wiki/Sample-Application)**
* **[yowsup-cli 2.0](https://github.com/tgalal/yowsup/wiki/yowsup-cli-2.0)**
* **[yowsup-cli](https://github.com/tgalal/yowsup/wiki/yowsup-cli-2.0)**
* **[Yowsup development, debugging, maintainance and sanity](https://github.com/tgalal/yowsup/wiki/Yowsup-development,-debugging,-maintainance-and-sanity)**


## Installation
(Updated Jan 12, 2015)
## Installation

- Requires python2.6+, or python3.0 +
- Required python packages: python-dateutil,
- Required python packages: python-dateutil,
- Required python packages for end-to-end encryption: protobuf, pycrypto, python-axolotl-curve25519
- Required python packages for yowsup-cli: argparse, readline (or pyreadline for windows), pillow (for sending images)

Expand All @@ -110,14 +43,14 @@ Because of a bug with python-dateutil package you might get permission error for
```
python setup.py install
```
Administrators privileges might be required, if so then run with 'sudo'
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
Expand All @@ -126,7 +59,7 @@ compiler=mingw32
- Install [zlib](http://www.zlib.net/)
- ```python setup.py install```

If pycrypto fails to install with some "chmod error". You can install it separately using something like
If pycrypto fails to install with some "chmod error". You can install it separately using something like
```easy_install http://www.voidspace.org.uk/downloads/pycrypto26/pycrypto-2.6.win32-py2.7.exe```

or for python3 from:
Expand All @@ -139,8 +72,8 @@ and then rerun the install command again

Special thanks to:

- [CODeRUS](https://github.com/CODeRUS)
- [mgp25](https://github.com/mgp25)
- [CODeRUS](https://github.com/CODeRUS)
- [mgp25](https://github.com/mgp25)
- [SikiFn](https://github.com/SikiFn)
- [0xTryCatch](https://github.com/0xTryCatch)
- [shirioko](https://github.com/shirioko)
Expand Down
2 changes: 1 addition & 1 deletion yowsup/__init__.py
@@ -1,2 +1,2 @@
__version__ = "2.4"
__version__ = "2.4.48"
__author__ = "Tarek Galal"
18 changes: 11 additions & 7 deletions yowsup/common/tools.py
Expand Up @@ -85,13 +85,13 @@ class TimeTools:
def parseIso(iso):
d=datetime.datetime(*map(int, re.split('[^\d]', iso)[:-1]))
return d
@staticmethod

@staticmethod
def utcToLocal(dt):
utc = tz.gettz('UTC')
local = tz.tzlocal()
dtUtc = dt.replace(tzinfo=utc)

return dtUtc.astimezone(local)

@staticmethod
Expand Down Expand Up @@ -128,6 +128,9 @@ def scaleImage(infile, outfile, imageFormat, width, height):
if ModuleTools.INSTALLED_PIL():
from PIL import Image
im = Image.open(infile)
#Convert P mode images
if im.mode != "RGB":
im = im.convert("RGB")
im.thumbnail((width, height))
im.save(outfile, imageFormat)
return True
Expand All @@ -148,10 +151,11 @@ def getImageDimensions(imageFile):
@staticmethod
def generatePreviewFromImage(image):
fd, path = tempfile.mkstemp()
fileObj = os.fdopen(fd, "rb+")

preview = None
if ImageTools.scaleImage(image, fileObj, "JPEG", YowConstants.PREVIEW_WIDTH, YowConstants.PREVIEW_HEIGHT):
if ImageTools.scaleImage(image, path, "JPEG", YowConstants.PREVIEW_WIDTH, YowConstants.PREVIEW_HEIGHT):
fileObj = os.fdopen(fd, "rb+")
fileObj.seek(0)
preview = fileObj.read()
fileObj.close()
return preview
fileObj.close()
return preview
43 changes: 39 additions & 4 deletions yowsup/demos/cli/layer.py
Expand Up @@ -47,6 +47,7 @@ def __init__(self):
self.connected = False
self.username = None
self.sendReceipts = True
self.sendRead = True
self.disconnectAction = self.__class__.DISCONNECT_ACTION_PROMPT
self.credentials = None

Expand Down Expand Up @@ -223,6 +224,35 @@ def onError(errorIqEntity, originalIqEntity):
else:
logger.error("Python PIL library is not installed, can't set profile picture")

@clicmd("Get profile privacy")
def profile_getPrivacy(self):
if self.assertConnected():
def onSuccess(resultIqEntity, originalIqEntity):
self.output("Profile privacy is: %s" %(resultIqEntity))

def onError(errorIqEntity, originalIqEntity):
logger.error("Error getting profile privacy")

iq = GetPrivacyIqProtocolEntity()
self._sendIq(iq, onSuccess, onError)

@clicmd("Profile privacy. value=all|contacts|none names=profile|status|last. Names are comma separated, defaults to all.")
def profile_setPrivacy(self, value="all", names=None):
if self.assertConnected():
def onSuccess(resultIqEntity, originalIqEntity):
self.output("Profile privacy set to: %s" %(resultIqEntity))

def onError(errorIqEntity, originalIqEntity):
logger.error("Error setting profile privacy")
try:
names = [name for name in names.split(',')] if names else None
iq = SetPrivacyIqProtocolEntity(value, names)
self._sendIq(iq, onSuccess, onError)
except Exception as inst:
self.output(inst.message)
return self.print_usage()


########### groups

@clicmd("List all groups you belong to", 5)
Expand Down Expand Up @@ -395,6 +425,12 @@ def state_typing(self, jid):
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():
Expand Down Expand Up @@ -492,8 +528,8 @@ def onMessage(self, message):

self.output(output, tag = None, prompt = not self.sendReceipts)
if self.sendReceipts:
self.toLower(message.ack())
self.output("Sent delivered receipt", tag = "Message %s" % message.getId())
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):
Expand All @@ -504,7 +540,7 @@ def getMediaMessageBody(self, message):
return self.getDownloadableMediaMessageBody(message)
else:
return "[Media Type: %s]" % message.getMediaType()


def getDownloadableMediaMessageBody(self, message):
return "[Media Type:{media_type}, Size:{media_size}, URL:{media_url}]".format(
Expand Down Expand Up @@ -570,4 +606,3 @@ def __str__(self):
@clicmd("Print this message")
def help(self):
self.print_usage()

7 changes: 3 additions & 4 deletions yowsup/demos/contacts/stack.py
Expand Up @@ -9,8 +9,7 @@
from yowsup.layers.protocol_acks import YowAckProtocolLayer
from yowsup.layers.logger import YowLoggerLayer
from yowsup.layers.protocol_contacts import YowContactsIqProtocolLayer
from yowsup.common import YowConstants
from yowsup import env
from yowsup.layers import YowParallelLayer

class YowsupSyncStack(object):
def __init__(self, credentials, contacts, encryptionEnabled = False):
Expand All @@ -24,7 +23,7 @@ def __init__(self, credentials, contacts, encryptionEnabled = False):
from yowsup.layers.axolotl import YowAxolotlLayer
layers = (
SyncLayer,
(YowAuthenticationProtocolLayer, YowContactsIqProtocolLayer, YowReceiptProtocolLayer, YowAckProtocolLayer),
YowParallelLayer([YowAuthenticationProtocolLayer, YowContactsIqProtocolLayer, YowReceiptProtocolLayer, YowAckProtocolLayer]),
YowAxolotlLayer,
YowLoggerLayer,
YowCoderLayer,
Expand All @@ -35,7 +34,7 @@ def __init__(self, credentials, contacts, encryptionEnabled = False):
else:
layers = (
SyncLayer,
(YowAuthenticationProtocolLayer, YowContactsIqProtocolLayer, YowReceiptProtocolLayer, YowAckProtocolLayer),
YowParallelLayer([YowAuthenticationProtocolLayer, YowContactsIqProtocolLayer, YowReceiptProtocolLayer, YowAckProtocolLayer]),
YowLoggerLayer,
YowCoderLayer,
YowCryptLayer,
Expand Down
7 changes: 3 additions & 4 deletions yowsup/demos/echoclient/stack.py
Expand Up @@ -12,16 +12,15 @@
from yowsup.layers.logger import YowLoggerLayer
from yowsup.layers.protocol_iq import YowIqProtocolLayer
from yowsup.layers.protocol_calls import YowCallsProtocolLayer
from yowsup.common import YowConstants
from yowsup import env
from yowsup.layers import YowParallelLayer

class YowsupEchoStack(object):
def __init__(self, credentials, encryptionEnabled = False):
if encryptionEnabled:
from yowsup.layers.axolotl import YowAxolotlLayer
layers = (
EchoLayer,
(YowAuthenticationProtocolLayer, YowMessagesProtocolLayer, YowReceiptProtocolLayer, YowAckProtocolLayer, YowMediaProtocolLayer, YowIqProtocolLayer, YowCallsProtocolLayer),
YowParallelLayer([YowAuthenticationProtocolLayer, YowMessagesProtocolLayer, YowReceiptProtocolLayer, YowAckProtocolLayer, YowMediaProtocolLayer, YowIqProtocolLayer, YowCallsProtocolLayer]),
YowAxolotlLayer,
YowLoggerLayer,
YowCoderLayer,
Expand All @@ -32,7 +31,7 @@ def __init__(self, credentials, encryptionEnabled = False):
else:
layers = (
EchoLayer,
(YowAuthenticationProtocolLayer, YowMessagesProtocolLayer, YowReceiptProtocolLayer, YowAckProtocolLayer, YowMediaProtocolLayer, YowIqProtocolLayer, YowCallsProtocolLayer),
YowParallelLayer([YowAuthenticationProtocolLayer, YowMessagesProtocolLayer, YowReceiptProtocolLayer, YowAckProtocolLayer, YowMediaProtocolLayer, YowIqProtocolLayer, YowCallsProtocolLayer]),
YowLoggerLayer,
YowCoderLayer,
YowCryptLayer,
Expand Down
8 changes: 4 additions & 4 deletions yowsup/demos/sendclient/stack.py
Expand Up @@ -9,8 +9,8 @@
from yowsup.layers.protocol_receipts import YowReceiptProtocolLayer
from yowsup.layers.protocol_acks import YowAckProtocolLayer
from yowsup.layers.logger import YowLoggerLayer
from yowsup.common import YowConstants
from yowsup import env
from yowsup.layers import YowParallelLayer


class YowsupSendStack(object):
def __init__(self, credentials, messages, encryptionEnabled = False):
Expand All @@ -24,7 +24,7 @@ def __init__(self, credentials, messages, encryptionEnabled = False):
from yowsup.layers.axolotl import YowAxolotlLayer
layers = (
SendLayer,
(YowAuthenticationProtocolLayer, YowMessagesProtocolLayer, YowReceiptProtocolLayer, YowAckProtocolLayer),
YowParallelLayer([YowAuthenticationProtocolLayer, YowMessagesProtocolLayer, YowReceiptProtocolLayer, YowAckProtocolLayer]),
YowAxolotlLayer,
YowLoggerLayer,
YowCoderLayer,
Expand All @@ -35,7 +35,7 @@ def __init__(self, credentials, messages, encryptionEnabled = False):
else:
layers = (
SendLayer,
(YowAuthenticationProtocolLayer, YowMessagesProtocolLayer, YowReceiptProtocolLayer, YowAckProtocolLayer),
YowParallelLayer([YowAuthenticationProtocolLayer, YowMessagesProtocolLayer, YowReceiptProtocolLayer, YowAckProtocolLayer]),
YowLoggerLayer,
YowCoderLayer,
YowCryptLayer,
Expand Down
32 changes: 17 additions & 15 deletions yowsup/env/env_android.py
@@ -1,25 +1,27 @@
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 = "MYFrqqEFgD/DG5Z9E+zaSA=="
"BAcTC1NhbnRhIENsYXJhMRYwFAYDVQQKEw1XaGF0c0FwcCBJbmMuMRQwEgYDVQQLEwtFbmdpbmVlcmluZzEUMBIGA1UEAxMLQnJ" \
"pYW4gQWN0b24wHhcNMTAwNjI1MjMwNzE2WhcNNDQwMjE1MjMwNzE2WjB8MQswCQYDVQQGEwJVUzETMBEGA1UECBMKQ2FsaWZvcm5" \
"pYTEUMBIGA1UEBxMLU2FudGEgQ2xhcmExFjAUBgNVBAoTDVdoYXRzQXBwIEluYy4xFDASBgNVBAsTC0VuZ2luZWVyaW5nMRQwEg" \
"YDVQQDEwtCcmlhbiBBY3RvbjCCAbgwggEsBgcqhkjOOAQBMIIBHwKBgQD9f1OBHXUSKVLfSpwu7OTn9hG3UjzvRADDHj+AtlEm" \
"aUVdQCJR+1k9jVj6v8X1ujD2y5tVbNeBO4AdNG/yZmC3a5lQpaSfn+gEexAiwk+7qdf+t8Yb+DtX58aophUPBPuD9tPFHsMCN" \
"VQTWhaRMvZ1864rYdcq7/IiAxmd0UgBxwIVAJdgUI8VIwvMspK5gqLrhAvwWBz1AoGBAPfhoIXWmz3ey7yrXDa4V7l5lK+7+jr" \
"qgvlXTAs9B4JnUVlXjrrUWU/mcQcQgYC0SRZxI+hMKBYTt88JMozIpuE8FnqLVHyNKOCjrh4rs6Z1kW6jfwv6ITVi8ftiegEkO" \
"8yk8b6oUZCJqIPf4VrlnwaSi2ZegHtVJWQBTDv+z0kqA4GFAAKBgQDRGYtLgWh7zyRtQainJfCpiaUbzjJuhMgo4fVWZIvXHaS" \
"HBU1t5w//S0lDK2hiqkj8KpMWGywVov9eZxZy37V26dEqr/c2m5qZ0E+ynSu7sqUD7kGx/zeIcGT0H+KAVgkGNQCo5Uc0koLRW" \
"YHNtYoIvt5R3X6YZylbPftF/8ayWTALBgcqhkjOOAQDBQADLwAwLAIUAKYCp0d6z4QQdyN74JDfQ2WCyi8CFDUM4CaNB+ceVXd" \
"KtOrNTQcc0e+t"

_MD5_CLASSES = "vIDGGxIcIxeBP0GoG8yL8g=="
_KEY = "/UIGKU1FVQa+ATM2A0za7G2KI9S/CwPYjgAbc67v7ep42eO/WeTLx1lb1cHwxpsEgF4+PmYpLd2YpGUdX/A2JQitsHzDwgcdBpUf7psX1BU="

_VERSION = "2.12.287"
_OS_NAME= "Android"
_VERSION = "2.12.357"
_OS_NAME = "Android"
_OS_VERSION = "4.3"
_DEVICE_NAME = "GalaxyS3"
_AXOLOTL = True
Expand Down

0 comments on commit a59ac41

Please sign in to comment.