Compare commits
26
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
a435a5281b | ||
|
|
a2eb04ceee | ||
|
|
dae2413ed1 | ||
|
|
cd9792193f | ||
|
|
75dbd1e498 | ||
|
|
a374009835 | ||
|
|
e00600c955 | ||
|
|
141fea542c | ||
|
|
ed4450778d | ||
|
|
41d59b1df0 | ||
|
|
fd104c09da | ||
|
|
6dbed91426 | ||
|
|
cb43f17d75 | ||
|
|
5ebf278ad3 | ||
|
|
7f782533b8 | ||
|
|
1790c1beae | ||
|
|
09e1c382d3 | ||
|
|
ceb2270ee5 | ||
|
|
986a3c81f3 | ||
|
|
11d6bbb916 | ||
|
|
b02f6318a7 | ||
|
|
c1435e74e8 | ||
|
|
b30da661e5 | ||
|
|
3a22dddc82 | ||
|
|
a19a17d4dc | ||
|
|
bff6ef92ce |
@@ -34,6 +34,8 @@ jobs:
|
||||
tox -r -e cov
|
||||
- name: Codecov
|
||||
uses: codecov/codecov-action@v1.0.6
|
||||
env:
|
||||
CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }}
|
||||
with:
|
||||
flags: unittests
|
||||
file: ./coverage.xml
|
||||
|
||||
+14
-1
@@ -4,10 +4,23 @@ Changelog
|
||||
|
||||
A list of changes between each release
|
||||
|
||||
0.16.3 (2020-08-02)
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
- Add user-agent to all headers
|
||||
|
||||
0.16.2 (2020-08-01)
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
- Add user-agent to header at login
|
||||
- Remove extra data parameters at login (not-needed)
|
||||
- Bump pytest to 6.0.1
|
||||
|
||||
|
||||
0.16.1 (2020-07-29)
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
- Unpin requeirements, set minimum version instead
|
||||
- Unpin requirements, set minimum version instead
|
||||
- Bump coverage to 5.2.1
|
||||
- Bump pytest to 6.0.0
|
||||
|
||||
|
||||
+1
-1
@@ -174,7 +174,7 @@ Similar methods exist for individual cameras:
|
||||
|
||||
Download videos
|
||||
----------------
|
||||
You can also use this library to download all videos from the server. In order to do this, you must specify a ``path``. You may also specifiy a how far back in time to go to retrieve videos via the ``since=`` variable (a simple string such as ``"2017/09/21"`` is sufficient), as well as how many pages to traverse via the ``page=`` variable. Note that by default, the library will search the first ten pages which is sufficient in most use cases. Additionally, you can specidy one or more cameras via the ``camera=`` property. This can be a single string indicating the name of the camera, or a list of camera names. By default, it is set to the string ``'all'`` to grab videos from all cameras.
|
||||
You can also use this library to download all videos from the server. In order to do this, you must specify a ``path``. You may also specifiy a how far back in time to go to retrieve videos via the ``since=`` variable (a simple string such as ``"2017/09/21"`` is sufficient), as well as how many pages to traverse via the ``stop=`` variable. Note that by default, the library will search the first ten pages which is sufficient in most use cases. Additionally, you can specify one or more cameras via the ``camera=`` property. This can be a single string indicating the name of the camera, or a list of camera names. By default, it is set to the string ``'all'`` to grab videos from all cameras.
|
||||
|
||||
Example usage, which downloads all videos recorded since July 4th, 2018 at 9:34am to the ``/home/blink`` directory:
|
||||
|
||||
|
||||
+8
-5
@@ -3,7 +3,7 @@
|
||||
import logging
|
||||
from json import dumps
|
||||
from blinkpy.helpers.util import get_time, Throttle
|
||||
from blinkpy.helpers.constants import DEFAULT_URL, TIMEOUT
|
||||
from blinkpy.helpers.constants import DEFAULT_URL, TIMEOUT, DEFAULT_USER_AGENT
|
||||
|
||||
_LOGGER = logging.getLogger(__name__)
|
||||
|
||||
@@ -20,21 +20,24 @@ def request_login(
|
||||
:param url: Login url.
|
||||
:login_data: Dictionary containing blink login data.
|
||||
"""
|
||||
headers = {"Host": DEFAULT_URL, "Content-Type": "application/json"}
|
||||
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"],
|
||||
"app_version": "6.0.7 (520300) #afb0be72a",
|
||||
"device_identifier": login_data["device_id"],
|
||||
"client_name": "Computer",
|
||||
"client_type": "android",
|
||||
"os_version": "5.1.1",
|
||||
"reauth": "false",
|
||||
}
|
||||
)
|
||||
|
||||
return auth.query(
|
||||
url=url,
|
||||
headers=headers,
|
||||
|
||||
+16
-7
@@ -6,7 +6,12 @@ from requests.adapters import HTTPAdapter
|
||||
from urllib3.util.retry import Retry
|
||||
from blinkpy import api
|
||||
from blinkpy.helpers import util
|
||||
from blinkpy.helpers.constants import BLINK_URL, LOGIN_ENDPOINT, TIMEOUT
|
||||
from blinkpy.helpers.constants import (
|
||||
BLINK_URL,
|
||||
DEFAULT_USER_AGENT,
|
||||
LOGIN_ENDPOINT,
|
||||
TIMEOUT,
|
||||
)
|
||||
|
||||
_LOGGER = logging.getLogger(__name__)
|
||||
|
||||
@@ -53,7 +58,7 @@ class Auth:
|
||||
"""Return authorization header."""
|
||||
if self.token is None:
|
||||
return None
|
||||
return {"TOKEN_AUTH": self.token}
|
||||
return {"TOKEN_AUTH": self.token, "user-agent": DEFAULT_USER_AGENT}
|
||||
|
||||
def create_session(self, opts=None):
|
||||
"""Create a session for blink communication."""
|
||||
@@ -108,11 +113,7 @@ class Auth:
|
||||
try:
|
||||
_LOGGER.info("Token expired, attempting automatic refresh.")
|
||||
self.login_response = self.login()
|
||||
self.region_id = self.login_response["region"]["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.extract_login_info()
|
||||
self.is_errored = False
|
||||
except LoginError:
|
||||
_LOGGER.error("Login endpoint failed. Try again later.")
|
||||
@@ -122,6 +123,14 @@ class Auth:
|
||||
raise TokenRefreshFailed
|
||||
return True
|
||||
|
||||
def extract_login_info(self):
|
||||
"""Extract login info from login response."""
|
||||
self.region_id = self.login_response["region"]["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"]
|
||||
|
||||
def startup(self):
|
||||
"""Initialize tokens for communication."""
|
||||
self.validate_login()
|
||||
|
||||
@@ -4,7 +4,7 @@ import os
|
||||
|
||||
MAJOR_VERSION = 0
|
||||
MINOR_VERSION = 17
|
||||
PATCH_VERSION = "0-rc0"
|
||||
PATCH_VERSION = "0.dev0"
|
||||
|
||||
__version__ = f"{MAJOR_VERSION}.{MINOR_VERSION}.{PATCH_VERSION}"
|
||||
|
||||
@@ -58,6 +58,7 @@ ONLINE = {"online": True, "offline": False}
|
||||
"""
|
||||
OTHER
|
||||
"""
|
||||
DEFAULT_USER_AGENT = "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/71.0.3578.98 Safari/537.36"
|
||||
DEVICE_ID = "Blinkpy"
|
||||
TIMESTAMP_FORMAT = "%Y-%m-%dT%H:%M:%S%z"
|
||||
DEFAULT_MOTION_INTERVAL = 1
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
black==19.10b0
|
||||
coverage==5.2.1
|
||||
coverage==5.3
|
||||
flake8==3.8.3
|
||||
flake8-docstrings==1.5.0
|
||||
pre-commit==2.6.0
|
||||
pylint==2.5.3
|
||||
pydocstyle==5.0.2
|
||||
pytest==6.0.0
|
||||
pytest-cov==2.10.0
|
||||
pytest==6.1.1
|
||||
pytest-cov==2.10.1
|
||||
pytest-sugar==0.9.4
|
||||
pytest-timeout==1.4.2
|
||||
restructuredtext-lint==1.3.1
|
||||
|
||||
+1
-1
@@ -128,7 +128,7 @@ class TestAuth(unittest.TestCase):
|
||||
def test_header(self):
|
||||
"""Test header data."""
|
||||
self.auth.token = "bar"
|
||||
expected_header = {"TOKEN_AUTH": "bar"}
|
||||
expected_header = {"TOKEN_AUTH": "bar", "user-agent": const.DEFAULT_USER_AGENT}
|
||||
self.assertDictEqual(self.auth.header, expected_header)
|
||||
|
||||
def test_header_no_token(self):
|
||||
|
||||
Reference in New Issue
Block a user