Skip to content

Commit

Permalink
Merge pull request #434 from fronzbot/dev
Browse files Browse the repository at this point in the history
0.17.0
  • Loading branch information
fronzbot authored Feb 15, 2021
2 parents 37350da + b41460c commit 1ced64d
Show file tree
Hide file tree
Showing 17 changed files with 195 additions and 75 deletions.
5 changes: 3 additions & 2 deletions .github/stale.yml
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
# Number of days of inactivity before an issue becomes stale
daysUntilStale: 60
daysUntilStale: 30

# Number of days of inactivity before a stale issue is closed
daysUntilClose: 7
Expand All @@ -8,7 +8,8 @@ daysUntilClose: 7
exemptLabels:
- Priority
- bug
- Help Wanted
- help wanted
- feature request

# Set to true to ignore issues in a project (defaults to false)
exemptProjects: true
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/lint.yml
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ jobs:
runs-on: ubuntu-latest
strategy:
matrix:
python-version: [3.8]
python-version: [3.9]

steps:
- uses: actions/checkout@v2
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/publish.yml
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ jobs:
- name: Set up Python
uses: actions/setup-python@v1
with:
python-version: '3.7'
python-version: '3.8'
- name: Install dependencies
run: |
python -m pip install --upgrade pip
Expand Down
4 changes: 2 additions & 2 deletions .github/workflows/tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,11 @@ jobs:
build:
runs-on: ${{ matrix.platform }}
strategy:
max-parallel: 3
max-parallel: 4
matrix:
platform:
- ubuntu-latest
python-version: [3.6, 3.7, 3.8]
python-version: [3.6, 3.7, 3.8, 3.9]

