Last active
March 15, 2018 02:06
-
-
Save jrlucier/90d0db3c46d81e42c0854603dd07d316 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import re | |
import json | |
import requests | |
from argparse import ArgumentParser | |
from abc import abstractproperty | |
__version__ = "0.0.1" | |
__all__ = ['ClientException', 'Eero', 'SessionStorage', '__version__'] | |
''' | |
This can be deleted, but I'm keeping it here for debug | |
''' | |
def print_json(data): | |
print(json.dumps(data, indent=4)) | |
class Eero(object): | |
def __init__(self, session): | |
# type(SessionStorage) -> () | |
self.session = session | |
self.client = Client() | |
@property | |
def _cookie_dict(self): | |
if self.needs_login(): | |
return dict() | |
else: | |
return dict(s=self.session.cookie) | |
def needs_login(self): | |
return self.session.cookie is None | |
def login(self, identifier): | |
# type(string) -> string | |
params = dict(login=identifier) | |
data = self.client.post('login', params=params) | |
return data['user_token'] | |
def login_verify(self, verification_code, user_token): | |
params = dict(code=verification_code) | |
response = self.client.post('login/verify', params=params, | |
cookies=dict(s=user_token)) | |
self.session.cookie = user_token | |
return response | |
def refreshed(self, func): | |
try: | |
return func() | |
except ClientException as exception: | |
if (exception.status == 401 | |
and exception.error_message == 'error.session.refresh'): | |
self.login_refresh() | |
return func() | |
else: | |
raise | |
def login_refresh(self): | |
response = self.client.post('login/refresh', cookies=self._cookie_dict) | |
self.session.cookie = response['user_token'] | |
def account(self): | |
return self.refreshed(lambda: self.client.get( | |
'account', | |
cookies=self._cookie_dict)) | |
def id_from_url(self, id_or_url): | |
match = re.search('^[0-9]+$', id_or_url) | |
if match: | |
return match.group(0) | |
match = re.search(r'\/([0-9]+)$', id_or_url) | |
if match: | |
return match.group(1) | |
def devices(self, network_id): | |
return self.refreshed(lambda: self.client.get( | |
'networks/{}/devices'.format( | |
self.id_from_url(network_id)), | |
cookies=self._cookie_dict)) | |
class SessionStorage(object): | |
@abstractproperty | |
def cookie(self): | |
pass | |
class ClientException(Exception): | |
def __init__(self, status, error_message): | |
super(ClientException, self).__init__() | |
self.status = status | |
self.error_message = error_message | |
class Client(object): | |
API_ENDPOINT = 'https://api-user.e2ro.com/2.2/{}' | |
def _parse_response(self, response): | |
data = json.loads(response.text) | |
if data['meta']['code'] is not 200 and data['meta']['code'] is not 201: | |
raise ClientException(data['meta']['code'], | |
data['meta'].get('error', "")) | |
return data.get('data', "") | |
def post(self, action, **kwargs): | |
response = requests.post(self.API_ENDPOINT.format(action), **kwargs) | |
return self._parse_response(response) | |
def get(self, action, **kwargs): | |
response = requests.get(self.API_ENDPOINT.format(action), **kwargs) | |
return self._parse_response(response) | |
class CookieStore(SessionStorage): | |
def __init__(self, cookie_file): | |
from os import path | |
self.cookie_file = path.abspath(cookie_file) | |
try: | |
with open(self.cookie_file, 'r') as f: | |
self.__cookie = f.read() | |
except IOError: | |
self.__cookie = None | |
@property | |
def cookie(self): | |
return self.__cookie | |
@cookie.setter | |
def cookie(self, cookie): | |
self.__cookie = cookie | |
with open(self.cookie_file, 'w+') as f: | |
f.write(self.__cookie) | |
session = CookieStore('session.cookie') | |
eero = Eero(session) | |
if __name__ == '__main__': | |
if eero.needs_login(): | |
parser = ArgumentParser() | |
parser.add_argument("-l", help="your eero login (phone number)") | |
args = parser.parse_args() | |
if args.l: | |
phone_number = args.l | |
else: | |
phone_number = raw_input('your eero login (phone number): ') | |
user_token = eero.login(phone_number) | |
verification_code = raw_input('verification key from SMS: ') | |
eero.login_verify(verification_code, user_token) | |
print('Login successful. Rerun this command to get some output') | |
else: | |
account = eero.account() | |
for network in account['networks']['data']: | |
devices = eero.devices(network['url']) | |
json_obj = json.loads(json.dumps(devices, indent=4)) | |
for device in json_obj: | |
if device['wireless'] and device['connected']: | |
print("{}, {}, {}".format(device['nickname'], device['hostname'], device['mac'])) | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment