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) YowsupEnv.setEnv("android") config_manager = ConfigManager() profile_name = None config_loaded_from_profile = True if self.args["config"]: config = config_manager.load(self.args["config"]) if not os.path.isfile(self.args["config"]): profile_name = self.args["config"] elif not self.args["config"].startswith( StorageTools.getStorageForProfile(config.phone)): config_loaded_from_profile = False else: raise ValueError("Must specify --config") if config is None: config = Config() if not config_loaded_from_profile: # config file was explicitly specified and is not that of profile, # load profile config and override values internal_config = config_manager.load(config.phone, profile_only=True) if internal_config is not None: for property in config.keys(): if property != "version" and config[property] is not None: internal_config[property] = config[property] config = internal_config if self._profile is None or self._profile.config is None: self._profile = YowProfile(profile_name or config.phone, config) if self._profile.config.phone is None: print("Invalid config") sys.exit(1)
class YowProfile(object): def __init__(self, profile_name, config=None): # type: (str, Config) -> None """ :param profile_name: profile name :param config: A supplied config will disable loading configs using the Config manager and provide that config instead """ logger.info("Constructed Profile(profile_name=%s)" % profile_name) self._profile_name = profile_name self._config = config self._config_manager = ConfigManager() self._axolotl_manager = None def __str__(self): return "YowProfile(profile_name=%s)" % self._profile_name def _load_config(self): # type: () -> Config logger.debug("load_config for %s" % self._profile_name) return self._config_manager.load(self._profile_name) def _load_axolotl_manager(self): # type: () -> AxolotlManager return AxolotlManagerFactory().get_manager(self._profile_name, self.username) def write_config(self, config): # type: (Config) -> None logger.debug("write_config for %s" % self._profile_name) self._config_manager.save(self._profile_name, config) @property def config(self): if self._config is None: self._config = self._load_config() return self._config @property def axolotl_manager(self): if self._axolotl_manager is None: self._axolotl_manager = self._load_axolotl_manager() return self._axolotl_manager @property def username(self): config = self.config return config.login or config.phone or self._profile_name
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()
from yowsup.stacks import YowStackBuilder from layer import MqttLayer from layer import EchoLayer from yowsup.layers import YowLayerEvent from yowsup.layers.network import YowNetworkLayer from yowsup.layers.auth import YowAuthenticationProtocolLayer from yowsup.common import YowConstants from yowsup.profile.profile import YowProfile from yowsup.config.manager import ConfigManager from yowsup.config.v1.config import Config stackBuilder = YowStackBuilder() stack = stackBuilder\ .pushDefaultLayers()\ .push(MqttLayer())\ .build() config_manager = ConfigManager() config = config_manager.load("36309040975") profile = YowProfile(config.login,config) stack.setProfile(profile) stack.broadcastEvent(YowLayerEvent(YowNetworkLayer.EVENT_STATE_CONNECT)) #sending the connect signal stack.loop() #this is the program mainloop`
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="2.19.51", mcc=config.mcc, mnc=config.mnc, os_version=yowsupenv.getOSVersion(), manufacturer=yowsupenv.getManufacturer(), device=yowsupenv.getDeviceName(), os_build_number=yowsupenv.getOSVersion(), phone_id=config.fdid, 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()