steps:
- uses: actions/checkout@v2
Expand Down
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -14,3 +14,4 @@ build/*
docs/_build
*.log
venv
.session*
25 changes: 0 additions & 25 deletions .gitlab-ci.yml

This file was deleted.

23 changes: 23 additions & 0 deletions CHANGES.rst
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,29 @@ Changelog

A list of changes between each release

0.17.0 (2021-02-15)
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

**Bugfixes:**
- Fix video downloading bug (`#424 <https://github.com/fronzbot/blinkpy/pull/424>`__)
- Fix repeated authorization email bug (`#432 <https://github.com/fronzbot/blinkpy/pull/432>`__ and `#428 <https://github.com/fronzbot/blinkpy/pull/428>`__)

**New Features:**
- Add logout method (`#429 <https://github.com/fronzbot/blinkpy/pull/429>`__)
- Add camera record method (`#430 <https://github.com/fronzbot/blinkpy/pull/430>`__)

**Other:**
- Add debug script to main repo to help with general debug
- Upgrade login endpoint from v4 to v5
- Add python 3.9 support
- Bump coverage to 5.4
- Bump pytest to 6.2.2
- Bump pytest-cov to 2.11.1
- Bump pygments to 2.8.0
- Bump pre-commit to 2.10.1
- Bump restructuredtext-lint to 1.3.2


0.16.4 (2020-11-22)
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

Expand Down
10 changes: 7 additions & 3 deletions blinkpy/api.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,18 +23,16 @@ 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",
"reauth": True,
}
)

Expand All @@ -57,6 +55,12 @@ 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"
Expand Down
39 changes: 25 additions & 14 deletions blinkpy/auth.py
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,11 @@ def header(self):
"""Return authorization header."""
if self.token is None:
return None
return {"TOKEN_AUTH": self.token, "user-agent": DEFAULT_USER_AGENT}
return {
"TOKEN_AUTH": self.token,
"user-agent": DEFAULT_USER_AGENT,
"content-type": "application/json",
}

def create_session(self, opts=None):
"""Create a session for blink communication."""
Expand Down Expand Up @@ -104,8 +108,12 @@ def login(self, login_url=LOGIN_ENDPOINT):
if response.status_code == 200:
return response.json()
raise LoginError
except AttributeError:
raise LoginError
except AttributeError as error:
raise LoginError from error

def logout(self, blink):
"""Log out."""
return api.request_logout(blink)

def refresh_token(self):
"""Refresh auth token."""
Expand All @@ -115,21 +123,21 @@ def refresh_token(self):
self.login_response = self.login()
self.extract_login_info()
self.is_errored = False
except LoginError:
except LoginError as error:
_LOGGER.error("Login endpoint failed. Try again later.")
raise TokenRefreshFailed
except (TypeError, KeyError):
raise TokenRefreshFailed from error
except (TypeError, KeyError) as error:
_LOGGER.error("Malformed login response: %s", self.login_response)
raise TokenRefreshFailed
raise TokenRefreshFailed from error
return True

def extract_login_info(self):
"""Extract login info from login response."""
self.region_id = self.login_response["region"]["tier"]
self.region_id = self.login_response["account"]["tier"]
self.host = f"{self.region_id}.{BLINK_URL}"
self.token = self.login_response["authtoken"]["authtoken"]
self.client_id = self.login_response["client"]["id"]
self.account_id = self.login_response["account"]["id"]
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"]

def startup(self):
"""Initialize tokens for communication."""
Expand All @@ -151,8 +159,8 @@ def validate_response(self, response, json_resp):
json_data = response.json()
except KeyError:
pass
except (AttributeError, ValueError):
raise BlinkBadResponse
except (AttributeError, ValueError) as error:
raise BlinkBadResponse from error

self.is_errored = False
return json_data
Expand Down Expand Up @@ -227,6 +235,9 @@ def send_auth_key(self, blink, key):
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
Expand All @@ -235,7 +246,7 @@ def send_auth_key(self, blink, key):
def check_key_required(self):
"""Check if 2FA key is required."""
try:
if self.login_response["client"]["verification_required"]:
if self.login_response["account"]["client_verification_required"]:
return True
except (KeyError, TypeError):
pass
Expand Down
4 changes: 4 additions & 0 deletions blinkpy/camera.py
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,10 @@ def arm(self, value):
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
Expand Down
7 changes: 4 additions & 3 deletions blinkpy/helpers/constants.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@
import os

MAJOR_VERSION = 0
MINOR_VERSION = 16
PATCH_VERSION = 4
MINOR_VERSION = 17
PATCH_VERSION = 0

__version__ = f"{MAJOR_VERSION}.{MINOR_VERSION}.{PATCH_VERSION}"

Expand Down Expand Up @@ -34,6 +34,7 @@
"Programming Language :: Python :: 3.6",
"Programming Language :: Python :: 3.7",
"Programming Language :: Python :: 3.8",
"Programming Language :: Python :: 3.9",
"Topic :: Home Automation",
]

Expand All @@ -48,7 +49,7 @@
BLINK_URL = "immedia-semi.com"
DEFAULT_URL = f"rest-prod.{BLINK_URL}"
BASE_URL = f"https://{DEFAULT_URL}"
LOGIN_ENDPOINT = f"{BASE_URL}/api/v4/account/login"
LOGIN_ENDPOINT = f"{BASE_URL}/api/v5/account/login"

"""
Dictionaries
Expand Down
14 changes: 7 additions & 7 deletions blinkpy/helpers/util.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,10 +33,13 @@ def json_save(data, file_name):
json.dump(data, json_file, indent=4)


def gen_uid(size):
def gen_uid(size, uid_format=False):
"""Create a random sring."""
full_token = secrets.token_hex(size)
return full_token[0:size]
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


def time_to_seconds(timestamp):
Expand Down Expand Up @@ -79,10 +82,7 @@ def prompt_login_data(data):

def validate_login_data(data):
"""Check for missing keys."""
data["uid"] = data.get("uid", gen_uid(const.SIZE_UID))
data["notification_key"] = data.get(
"notification_key", gen_uid(const.SIZE_NOTIFICATION_KEY)
)
data["uid"] = data.get("uid", gen_uid(const.SIZE_UID, uid_format=True))
data["device_id"] = data.get("device_id", const.DEVICE_ID)

return data
Expand Down
77 changes: 77 additions & 0 deletions debug_login.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
"""Login testing script."""
import sys
import os
from blinkpy.blinkpy import Blink
from blinkpy.auth import Auth
from blinkpy.helpers.util import json_load, json_save

save_session = False
print("")
print("Blink Login Debug Script ...")
print(" ... Loading previous session information.")
cwd = os.getcwd()
print(f" ... Looking in {cwd}.")
session_path = os.path.join(cwd, ".session_debug")
session = json_load(session_path)

try:
auth_file = session["file"]
except (TypeError, KeyError):
print(" ... Please input location of auth file")
auth_file = input(" Must contain username and password: ")
save_session = True

data = json_load(auth_file)
if data is None:
print(f" ... Please fix file contents of {auth_file}.")
print(" ... Exiting.")
sys.exit(1)

try:
username = data["username"]
password = data["password"]
except KeyError:
print(f" ... File contents of {auth_file} incorrect.")
print(" ... Require username and password at minimum.")
print(" ... Exiting.")
sys.exit(1)

if save_session:
print(f" ... Saving session file to {session_path}.")
json_save({"file": auth_file}, session_path)

blink = Blink()
auth = Auth(data)
blink.auth = auth

print(" ... Starting Blink.")
print("")
blink.start()
print("")
print(" ... Printing login response.")
print("")
print(blink.auth.login_response)
print("")
print(" ... Printing login attributes.")
print("")
print(blink.auth.login_attributes)
print("")
input(" ... Press any key to continue: ")
print(" ... Deactivating auth token.")
blink.auth.token = "foobar"
print(f"\t - blink.auth.token = {blink.auth.token}")

print(" ... Attempting login.")
print("")
blink.start()
print("")
print(" ... Printing login response.")
print("")
print(blink.auth.login_response)
print("")
print(" ... Printing login attributes.")
print("")
print(blink.auth.login_attributes)
print("")
rint(" ... Done.")
print("")
12 changes: 6 additions & 6 deletions requirements_test.txt
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
black==19.10b0
coverage==5.3
coverage==5.4
flake8==3.8.4
flake8-docstrings==1.5.0
pre-commit==2.7.1
pre-commit==2.10.1
pylint==2.6.0
pydocstyle==5.1.1
pytest==6.1.1
pytest-cov==2.10.1
pytest==6.2.2
pytest-cov==2.11.1
pytest-sugar==0.9.4
pytest-timeout==1.4.2
restructuredtext-lint==1.3.1
pygments==2.7.1
restructuredtext-lint==1.3.2
pygments==2.8.0
testtools>=2.4.0
Loading

0 comments on commit 1ced64d

Please sign in to comment.