123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370 |
- #!/usr/bin/env python
- __version__ = "2.0.15"
- __author__ = "Tarek Galal"
- import sys, argparse, yowsup, logging
- from yowsup.env import YowsupEnv
- HELP_CONFIG = """
- ############# Yowsup Configuration Sample ###########
- #
- # ====================
- # The file contains info about your WhatsApp account. This is used during registration and login.
- # You can define or override all fields in the command line args as well.
- #
- # Country code. See http://www.ipipi.com/help/telephone-country-codes.htm. This is now required.
- cc=49
- #
- # Your full phone number including the country code you defined in 'cc', without preceding '+' or '00'
- phone=491234567890
- #
- # You obtain this password when you register using Yowsup.
- password=NDkxNTIyNTI1NjAyMkBzLndoYXRzYXBwLm5ldA==
- #######################################################
- """
- 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)
- self.add_argument("-v", "--version",
- action = "store_true",
- help = "Print version info and exit"
- )
- self.add_argument("-d", "--debug",
- action = "store_true",
- help = "Show debug messages"
- )
- self.add_argument("--help-config", help = "Prints a config file sample", action = "store_true")
- self.args = {}
- def getArgs(self):
- return self.parse_args()
- def getConfig(self, config):
- try:
- f = open(config)
- out = {}
- for l in f:
- line = l.strip()
- if len(line) and line[0] not in ('#',';'):
- prep = line.split('#', 1)[0].split(';', 1)[0].split('=', 1)
- varname = prep[0].strip()
- val = prep[1].strip()
- out[varname.replace('-', '_')] = val
- return out
- except IOError:
- print("Invalid config path: %s" % config)
- sys.exit(1)
- def process(self):
- self.args = vars(self.parse_args())
- if self.args["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)
- if self.args["help_config"]:
- print(HELP_CONFIG)
- sys.exit(0)
- def printInfoText(self):
- print(CR_TEXT.format(cliVersion=__version__, yowsupVersion=yowsup.__version__))
- class RegistrationArgParser(YowArgParser):
- def __init__(self, *args, **kwargs):
- super(RegistrationArgParser, self).__init__(*args, **kwargs)
- self.description = "WhatsApp Registration options"
- configGroup = self.add_argument_group("Configuration options",
- description = "Config file is optional. Other configuration arguments have higher priority if given, and will override those specified in the config file")
- configGroup.add_argument("-c", '--config',
- action = "store",
- help = 'Path to config file. If this is not set then you must set at least --phone and --cc arguments')
- configGroup.add_argument('-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")
- configGroup.add_argument("-n", '--mnc',
- action = "store",
- help = "Mobile Network Code. Check your mnc from https://en.wikipedia.org/wiki/Mobile_country_code")
- # configGroup.add_argument("-M", '--sim-mcc',
- # action = "store",
- # help = "Mobile Country Code. Check your mcc here: https://en.wikipedia.org/wiki/Mobile_country_code"
- # )
- # configGroup.add_argument("-N", '--sim-mnc',
- # action= "store",
- # help = "SIM MNC"
- # )
- configGroup.add_argument("-p", '--phone',
- action= "store",
- help = " Your full phone number including the country code you defined in 'cc', without preceeding '+' or '00'")
- configGroup.add_argument("-C", '--cc',
- action = "store",
- help = "Country code. See http://www.ipipi.com/networkList.do. This is now required")
- # configGroup.add_argument("-i", '--id',
- # action="store",
- # help = "Identity"
- # )
- regSteps = self.add_argument_group("Modes")
- regSteps = regSteps.add_mutually_exclusive_group()
- regSteps.add_argument("-r", '--requestcode', help='Request the digit registration code from Whatsapp.', action="store", required=False, metavar="(sms|voice)")
- regSteps.add_argument("-R", '--register', help='Register account on Whatsapp using the code you previously received', action="store", required=False, metavar="code")
- def process(self):
- super(RegistrationArgParser, self).process()
- config = self.getConfig(self.args["config"]) if self.args["config"] else {}
- if self.args["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"]
- if self.args["cc" ] : config["cc"] = self.args["cc"]
- #if self.args["sim_mnc"] : config["sim_mnc"] = self.args["sim_mnc"]
- #if self.args["sim_mcc"] : config["sim_mcc"] = self.args["sim_mcc"]
- if not "mcc" in config: config["mcc"] = "000"
- if not "mnc" in config: config["mnc"] = "000"
- if not "sim_mcc" in config: config["sim_mcc"] = "000"
- if not "sim_mnc" in config: config["sim_mnc"] = "000"
- try:
- assert self.args["requestcode"] or self.args["register"], "Must specify one of the modes -r/-R"
- assert "cc" in config, "Must specify cc (country code)"
- assert "phone" in config, "Must specify phone number"
- except AssertionError as e:
- print(e)
- print("\n")
- return False
- if not config["phone"].startswith(config["cc"]):
- print("Error, phone number does not start with the specified country code\n")
- return False
- config["phone"] = config["phone"][len(config["cc"]):]
- if self.args["requestcode"]:
- self.handleRequestCode(self.args["requestcode"], config)
- elif self.args["register"]:
- self.handleRegister(self.args["register"], config)
- else:
- return False
- return True
- def handleRequestCode(self, method, config):
- from yowsup.registration import WACodeRequest
- self.printInfoText()
- codeReq = WACodeRequest(config["cc"],
- config["phone"],
- config["mcc"],
- config["mnc"],
- config["mcc"],
- config["mnc"],
- method
- )
- result = codeReq.send()
- print(self.resultToString(result))
- def handleRegister(self, code, config):
- from yowsup.registration import WARegRequest
- self.printInfoText()
- code = code.replace('-', '')
- req = WARegRequest(config["cc"], config["phone"], code)
- result = req.send()
- print(self.resultToString(result))
- def resultToString(self, result):
- unistr = str if sys.version_info >= (3, 0) else unicode
- out = []
- for k, v in result.items():
- if v is None:
- continue
- out.append("%s: %s" %(k, v.encode("utf-8") if type(v) is unistr else v))
- return "\n".join(out)
- class DemosArgParser(YowArgParser):
- def __init__(self, *args, **kwargs):
- super(DemosArgParser, self).__init__(*args, **kwargs)
- self.description = "Run a yowsup demo"
- configGroup = self.add_argument_group("Configuration options for demos")
- credentialsOpts = configGroup.add_mutually_exclusive_group()
- credentialsOpts.add_argument("-l", "--login", action="store", metavar="phone:b64password",
- help = "WhatsApp login credentials, in the format phonenumber:password, where password is base64 encoded.")
- credentialsOpts.add_argument("-c", "--config", action="store",
- help = "Path to config file containing authentication info. For more info about config format use --help-config")
- configGroup.add_argument('-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")
- cmdopts.add_argument('-y', '--yowsup', action = "store_true", help = "Start the Yowsup command line client")
- echoOpts = self.add_argument_group("Echo client demo")
- echoOpts.add_argument('-e', '--echo', action = "store_true", help = "Start the Yowsup Echo client")
- sendOpts = self.add_argument_group("Send client demo")
- sendOpts.add_argument('-s', '--send', action="store", help = "Send a message to specified phone number, "
- "wait for server receipt and exit",
- metavar=("phone", "message"), nargs = 2)
- syncContacts = self.add_argument_group("Sync contacts")
- syncContacts.add_argument('-S','--sync', action = "store" , help = "Sync ( check valid ) whatsapp contacts",metavar =("contacts"))
- def process(self):
- super(DemosArgParser, self).process()
- if self.args["env"]:
- YowsupEnv.setEnv(self.args["env"])
- if self.args["yowsup"]:
- self.startCmdline()
- elif self.args["echo"]:
- self.startEcho()
- elif self.args["send"]:
- self.startSendClient()
- elif self.args["sync"]:
- self.startSyncContacts()
- else:
- return False
- return True
- def _getCredentials(self):
- if self.args["login"]:
- return tuple(self.args["login"].split(":"))
- elif self.args["config"]:
- config = self.getConfig(self.args["config"])
- assert "password" in config and "phone" in config, "Must specify at least phone number and password in config file"
- return config["phone"], config["password"]
- else:
- return None
- def startCmdline(self):
- from yowsup.demos import cli
- credentials = self._getCredentials()
- if not credentials:
- print("Error: You must specify a configuration method")
- sys.exit(1)
- self.printInfoText()
- stack = cli.YowsupCliStack(credentials, not self.args["unmoxie"])
- stack.start()
- def startEcho(self):
- from yowsup.demos import echoclient
- credentials = self._getCredentials()
- if not credentials:
- print("Error: You must specify a configuration method")
- sys.exit(1)
- try:
- self.printInfoText()
- stack = echoclient.YowsupEchoStack(credentials, not self.args["unmoxie"])
- stack.start()
- except KeyboardInterrupt:
- print("\nYowsdown")
- sys.exit(0)
- def startSendClient(self):
- from yowsup.demos import sendclient
- credentials = self._getCredentials()
- if not credentials:
- print("Error: You must specify a configuration method")
- sys.exit(1)
- try:
- self.printInfoText()
- stack = sendclient.YowsupSendStack(credentials, [([self.args["send"][0], self.args["send"][1]])],
- not self.args["unmoxie"])
- stack.start()
- except KeyboardInterrupt:
- print("\nYowsdown")
- sys.exit(0)
- def startSyncContacts(self):
- from yowsup.demos import contacts
- credentials = self._getCredentials()
- if not credentials:
- print("Error: You must specify a configuration method")
- sys.exit(1)
- try:
- self.printInfoText()
- stack = contacts.YowsupSyncStack(credentials,self.args["sync"].split(','), not self.args["unmoxie"])
- stack.start()
- except KeyboardInterrupt:
- print("\nYowsdown")
- sys.exit(0)
- if __name__ == "__main__":
- args = sys.argv
- if(len(args) > 1):
- del args[0]
- modeDict = {
- "demos": DemosArgParser,
- "registration": RegistrationArgParser,
- "version": None
- }
- if(len(args) == 0 or args[0] not in modeDict):
- print("Available commands:\n===================")
- print(", ".join(modeDict.keys()))
- sys.exit(1)
- mode = args[0]
- if mode == "version":
- print("yowsup-cli v%s\nUsing yowsup v%s" % (__version__, yowsup.__version__))
- sys.exit(0)
- else:
- parser = modeDict[mode]()
- if not parser.process():
- parser.print_help()
|