diff --git a/README.md b/README.md index 74182d632..8a2ee169b 100644 --- a/README.md +++ b/README.md @@ -2,8 +2,8 @@ -## Updates (March 31, 2016) -Yowsup v2.4.97 is out, See [release notes](https://github.com/tgalal/yowsup/releases/tag/v2.4.97) +## Updates (April 1, 2016) +Yowsup v2.4.102 is out, See [release notes](https://github.com/tgalal/yowsup/releases/tag/v2.4.102) ========================================================== diff --git a/yowsup-cli b/yowsup-cli index a7e22f2b0..c246e1e7c 100755 --- a/yowsup-cli +++ b/yowsup-cli @@ -1,8 +1,9 @@ #!/usr/bin/env python -__version__ = "2.0.13" +__version__ = "2.0.15" __author__ = "Tarek Galal" import sys, argparse, yowsup, logging +from yowsup.env import YowsupEnv HELP_CONFIG = """ ############# Yowsup Configuration Sample ########### @@ -22,8 +23,25 @@ password=NDkxNTIyNTI1NjAyMkBzLndoYXRzYXBwLm5ldA== ####################################################### """ + +CR_TEXT = """yowsup-cli v{cliVersion} +yowsup v{yowsupVersion} + +Copyright (c) 2012-2016 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") + class YowArgParser(argparse.ArgumentParser): def __init__(self, *args, **kwargs): super(YowArgParser, self).__init__(*args, **kwargs) @@ -60,6 +78,12 @@ class YowArgParser(argparse.ArgumentParser): def process(self): self.args = vars(self.parse_args()) + + if self.args["debug"]: + logging.basicConfig(level = logging.DEBUG) + else: + logging.basicConfig(level = logging.INFO) + if self.args["version"]: print("yowsup-cli v%s\nUsing yowsup v%s" % (__version__, yowsup.__version__)) sys.exit(0) @@ -68,11 +92,9 @@ class YowArgParser(argparse.ArgumentParser): print(HELP_CONFIG) sys.exit(0) - if self.args["debug"]: - logging.basicConfig(level = logging.DEBUG) - else: - logging.basicConfig(level = logging.INFO) + def printInfoText(self): + print(CR_TEXT.format(cliVersion=__version__, yowsupVersion=yowsup.__version__)) class RegistrationArgParser(YowArgParser): def __init__(self, *args, **kwargs): @@ -81,9 +103,16 @@ class RegistrationArgParser(YowArgParser): configGroup = self.add_argument_group("Configuration options", description = "Config file is optional. Other configuration arguments have higher priority if given, and will override those specified in the config file") + configGroup.add_argument("-c", '--config', action = "store", help = 'Path to config file. If this is not set then you must set at least --phone and --cc arguments') + + configGroup.add_argument('-E', '--env', + action = "store", + help = "Set the environment yowsup simulates", + choices = YowsupEnv.getRegisteredEnvs()) + configGroup.add_argument("-m", '--mcc', action = "store", help = "Mobile Country Code. Check your mcc here: https://en.wikipedia.org/wiki/Mobile_country_code") @@ -107,7 +136,6 @@ class RegistrationArgParser(YowArgParser): action = "store", help = "Country code. See http://www.ipipi.com/networkList.do. This is now required") - # configGroup.add_argument("-i", '--id', # action="store", # help = "Identity" @@ -124,6 +152,9 @@ class RegistrationArgParser(YowArgParser): config = self.getConfig(self.args["config"]) if self.args["config"] else {} + if self.args["env"]: + YowsupEnv.setEnv(self.args["env"]) + if self.args["mcc"] : config["mcc"] = self.args["mcc"] if self.args["mnc"] : config["mnc"] = self.args["mnc"] if self.args["phone"] : config["phone"] = self.args["phone"] @@ -165,6 +196,7 @@ class RegistrationArgParser(YowArgParser): def handleRequestCode(self, method, config): from yowsup.registration import WACodeRequest + self.printInfoText() codeReq = WACodeRequest(config["cc"], config["phone"], config["mcc"], @@ -178,6 +210,7 @@ class RegistrationArgParser(YowArgParser): def handleRegister(self, code, config): from yowsup.registration import WARegRequest + self.printInfoText() code = code.replace('-', '') req = WARegRequest(config["cc"], config["phone"], code) result = req.send() @@ -205,6 +238,11 @@ class DemosArgParser(YowArgParser): credentialsOpts.add_argument("-c", "--config", action="store", help = "Path to config file containing authentication info. For more info about config format use --help-config") + configGroup.add_argument('-E', '--env', + action = "store", + help = "Set the environment yowsup simulates", + choices = YowsupEnv.getRegisteredEnvs()) + configGroup.add_argument("-M", "--unmoxie", action="store_true", help="Disable E2E Encryption") cmdopts = self.add_argument_group("Command line interface demo") @@ -223,6 +261,9 @@ class DemosArgParser(YowArgParser): def process(self): super(DemosArgParser, self).process() + if self.args["env"]: + YowsupEnv.setEnv(self.args["env"]) + if self.args["yowsup"]: self.startCmdline() elif self.args["echo"]: @@ -251,6 +292,7 @@ class DemosArgParser(YowArgParser): if not credentials: print("Error: You must specify a configuration method") sys.exit(1) + self.printInfoText() stack = cli.YowsupCliStack(credentials, not self.args["unmoxie"]) stack.start() @@ -261,6 +303,7 @@ class DemosArgParser(YowArgParser): print("Error: You must specify a configuration method") sys.exit(1) try: + self.printInfoText() stack = echoclient.YowsupEchoStack(credentials, not self.args["unmoxie"]) stack.start() except KeyboardInterrupt: @@ -275,6 +318,7 @@ class DemosArgParser(YowArgParser): sys.exit(1) try: + self.printInfoText() stack = sendclient.YowsupSendStack(credentials, [([self.args["send"][0], self.args["send"][1]])], not self.args["unmoxie"]) stack.start() @@ -289,6 +333,7 @@ class DemosArgParser(YowArgParser): print("Error: You must specify a configuration method") sys.exit(1) try: + self.printInfoText() stack = contacts.YowsupSyncStack(credentials,self.args["sync"].split(','), not self.args["unmoxie"]) stack.start() except KeyboardInterrupt: diff --git a/yowsup/__init__.py b/yowsup/__init__.py index 9992dd898..74c4c97b3 100644 --- a/yowsup/__init__.py +++ b/yowsup/__init__.py @@ -1,2 +1,2 @@ -__version__ = "2.4.98" +__version__ = "2.4.102" __author__ = "Tarek Galal" diff --git a/yowsup/common/http/warequest.py b/yowsup/common/http/warequest.py index 86d9f69de..c847be894 100644 --- a/yowsup/common/http/warequest.py +++ b/yowsup/common/http/warequest.py @@ -1,8 +1,7 @@ import urllib,sys, os, logging import hashlib from .waresponseparser import ResponseParser -from yowsup.env import AndroidYowsupEnv -CURRENT_ENV = AndroidYowsupEnv() +from yowsup.env import YowsupEnv if sys.version_info < (3, 0): import httplib @@ -36,8 +35,6 @@ def __init__(self): self.sent = False self.response = None - - def setParsableVariables(self, pvars): self.pvars = pvars @@ -63,7 +60,7 @@ def clearParams(self): self.params = [] def getUserAgent(self): - return CURRENT_ENV.getUserAgent() + return YowsupEnv.getCurrent().getUserAgent() def send(self, parser = None): diff --git a/yowsup/env/__init__.py b/yowsup/env/__init__.py index 1bcd29bfa..e2ac66542 100644 --- a/yowsup/env/__init__.py +++ b/yowsup/env/__init__.py @@ -1,4 +1,3 @@ +from .env import YowsupEnv from .env_android import AndroidYowsupEnv from .env_s40 import S40YowsupEnv - -CURRENT_ENV = S40YowsupEnv() diff --git a/yowsup/env/env.py b/yowsup/env/env.py index 9a0c3d33f..7c7c1a48b 100644 --- a/yowsup/env/env.py +++ b/yowsup/env/env.py @@ -1,9 +1,54 @@ import abc -class YowsupEnv(object): - __metaclass__ = abc.ABCMeta +import logging +from six import with_metaclass + +logger = logging.getLogger(__name__) + +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/{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): + if cls.__CURR is None: + newEnvName = cls.getRegisteredEnvs()[0] + logger.debug("Env not set, setting it to %s" % newEnvName ) + cls.setEnv(newEnvName) + return cls.__CURR + @abc.abstractmethod def getToken(self, phoneNumber): pass @@ -38,4 +83,3 @@ def getUserAgent(self): OS_VERSION = self.getOSVersion(), DEVICE_NAME = self.getDeviceName() ) - diff --git a/yowsup/registration/coderequest.py b/yowsup/registration/coderequest.py index 8bbb5ab03..5d76187a9 100644 --- a/yowsup/registration/coderequest.py +++ b/yowsup/registration/coderequest.py @@ -1,11 +1,9 @@ from yowsup.common.http.warequest import WARequest from yowsup.common.http.waresponseparser import JSONResponseParser -# from yowsup.env import CURRENT_ENV from yowsup.common.tools import StorageTools, WATools from yowsup.registration.existsrequest import WAExistsRequest -from yowsup.env import AndroidYowsupEnv +from yowsup.env import YowsupEnv import random, hashlib, os -CURRENT_ENV = AndroidYowsupEnv() class WACodeRequest(WARequest): @@ -40,7 +38,7 @@ def __init__(self,cc, p_in, mcc= "000", mnc = "000", sim_mcc = "000", sim_mnc = self.addParam("extexist", "1") self.addParam("extstate", "1") - self.addParam("token", CURRENT_ENV.getToken(p_in)) + self.addParam("token", YowsupEnv.getCurrent().getToken(p_in)) self.url = "v.whatsapp.net/v2/code" @@ -63,4 +61,3 @@ def send(self, parser = None): if res["status"] == "sent": StorageTools.writeIdentity(self.cc + self.p_in, self.__id) return res - diff --git a/yowsup/registration/existsrequest.py b/yowsup/registration/existsrequest.py index 52f0047d4..78a446ae9 100644 --- a/yowsup/registration/existsrequest.py +++ b/yowsup/registration/existsrequest.py @@ -1,9 +1,8 @@ from yowsup.common.http.warequest import WARequest from yowsup.common.http.waresponseparser import JSONResponseParser -from yowsup.env import CURRENT_ENV - +from yowsup.env import YowsupEnv class WAExistsRequest(WARequest): - + def __init__(self,cc, p_in, idx): super(WAExistsRequest,self).__init__() @@ -12,7 +11,7 @@ def __init__(self,cc, p_in, idx): self.addParam("id", idx) self.addParam("lg", "en") self.addParam("lc", "GB") - self.addParam("token", CURRENT_ENV.getToken(p_in)) + self.addParam("token", YowsupEnv.getCurrent().getToken(p_in)) self.url = "v.whatsapp.net/v2/exist" @@ -24,4 +23,4 @@ def __init__(self,cc, p_in, idx): def send(self, parser = None): res = super(WAExistsRequest, self).send(parser) - return res \ No newline at end of file + return res diff --git a/yowsup/stacks/yowstack.py b/yowsup/stacks/yowstack.py index b360fe623..81236e7dc 100644 --- a/yowsup/stacks/yowstack.py +++ b/yowsup/stacks/yowstack.py @@ -20,7 +20,7 @@ from yowsup.layers.protocol_privacy import YowPrivacyProtocolLayer from yowsup.layers.protocol_profiles import YowProfilesProtocolLayer from yowsup.layers.protocol_calls import YowCallsProtocolLayer -from yowsup import env +from yowsup.env import YowsupEnv from yowsup.common.constants import YowConstants import inspect try: @@ -131,7 +131,7 @@ def __init__(self, stackClassesArr = None, reversed = True, props = None): self.setProp(YowNetworkLayer.PROP_ENDPOINT, YowConstants.ENDPOINTS[random.randint(0,len(YowConstants.ENDPOINTS)-1)]) self.setProp(YowCoderLayer.PROP_DOMAIN, YowConstants.DOMAIN) - self.setProp(YowCoderLayer.PROP_RESOURCE, env.CURRENT_ENV.getResource()) + self.setProp(YowCoderLayer.PROP_RESOURCE, YowsupEnv.getCurrent().getResource()) self._construct()