Compare commits

..
5 Commits
Author SHA1 Message Date
Kevin FronczakandGitHub 37350da1b2 Merge pull request #402 from fronzbot/dev
0.16.4
2020-11-22 23:33:15 -05:00
Kevin FronczakandGitHub 19b7eef123 Merge pull request #363 from fronzbot/dev
0.16.3
2020-08-01 23:33:38 -04:00
Kevin FronczakandGitHub 6bd8d14190 Merge pull request #359 from fronzbot/dev
0.16.2
2020-08-01 23:12:25 -04:00
Kevin FronczakandGitHub f6ddfbe5cf Merge pull request #349 from fronzbot/dev
0.16.1
2020-07-29 11:32:04 -04:00
Kevin FronczakandGitHub 1b66eddfb4 Merge pull request #340 from fronzbot/dev
0.16.0
2020-07-20 23:01:30 -04:00
14 changed files with 75 additions and 93 deletions
+2 -3
View File
@@ -1,5 +1,5 @@
# Number of days of inactivity before an issue becomes stale
daysUntilStale: 30
daysUntilStale: 60
# Number of days of inactivity before a stale issue is closed
daysUntilClose: 7
@@ -8,8 +8,7 @@ daysUntilClose: 7
exemptLabels:
- Priority
- bug
- help wanted
- feature request
- Help Wanted
# Set to true to ignore issues in a project (defaults to false)
exemptProjects: true
+1 -1
View File
@@ -15,7 +15,7 @@ jobs:
runs-on: ubuntu-latest
strategy:
matrix:
python-version: [3.9]
python-version: [3.8]
steps:
- uses: actions/checkout@v2
+1 -1
View File
@@ -17,7 +17,7 @@ jobs:
- name: Set up Python
uses: actions/setup-python@v1
with:
python-version: '3.8'
python-version: '3.7'
- name: Install dependencies
run: |
python -m pip install --upgrade pip
+2 -2
View File
@@ -10,11 +10,11 @@ jobs:
build:
runs-on: ${{ matrix.platform }}
strategy:
max-parallel: 4
max-parallel: 3
matrix:
platform:
- ubuntu-latest
python-version: [3.6, 3.7, 3.8, 3.9]
python-version: [3.6, 3.7, 3.8]
steps:
- uses: actions/checkout@v2
+25
View File
@@ -0,0 +1,25 @@
image: python
stages:
- test
before_script:
- curl -O https://bootstrap.pypa.io/get-pip.py
- python get-pip.py
- pip install tox
python35:
image: python:3.5
stage: test
script: tox -e py35
python36:
image: python:3.6
stage: test
script: tox -e py36
lint:
image: python:3.6
stage: test
script: tox -e lint
+3 -6
View File
@@ -23,15 +23,18 @@ def request_login(
headers = {
"Host": DEFAULT_URL,
"Content-Type": "application/json",
"Accept": "/",
"user-agent": DEFAULT_USER_AGENT,
}
data = dumps(
{
"email": login_data["username"],
"password": login_data["password"],
"notification_key": login_data["notification_key"],
"unique_id": login_data["uid"],
"device_identifier": login_data["device_id"],
"client_name": "Computer",
"reauth": "false",
}
)
@@ -54,12 +57,6 @@ def request_verify(auth, blink, verify_key):
)
def request_logout(blink):
"""Logout of blink servers."""
url = f"{blink.urls.base_url}/api/v4/account/{blink.account_id}/client/{blink.client_id}/logout"
return http_post(blink, url=url)
def request_networks(blink):
"""Request all networks information."""
url = f"{blink.urls.base_url}/networks"
+14 -25
View File
@@ -58,11 +58,7 @@ class Auth:
"""Return authorization header."""
if self.token is None:
return None
return {
"TOKEN_AUTH": self.token,
"user-agent": DEFAULT_USER_AGENT,
"content-type": "application/json",
}
return {"TOKEN_AUTH": self.token, "user-agent": DEFAULT_USER_AGENT}
def create_session(self, opts=None):
"""Create a session for blink communication."""
@@ -108,12 +104,8 @@ class Auth:
if response.status_code == 200:
return response.json()
raise LoginError
except AttributeError as error:
raise LoginError from error
def logout(self, blink):
"""Log out."""
return api.request_logout(blink)
except AttributeError:
raise LoginError
def refresh_token(self):
"""Refresh auth token."""
@@ -123,21 +115,21 @@ class Auth:
self.login_response = self.login()
self.extract_login_info()
self.is_errored = False
except LoginError as error:
except LoginError:
_LOGGER.error("Login endpoint failed. Try again later.")
raise TokenRefreshFailed from error
except (TypeError, KeyError) as error:
raise TokenRefreshFailed
except (TypeError, KeyError):
_LOGGER.error("Malformed login response: %s", self.login_response)
raise TokenRefreshFailed from error
raise TokenRefreshFailed
return True
def extract_login_info(self):
"""Extract login info from login response."""
self.region_id = self.login_response["account"]["tier"]
self.region_id = self.login_response["region"]["tier"]
self.host = f"{self.region_id}.{BLINK_URL}"
self.token = self.login_response["auth"]["token"]
self.client_id = self.login_response["account"]["client_id"]
self.account_id = self.login_response["account"]["account_id"]
self.token = self.login_response["authtoken"]["authtoken"]
self.client_id = self.login_response["client"]["id"]
self.account_id = self.login_response["account"]["id"]
def startup(self):
"""Initialize tokens for communication."""
@@ -159,8 +151,8 @@ class Auth:
json_data = response.json()
except KeyError:
pass
except (AttributeError, ValueError) as error:
raise BlinkBadResponse from error
except (AttributeError, ValueError):
raise BlinkBadResponse
self.is_errored = False
return json_data
@@ -235,9 +227,6 @@ class Auth:
try:
json_resp = response.json()
blink.available = json_resp["valid"]
if not json_resp["valid"]:
_LOGGER.error("%s", json_resp["message"])
return False
except (KeyError, TypeError):
_LOGGER.error("Did not receive valid response from server.")
return False
@@ -246,7 +235,7 @@ class Auth:
def check_key_required(self):
"""Check if 2FA key is required."""
try:
if self.login_response["account"]["client_verification_required"]:
if self.login_response["client"]["verification_required"]:
return True
except (KeyError, TypeError):
pass
-4
View File
@@ -98,10 +98,6 @@ class BlinkCamera:
self.sync.blink, self.network_id, self.camera_id
)
def record(self):
"""Initiate clip recording."""
return api.request_new_video(self.sync.blink, self.network_id, self.camera_id)
def get_media(self, media_type="image"):
"""Download media (image or video)."""
url = self.thumbnail
+3 -4
View File
@@ -3,8 +3,8 @@
import os
MAJOR_VERSION = 0
MINOR_VERSION = 17
PATCH_VERSION = "0.rc0"
MINOR_VERSION = 16
PATCH_VERSION = 4
__version__ = f"{MAJOR_VERSION}.{MINOR_VERSION}.{PATCH_VERSION}"
@@ -34,7 +34,6 @@ PROJECT_CLASSIFIERS = [
"Programming Language :: Python :: 3.6",
"Programming Language :: Python :: 3.7",
"Programming Language :: Python :: 3.8",
"Programming Language :: Python :: 3.9",
"Topic :: Home Automation",
]
@@ -49,7 +48,7 @@ URLS
BLINK_URL = "immedia-semi.com"
DEFAULT_URL = f"rest-prod.{BLINK_URL}"
BASE_URL = f"https://{DEFAULT_URL}"
LOGIN_ENDPOINT = f"{BASE_URL}/api/v5/account/login"
LOGIN_ENDPOINT = f"{BASE_URL}/api/v4/account/login"
"""
Dictionaries
+7 -7
View File
@@ -33,13 +33,10 @@ def json_save(data, file_name):
json.dump(data, json_file, indent=4)
def gen_uid(size, uid_format=False):
def gen_uid(size):
"""Create a random sring."""
if uid_format:
token = f"BlinkCamera_{secrets.token_hex(4)}-{secrets.token_hex(2)}-{secrets.token_hex(2)}-{secrets.token_hex(2)}-{secrets.token_hex(6)}"
else:
token = secrets.token_hex(size)
return token
full_token = secrets.token_hex(size)
return full_token[0:size]
def time_to_seconds(timestamp):
@@ -82,7 +79,10 @@ def prompt_login_data(data):
def validate_login_data(data):
"""Check for missing keys."""
data["uid"] = data.get("uid", gen_uid(const.SIZE_UID, uid_format=True))
data["uid"] = data.get("uid", gen_uid(const.SIZE_UID))
data["notification_key"] = data.get(
"notification_key", gen_uid(const.SIZE_NOTIFICATION_KEY)
)
data["device_id"] = data.get("device_id", const.DEVICE_ID)
return data
+6 -6
View File
@@ -1,14 +1,14 @@
black==19.10b0
coverage==5.4
coverage==5.3
flake8==3.8.4
flake8-docstrings==1.5.0
pre-commit==2.10.1
pre-commit==2.7.1
pylint==2.6.0
pydocstyle==5.1.1
pytest==6.2.2
pytest-cov==2.11.1
pytest==6.1.1
pytest-cov==2.10.1
pytest-sugar==0.9.4
pytest-timeout==1.4.2
restructuredtext-lint==1.3.2
pygments==2.7.4
restructuredtext-lint==1.3.1
pygments==2.7.1
testtools>=2.4.0
+9 -16
View File
@@ -42,6 +42,7 @@ class TestAuth(unittest.TestCase):
"username": "foo",
"password": "bar",
"uid": 1234,
"notification_key": 1234,
"device_id": const.DEVICE_ID,
}
self.assertDictEqual(auth.data, expected_data)
@@ -61,6 +62,7 @@ class TestAuth(unittest.TestCase):
"username": "foo",
"password": "bar",
"uid": 1234,
"notification_key": 1234,
"device_id": const.DEVICE_ID,
}
self.assertDictEqual(auth.data, expected_data)
@@ -126,11 +128,7 @@ class TestAuth(unittest.TestCase):
def test_header(self):
"""Test header data."""
self.auth.token = "bar"
expected_header = {
"TOKEN_AUTH": "bar",
"user-agent": const.DEFAULT_USER_AGENT,
"content-type": "application/json",
}
expected_header = {"TOKEN_AUTH": "bar", "user-agent": const.DEFAULT_USER_AGENT}
self.assertDictEqual(self.auth.header, expected_header)
def test_header_no_token(self):
@@ -163,8 +161,10 @@ class TestAuth(unittest.TestCase):
def test_refresh_token(self, mock_login):
"""Test refresh token method."""
mock_login.return_value = {
"account": {"account_id": 5678, "client_id": 1234, "tier": "test"},
"auth": {"token": "foobar"},
"region": {"tier": "test"},
"authtoken": {"authtoken": "foobar"},
"client": {"id": 1234},
"account": {"id": 5678},
}
self.assertTrue(self.auth.refresh_token())
self.assertEqual(self.auth.region_id, "test")
@@ -186,19 +186,12 @@ class TestAuth(unittest.TestCase):
self.auth.login_response = {}
self.assertFalse(self.auth.check_key_required())
self.auth.login_response = {"account": {"client_verification_required": False}}
self.auth.login_response = {"client": {"verification_required": False}}
self.assertFalse(self.auth.check_key_required())
self.auth.login_response = {"account": {"client_verification_required": True}}
self.auth.login_response = {"client": {"verification_required": True}}
self.assertTrue(self.auth.check_key_required())
@mock.patch("blinkpy.auth.api.request_logout")
def test_logout(self, mock_req):
"""Test logout method."""
mock_blink = MockBlink(None)
mock_req.return_value = True
self.assertTrue(self.auth.logout(mock_blink))
@mock.patch("blinkpy.auth.api.request_verify")
def test_send_auth_key(self, mock_req):
"""Check sending of auth key."""
+1 -17
View File
@@ -3,7 +3,7 @@
import unittest
from unittest import mock
import time
from blinkpy.helpers.util import json_load, Throttle, time_to_seconds, gen_uid
from blinkpy.helpers.util import json_load, Throttle, time_to_seconds
class TestUtil(unittest.TestCase):
@@ -132,19 +132,3 @@ class TestUtil(unittest.TestCase):
self.assertEqual(json_load("fake.file"), None)
with mock.patch("builtins.open", mock.mock_open(read_data="")):
self.assertEqual(json_load("fake.file"), None)
def test_gen_uid(self):
"""Test gen_uid formatting."""
val1 = gen_uid(8)
val2 = gen_uid(8, uid_format=True)
self.assertEqual(len(val1), 16)
self.assertTrue(val2.startswith("BlinkCamera_"))
val2_cut = val2.split("_")
val2_split = val2_cut[1].split("-")
self.assertEqual(len(val2_split[0]), 8)
self.assertEqual(len(val2_split[1]), 4)
self.assertEqual(len(val2_split[2]), 4)
self.assertEqual(len(val2_split[3]), 4)
self.assertEqual(len(val2_split[4]), 12)
+1 -1
View File
@@ -1,5 +1,5 @@
[tox]
envlist = build, py36, py37, py38, py39, lint
envlist = build, py36, py37, py38, lint
skip_missing_interpreters = True
skipsdist = True