def __init__(self, client, user_list, client_conversation, client_events=[]): """Initialize a new Conversation.""" self._client = client # Client self._user_list = user_list # UserList self._conversation = client_conversation # ClientConversation self._events = [] # [ConversationEvent] self._events_dict = {} # {event_id: ConversationEvent} self._send_message_lock = asyncio.Lock() for event_ in client_events: self.add_event(event_) # Event fired when a user starts or stops typing with arguments # (typing_message). self.on_typing = event.Event('Conversation.on_typing') # Event fired when a new ConversationEvent arrives with arguments # (ConversationEvent). self.on_event = event.Event('Conversation.on_event') # Event fired when a watermark (read timestamp) is updated with # arguments (WatermarkNotification). self.on_watermark_notification = event.Event( 'Conversation.on_watermark_notification') self.on_watermark_notification.add_observer( self._on_watermark_notification)
def __init__(self, cookies, session, max_retries, retry_backoff_base): """Create a new channel.""" # Event fired when channel connects with arguments (): self.on_connect = event.Event('Channel.on_connect') # Event fired when channel reconnects with arguments (): self.on_reconnect = event.Event('Channel.on_reconnect') # Event fired when channel disconnects with arguments (): self.on_disconnect = event.Event('Channel.on_disconnect') # Event fired when an array is received with arguments (array): self.on_receive_array = event.Event('Channel.on_receive_array') self._max_retries = max_retries self._retry_backoff_base = retry_backoff_base # True if the channel is currently connected: self._is_connected = False # True if the on_connect event has been called at least once: self._on_connect_called = False # Request cookies dictionary: self._cookies = cookies # Parser for assembling messages: self._chunk_parser = None # aiohttp session for keep-alive and cookies: self._session = session # Discovered parameters: self._sid_param = None self._gsessionid_param = None
def __init__(self, cookies, connector): """Create a new channel.""" # Event fired when channel connects with arguments (): self.on_connect = event.Event('Channel.on_connect') # Event fired when channel reconnects with arguments (): self.on_reconnect = event.Event('Channel.on_reconnect') # Event fired when channel disconnects with arguments (): self.on_disconnect = event.Event('Channel.on_disconnect') # Event fired when a channel submission is received with arguments # (submission): self.on_message = event.Event('Channel.on_message') # True if the channel is currently connected: self._is_connected = False # True if the channel has been subscribed: self._is_subscribed = False # True if the on_connect event has been called at least once: self._on_connect_called = False # Request cookies dictionary: self._cookies = cookies # Parser for assembling messages: self._push_parser = None # aiohttp connector for keep-alive: self._connector = connector # Discovered parameters: self._sid_param = None self._gsessionid_param = None
def __init__(self, client, user_list, conversation, events=[]): """Initialize a new Conversation.""" # pylint: disable=dangerous-default-value self._client = client # Client self._user_list = user_list # UserList self._conversation = conversation # hangouts_pb2.Conversation self._events = [] # [hangouts_pb2.Event] self._events_dict = {} # {event_id: ConversationEvent} self._send_message_lock = asyncio.Lock() for event_ in events: # Workaround to ignore observed events returned from # syncrecentconversations. if event_.event_type != hangouts_pb2.EVENT_TYPE_OBSERVED_EVENT: self.add_event(event_) # Event fired when a user starts or stops typing with arguments # (typing_message). self.on_typing = event.Event('Conversation.on_typing') # Event fired when a new ConversationEvent arrives with arguments # (ConversationEvent). self.on_event = event.Event('Conversation.on_event') # Event fired when a watermark (read timestamp) is updated with # arguments (WatermarkNotification). self.on_watermark_notification = event.Event( 'Conversation.on_watermark_notification') self.on_watermark_notification.add_observer( self._on_watermark_notification)
def __init__(self, session, max_retries, retry_backoff_base): """Create a new channel. Args: session (http_utils.Session): Request session. max_retries (int): Number of retries for long-polling request. retry_backoff_base (int): The base term for the long-polling exponential backoff. """ # Event fired when channel connects with arguments (): self.on_connect = event.Event('Channel.on_connect') # Event fired when channel reconnects with arguments (): self.on_reconnect = event.Event('Channel.on_reconnect') # Event fired when channel disconnects with arguments (): self.on_disconnect = event.Event('Channel.on_disconnect') # Event fired when an array is received with arguments (array): self.on_receive_array = event.Event('Channel.on_receive_array') self._max_retries = max_retries self._retry_backoff_base = retry_backoff_base # True if the channel is currently connected: self._is_connected = False # True if the on_connect event has been called at least once: self._on_connect_called = False # Parser for assembling messages: self._chunk_parser = None # Session for HTTP requests: self._session = session # Discovered parameters: self._sid_param = None self._gsessionid_param = None
def __init__(self, client, conv_states, user_list, sync_timestamp): self._client = client # Client self._conv_dict = {} # {conv_id: Conversation} self._sync_timestamp = sync_timestamp # datetime self._user_list = user_list # UserList # Initialize the list of conversations from Client's list of # ClientConversationStates. for conv_state in conv_states: self.add_conversation(conv_state.conversation, conv_state.event) self._client.on_state_update.add_observer(self._on_state_update) self._client.on_connect.add_observer(self._sync) self._client.on_reconnect.add_observer(self._sync) # Event fired when a new ConversationEvent arrives with arguments # (ConversationEvent). self.on_event = event.Event('ConversationList.on_event') # Event fired when a user starts or stops typing with arguments # (typing_message). self.on_typing = event.Event('ConversationList.on_typing') # Event fired when a watermark (read timestamp) is updated with # arguments (WatermarkNotification). self.on_watermark_notification = event.Event( 'ConversationList.on_watermark_notification')
def __init__(self, client, user_list, conversation, events=[], event_cont_token=None): # pylint: disable=dangerous-default-value self._client = client # Client self._user_list = user_list # UserList self._conversation = conversation # hangouts_pb2.Conversation self._events = [] # [hangouts_pb2.Event] self._events_dict = {} # {event_id: ConversationEvent} self._send_message_lock = asyncio.Lock() self._watermarks = {} # {UserID: datetime.datetime} self._event_cont_token = event_cont_token for event_ in events: # Workaround to ignore observed events returned from # syncrecentconversations. if event_.event_type != hangouts_pb2.EVENT_TYPE_OBSERVED_EVENT: self.add_event(event_) self.on_event = event.Event('Conversation.on_event') """ :class:`.Event` fired when an event occurs in this conversation. Args: conv_event: :class:`.ConversationEvent` that occurred. """ self.on_typing = event.Event('Conversation.on_typing') """ :class:`.Event` fired when a users starts or stops typing in this conversation. Args: typing_message: :class:`~hangups.parsers.TypingStatusMessage` that occurred. """ self.on_watermark_notification = event.Event( 'Conversation.on_watermark_notification') """ :class:`.Event` fired when a watermark (read timestamp) is updated for this conversation. Args: watermark_notification: :class:`~hangups.parsers.WatermarkNotification` that occurred. """ self.on_watermark_notification.add_observer( self._on_watermark_notification)
def __init__(self, cookies): """Create new client. cookies is a dictionary of authentication cookies. """ # Event fired when the client connects for the first time with # arguments (). self.on_connect = event.Event('Client.on_connect') # Event fired when the client reconnects after being disconnected with # arguments (). self.on_reconnect = event.Event('Client.on_reconnect') # Event fired when the client is disconnected with arguments (). self.on_disconnect = event.Event('Client.on_disconnect') # Event fired when a StateUpdate arrives with arguments (state_update). self.on_state_update = event.Event('Client.on_state_update') self._cookies = cookies proxy = os.environ.get('HTTP_PROXY') if proxy: self._connector = aiohttp.ProxyConnector(proxy) else: self._connector = aiohttp.TCPConnector() self._channel = channel.Channel(self._cookies, self._connector) # Future for Channel.listen self._listen_future = None self._request_header = hangouts_pb2.RequestHeader( # Ignore most of the RequestHeader fields since they aren't # required. Sending a recognized client_id is important because it # changes the behaviour of some APIs (eg. get_conversation will # filter out EVENT_TYPE_GROUP_LINK_SHARING_MODIFICATION without # it). client_version=hangouts_pb2.ClientVersion( client_id=hangouts_pb2.CLIENT_ID_WEB_HANGOUTS, major_version='hangups-{}'.format(version.__version__), ), language_code='en', ) # String identifying this client (populated later): self._client_id = None # String email address for this account (populated later): self._email = None # Active client management parameters: # Time in seconds that the client as last set as active: self._last_active_secs = 0.0 # ActiveClientState enum int value or None: self._active_client_state = None
def __init__(self, cookies): """Create new client. cookies is a dictionary of authentication cookies. """ # Event fired when the client connects for the first time with # arguments (). self.on_connect = event.Event('Client.on_connect') # Event fired when the client reconnects after being disconnected with # arguments (). self.on_reconnect = event.Event('Client.on_reconnect') # Event fired when the client is disconnected with arguments (). self.on_disconnect = event.Event('Client.on_disconnect') # Event fired when a StateUpdate arrives with arguments (state_update). self.on_state_update = event.Event('Client.on_state_update') self._cookies = cookies proxy = os.environ.get('HTTP_PROXY') if proxy: self._connector = aiohttp.ProxyConnector(proxy) else: self._connector = aiohttp.TCPConnector() self._channel = channel.Channel(self._cookies, self._connector) # Future for Channel.listen self._listen_future = None self._request_header = hangouts_pb2.RequestHeader( # Ignore most of the RequestHeader fields since they aren't # required. client_version=hangouts_pb2.ClientVersion( major_version='hangups-{}'.format(__version__), ), language_code='en', ) # String identifying this client (populated later): self._client_id = None # String email address for this account (populated later): self._email = None # Active client management parameters: # Time in seconds that the client as last set as active: self._last_active_secs = 0.0 # ActiveClientState enum int value or None: self._active_client_state = None
def test_function_observer(): e = event.Event('MyEvent') res = [] a = lambda arg: res.append('a' + arg) e.add_observer(a) yield from e.fire('1') assert res == ['a1']
def test_already_added(): def a(arg): print('A: got {}'.format(arg)) e = event.Event('MyEvent') e.add_observer(a) with pytest.raises(ValueError): e.add_observer(a)
def test_coroutine_observer(): e = event.Event('MyEvent') res = [] a = asyncio.coroutine(lambda arg: res.append('a' + arg)) e.add_observer(a) yield from e.fire('1') assert res == ['a1']
async def test_coroutine_observer(): e = event.Event('MyEvent') res = [] async def a(arg): res.append('a' + arg) e.add_observer(a) await e.fire('1') assert res == ['a1']
def __init__(self, cookies): """Create new client. cookies is a dictionary of authentication cookies. """ # Event fired when the client connects for the first time with # arguments (initial_data). self.on_connect = event.Event('Client.on_connect') # Event fired when the client reconnects after being disconnected with # arguments (). self.on_reconnect = event.Event('Client.on_reconnect') # Event fired when the client is disconnected with arguments (). self.on_disconnect = event.Event('Client.on_disconnect') # Event fired when a ClientStateUpdate arrives with arguments # (state_update). self.on_state_update = event.Event('Client.on_state_update') self._cookies = cookies proxy = os.environ.get('HTTP_PROXY') if proxy: self._connector = aiohttp.ProxyConnector(proxy) else: self._connector = aiohttp.TCPConnector() # hangups.channel.Channel instantiated in connect() self._channel = None # API key sent with every request: self._api_key = None # Parameters sent in request headers: self._header_date = None self._header_version = None self._header_id = None # String identifying this client: self._client_id = None # Account email address: self._email = None # Time in seconds that the client as last set as active: self._last_active_secs = 0.0 # ActiveClientState enum value or None: self._active_client_state = None # Future for Channel.listen self._listen_future = None
def __init__(self, client, user_list, client_conversation, client_events=[]): """Initialize a new Conversation.""" self._client = client # Client self._user_list = user_list # UserList self._conversation = client_conversation # ClientConversation self._events = [] # [ConversationEvent] for event_ in client_events: self.add_event(event_) # Event fired when a user starts or stops typing with arguments # (typing_message). self.on_typing = event.Event('Conversation.on_typing') # Event fired when a new ConversationEvent arrives with arguments # (ConversationEvent). self.on_event = event.Event('Conversation.on_event')
def __init__(self, cookies): """Create new client. cookies is a dictionary of authentication cookies. """ # Event fired when the client connects for the first time with # arguments (initial_data). self.on_connect = event.Event('Client.on_connect') # Event fired when the client reconnects after being disconnected with # arguments (). self.on_reconnect = event.Event('Client.on_reconnect') # Event fired when the client is disconnected with arguments (). self.on_disconnect = event.Event('Client.on_disconnect') # Event fired when a ClientStateUpdate arrives with arguments # (state_update). self.on_state_update = event.Event('Client.on_state_update') self._cookies = cookies self._connector = aiohttp.TCPConnector() # hangups.channel.Channel instantiated in connect() self._channel = None # API key sent with every request: self._api_key = None # Parameters sent in request headers: self._header_date = None self._header_version = None self._header_id = None # Like the jabber client ID self._header_client = None # Parameters needed to create the Channel: self._channel_path = None self._clid = None self._channel_ec_param = None self._channel_prop_param = None # Time in seconds that the client as last set as active: self._last_active_secs = 0.0 # ActiveClientState enum value or None: self._active_client_state = None # Future for Channel.listen self._listen_future = None
def __init__(self, cookies, path, clid, ec, prop, connector): """Create a new channel.""" # Event fired when channel connects with arguments (): self.on_connect = event.Event('Channel.on_connect') # Event fired when channel reconnects with arguments (): self.on_reconnect = event.Event('Channel.on_reconnect') # Event fired when channel disconnects with arguments (): self.on_disconnect = event.Event('Channel.on_disconnect') # Event fired when a channel submission is received with arguments # (submission): self.on_message = event.Event('Channel.on_message') # True if the channel is currently connected: self._is_connected = False # True if the on_connect event has been called at least once: self._on_connect_called = False # Request cookies dictionary: self._cookies = cookies # Parser for assembling messages: self._push_parser = None # aiohttp connector for keep-alive: self._connector = connector # Static channel parameters: # '/u/0/talkgadget/_/channel/' self._channel_path = path # 'A672C650270E1674' self._clid_param = clid # '["ci:ec",1,1,0,"chat_wcs_20140813.110045_RC2"]\n' self._ec_param = ec # 'aChromeExtension' self._prop_param = prop # Discovered parameters: self._sid_param = None self._gsessionid_param = None self._email = None self._header_client = None
def __init__(self, cookies): """Create new client. cookies is a dictionary of authentication cookies. """ # Event fired when the client connects for the first time with # arguments (initial_data). self.on_connect = event.Event('Client.on_connect') self.__on_pre_connect = event.Event('Client.on_pre_connect') self.__on_pre_connect.add_observer(self._on_pre_connect) # Event fired when the client reconnects after being disconnected with # arguments (). self.on_reconnect = event.Event('Client.on_reconnect') # Event fired when the client is disconnected with arguments (). self.on_disconnect = event.Event('Client.on_disconnect') # Event fired when a ClientStateUpdate arrives with arguments # (state_update). self.on_state_update = event.Event('Client.on_state_update') self._cookies = cookies self._connector = aiohttp.TCPConnector() # hangups.channel.Channel instantiated in connect() self._channel = None # API key sent with every request: self._api_key = None # Parameters sent in request headers: self._header_date = None self._header_version = None self._header_id = None # Like the jabber client ID self._header_client = None self._email = None # Parameters needed to create the Channel: self._channel_path = None self._clid = None self._channel_ec_param = None self._channel_prop_param = None
def __init__(self, client, conv_states, user_list, sync_timestamp): self._client = client # Client self._conv_dict = {} # {conv_id: Conversation} self._sync_timestamp = sync_timestamp # datetime self._user_list = user_list # UserList # Initialize the list of conversations from Client's list of # hangouts_pb2.ConversationState. for conv_state in conv_states: self._add_conversation(conv_state.conversation, conv_state.event) self._client.on_state_update.add_observer(self._on_state_update) self._client.on_connect.add_observer(self._sync) self._client.on_reconnect.add_observer(self._sync) self.on_event = event.Event('ConversationList.on_event') """ :class:`~hangups.event.Event` fired when an event occurs in any conversation. Args: conv_event: :class:`ConversationEvent` that occurred. """ self.on_typing = event.Event('ConversationList.on_typing') """ :class:`~hangups.event.Event` fired when a users starts or stops typing in any conversation. Args: typing_message: :class:`~hangups.parsers.TypingStatusMessage` that occurred. """ self.on_watermark_notification = event.Event( 'ConversationList.on_watermark_notification' ) """
def test_event(): e = event.Event('MyEvent') res = [] a = asyncio.coroutine(lambda arg: res.append('a' + arg)) b = asyncio.coroutine(lambda arg: res.append('b' + arg)) e.add_observer(a) yield from e.fire('1') e.add_observer(b) yield from e.fire('2') e.remove_observer(a) yield from e.fire('3') e.remove_observer(b) yield from e.fire('4') assert res == ['a1', 'a2', 'b2', 'b3']
def __init__(self, client, conv_states, user_list, sync_timestamp): self._client = client # Client self._conv_dict = {} # {conv_id: Conversation} self._sync_timestamp = sync_timestamp # datetime self._user_list = user_list # UserList # Initialize the list of conversations from Client's list of # ClientConversationStates. for conv_state in conv_states: self.add_conversation(conv_state.conversation, conv_state.event) self._client.on_state_update.add_observer(self._on_state_update) # TODO: Make event support coroutines so we don't have to do this: sync_f = lambda initial_data=None: asyncio.async(self._sync()) \ .add_done_callback(lambda f: f.result()) self._client.on_connect.add_observer(sync_f) self._client.on_reconnect.add_observer(sync_f) # Event fired when a new ConversationEvent arrives with arguments # (ConversationEvent). self.on_event = event.Event('ConversationList.on_event') # Event fired when a user starts or stops typing with arguments # (typing_message). self.on_typing = event.Event('ConversationList.on_typing')
async def test_event(): e = event.Event('MyEvent') res = [] async def a(arg): res.append('a' + arg) async def b(arg): res.append('b' + arg) e.add_observer(a) await e.fire('1') e.add_observer(b) await e.fire('2') e.remove_observer(a) await e.fire('3') e.remove_observer(b) await e.fire('4') assert res == ['a1', 'a2', 'b2', 'b3']
async def test_function_observer(): e = event.Event('MyEvent') res = [] e.add_observer(lambda arg: res.append('a' + arg)) await e.fire('1') assert res == ['a1']
def test_remove_nonexistant(): e = event.Event('MyEvent') with pytest.raises(ValueError): e.remove_observer(lambda a: print('A: got {}'.format(a)))
def __init__(self, cookies, max_retries=5, retry_backoff_base=2): self._max_retries = max_retries self._retry_backoff_base = retry_backoff_base self.on_connect = event.Event('Client.on_connect') """ :class:`~hangups.event.Event` fired when the client connects for the first time. """ self.on_reconnect = event.Event('Client.on_reconnect') """ :class:`~hangups.event.Event` fired when the client reconnects after being disconnected. """ self.on_disconnect = event.Event('Client.on_disconnect') """ :class:`~hangups.event.Event` fired when the client is disconnected. """ self.on_state_update = event.Event('Client.on_state_update') """ :class:`~hangups.event.Event` fired when an update arrives from the server. Args: state_update: A ``StateUpdate`` message. """ # Google session cookies: self._cookies = cookies # aiohttp.ClientSession instance (populated by connect method): self._session = None # Channel instance (populated by connect method): self._channel = None # Future for Channel.listen (populated by connect method): self._listen_future = None self._request_header = hangouts_pb2.RequestHeader( # Ignore most of the RequestHeader fields since they aren't # required. Sending a recognized client_id is important because it # changes the behaviour of some APIs (eg. get_conversation will # filter out EVENT_TYPE_GROUP_LINK_SHARING_MODIFICATION without # it). client_version=hangouts_pb2.ClientVersion( client_id=hangouts_pb2.CLIENT_ID_WEB_HANGOUTS, major_version='hangups-{}'.format(version.__version__), ), language_code='en', ) # String identifying this client (populated later): self._client_id = None # String email address for this account (populated later): self._email = None # Active client management parameters: # Time in seconds that the client as last set as active: self._last_active_secs = 0.0 # ActiveClientState enum int value or None: self._active_client_state = None
def create_event(self, *event_name: str) -> None: for event_ in event_name: self.events[event_] = event.Event('hanger.{}'.format(event_name))