Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

v0.15.0 #253

Merged
merged 70 commits into from
May 8, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
70 commits
Select commit Hold shift + click to select a range
e43d2f9
Dev version bump
fronzbot Apr 22, 2020
8a8c4ea
Change to SemVer for dev versions (now rc)
fronzbot May 4, 2020
6159987
Downgrade pip
fronzbot May 4, 2020
19a29bc
Create stale.yml
fronzbot May 4, 2020
c64f5cf
Downgrade pip again
fronzbot May 4, 2020
44d5bb6
Exempt stuff added to projects and milestones
fronzbot May 4, 2020
a531a8e
Update setup.py to not rely on internal pip functions
fronzbot May 4, 2020
1694187
Merge pull request #233 from fronzbot/pip-downgrade-workflows
fronzbot May 4, 2020
72d97f4
Bump requests from 2.22.0 to 2.23.0
dependabot-preview[bot] May 4, 2020
6a481aa
Update stale.yml
fronzbot May 4, 2020
a66c926
Merge pull request #232 from fronzbot/stale-bot
fronzbot May 4, 2020
42ed18f
Bump requests to 2.23.0
fronzbot May 4, 2020
a875816
Merge pull request #231 from fronzbot/dependabot/pip/requests-2.23.0
fronzbot May 4, 2020
bf87f36
Bump testtools from 2.3.0 to 2.4.0
dependabot-preview[bot] May 4, 2020
e6c8420
Bump pytest from 5.3.5 to 5.4.1
dependabot-preview[bot] May 4, 2020
f576c97
Bump coverage from 4.5.4 to 5.1
dependabot-preview[bot] May 4, 2020
0554e4e
Merge pull request #229 from fronzbot/dependabot/pip/pytest-5.4.1
fronzbot May 4, 2020
6977518
Merge pull request #228 from fronzbot/dependabot/pip/coverage-5.1
fronzbot May 4, 2020
13e2262
Bump pylint from 2.4.4 to 2.5.0
dependabot-preview[bot] May 4, 2020
973374f
Merge pull request #227 from fronzbot/dependabot/pip/testtools-2.4.0
fronzbot May 4, 2020
db23acd
Update python-slugify requirement from ~=3.0.2 to ~=4.0.0
dependabot-preview[bot] May 4, 2020
cc5fbcd
Bump slugify to 4.0.0
fronzbot May 4, 2020
bc4956c
Merge pull request #234 from fronzbot/dependabot/pip/python-slugify-a…
fronzbot May 4, 2020
e0ff5c4
Update python-dateutil requirement from ~=2.8.0 to ~=2.8.1
dependabot-preview[bot] May 4, 2020
4587268
Bump dateutil to 2.8.1
fronzbot May 4, 2020
fae1e1a
Merge pull request #230 from fronzbot/dependabot/pip/python-dateutil-…
fronzbot May 4, 2020
43ed6f1
Fix lint errors
fronzbot May 4, 2020
c122c4e
Merge pull request #235 from fronzbot/dependabot/pip/pylint-2.5.0
fronzbot May 4, 2020
6a2650d
Remove .flake8 file
fronzbot May 4, 2020
19b2541
Merge pull request #236 from fronzbot/remove-flake8-filewq
fronzbot May 4, 2020
b201c95
Remove Python 3.5.3 support
fronzbot May 4, 2020
addc32e
Merge pull request #237 from fronzbot/deprecate-py35
fronzbot May 4, 2020
e1bbbb5
Add black formatting style
fronzbot May 4, 2020
1dbb8d4
Add black badge
fronzbot May 4, 2020
28271ef
Remove hound.
fronzbot May 4, 2020
5a5c34b
Merge pull request #238 from fronzbot/add-black
fronzbot May 4, 2020
cdd01c5
Fix codecov threshold
fronzbot May 4, 2020
7247348
Merge pull request #239 from fronzbot/codecov-threshold
fronzbot May 4, 2020
819e383
Bump pylint from 2.5.0 to 2.5.1
dependabot-preview[bot] May 5, 2020
853c596
Merge pull request #240 from fronzbot/dependabot/pip/pylint-2.5.1
fronzbot May 5, 2020
f80a93f
Refactor login logic in preperation for 2FA
fronzbot May 5, 2020
c51551a
Add skeleton for 2FA
fronzbot May 5, 2020
9bc20cc
Merge pull request #241 from fronzbot/refactor-login-logic
fronzbot May 5, 2020
0c79620
Updated login method to allow for email verification and 2FA in future
fronzbot May 5, 2020
0c7737c
Update README
fronzbot May 5, 2020
1e86e7e
Add unit tests for new methods
fronzbot May 6, 2020
86aae07
Merge pull request #242 from fronzbot/add-2FA
fronzbot May 6, 2020
33f0e16
Bump pylint from 2.5.1 to 2.5.2
dependabot-preview[bot] May 6, 2020
d49a1fe
Fix typo, remove Python Version info
fronzbot May 6, 2020
1d65d55
Fix typo
fronzbot May 6, 2020
887a1d0
Merge pull request #244 from fronzbot/fix-typos
fronzbot May 6, 2020
2f0cec2
Merge pull request #243 from fronzbot/dependabot/pip/pylint-2.5.2
fronzbot May 6, 2020
dfb90b8
Dev version bump
fronzbot May 6, 2020
4b11a8b
Add ability to have unique device name per application
fronzbot May 6, 2020
60cbcb7
Update login methods to ensure platform is refreshed
fronzbot May 6, 2020
ec476bb
quick codecov threshold fix...maybe
fronzbot May 6, 2020
e3f9f4b
Merge pull request #245 from fronzbot/add-device-id-param
fronzbot May 6, 2020
a8605bd
Dev version bump
fronzbot May 6, 2020
7b2e015
Pin test requirements
fronzbot May 7, 2020
255812d
Merge pull request #246 from fronzbot/pin-requirements
fronzbot May 7, 2020
12b5dfd
Bump pytest-timeout from 1.3.3 to 1.3.4
dependabot-preview[bot] May 8, 2020
62a74db
Bump pytest-sugar from 0.9.2 to 0.9.3
dependabot-preview[bot] May 8, 2020
90ad0c7
Merge pull request #249 from fronzbot/dependabot/pip/pytest-timeout-1…
fronzbot May 8, 2020
9d6075c
Merge branch 'dev' into dependabot/pip/pytest-sugar-0.9.3
fronzbot May 8, 2020
e953a2f
Version bump
fronzbot May 8, 2020
f15f00e
Merge pull request #250 from fronzbot/dependabot/pip/pytest-sugar-0.9.3
fronzbot May 8, 2020
78ec104
Bump pygments from 2.2.0 to 2.6.1
dependabot-preview[bot] May 8, 2020
4582600
Merge pull request #252 from fronzbot/dependabot/pip/pygments-2.6.1
fronzbot May 8, 2020
7a2b3b9
Bump restructuredtext-lint from 1.0.1 to 1.3.0
dependabot-preview[bot] May 8, 2020
5c9ced0
Merge pull request #251 from fronzbot/dependabot/pip/restructuredtext…
fronzbot May 8, 2020
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 0 additions & 2 deletions .flake8

This file was deleted.

30 changes: 30 additions & 0 deletions .github/stale.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
# Number of days of inactivity before an issue becomes stale
daysUntilStale: 60

# Number of days of inactivity before a stale issue is closed
daysUntilClose: 7

# Issues with these labels will never be considered stale
exemptLabels:
- Priority
- bug
- Help Wanted

# Set to true to ignore issues in a project (defaults to false)
exemptProjects: true

# Set to true to ignore issues in a milestone (defaults to false)
exemptMilestones: true

# Label to use when marking an issue as stale
staleLabel: stale

# Comment to post when marking an issue as stale. Set to `false` to disable
markComment: >
This issue has been automatically marked as stale because it has not had
recent activity. It will be closed if no further activity occurs within seven days. Thank you
for your contributions.

# Comment to post when closing a stale issue. Set to `false` to disable
closeComment: >
This issue is now being closed due to inactivity.
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: 4
max-parallel: 3
matrix:
platform:
- ubuntu-latest
python-version: [3.5, 3.6, 3.7, 3.8]
python-version: [3.6, 3.7, 3.8]

steps:
- uses: actions/checkout@v2
Expand Down
2 changes: 1 addition & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
.tox/*
__pycache__/*
htmlcov/*
.coverage
.coverage.*
coverage.xml
*.pyc
*.egg*/*
Expand Down
11 changes: 0 additions & 11 deletions .hound.yml

This file was deleted.

20 changes: 12 additions & 8 deletions README.rst
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
blinkpy |Build Status| |Coverage Status| |Docs| |PyPi Version| |Python Version|
================================================================================
A Python library for the Blink Camera system
blinkpy |Build Status| |Coverage Status| |Docs| |PyPi Version| |Codestyle|
=============================================================================================
A Python library for the Blink Camera system (Python 3.6+)

Like the library? Consider buying me a cup of coffee!

Expand Down Expand Up @@ -53,7 +53,12 @@ The simplest way to use this package from a terminal is to call ``Blink.start()`
blink = blinkpy.Blink(username='YOUR USER NAME', password='YOUR PASSWORD', refresh_rate=30)
blink.start()

If you would like to log in without setting up the cameras or system, you can simply call the ``Blink.login()`` function which will prompt for a username and password and then authenticate with the server. This is useful if you want to avoid use of the ``start()`` function which simply acts as a wrapper for more targeted API methods.
At startup, you may be prompted for a verification key. Just enter this in the command-line prompt. If you just receive a verification email asking to validate access for your device, enter nothing at this prompt. To avoid any command-line interaction, call the ``Blink`` class with the ``no_prompt=True`` flag. Instead, once you receive the verification email, call the following functions:

.. code:: python

blink.login_handler.send_auth_key(blink, VERIFICATION_KEY)
blink.setup_post_verify()

In addition, you can also save your credentials in a json file and initialize Blink with the credential file as follows:

Expand Down Expand Up @@ -124,9 +129,8 @@ Example usage, which downloads all videos recorded since July 4th, 2018 at 9:34a
.. |PyPi Version| image:: https://img.shields.io/pypi/v/blinkpy.svg
:target: https://pypi.python.org/pypi/blinkpy
.. |Docs| image:: https://readthedocs.org/projects/blinkpy/badge/?version=latest
:target: http://blinkpy.readthedocs.io/en/latest/?badge=latest
.. |Python Version| image:: https://img.shields.io/pypi/pyversions/blinkpy.svg
:target: https://img.shields.io/pypi/pyversions/blinkpy.svg

:target: http://blinkpy.readthedocs.io/en/latest/?badge=latest
.. |Donate| image:: https://www.paypalobjects.com/en_US/i/btn/btn_donateCC_LG.gif
:target: https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=UR6Z2B8GXYUCC
.. |Codestyle| image:: https://img.shields.io/badge/code%20style-black-000000.svg
:target: https://github.com/psf/black
10 changes: 5 additions & 5 deletions app/app.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,17 +4,17 @@
from blinkpy import blinkpy


USERNAME = environ.get('USERNAME')
PASSWORD = environ.get('PASSWORD')
TIMEDELTA = timedelta(environ.get('TIMEDELTA', 1))
USERNAME = environ.get("USERNAME")
PASSWORD = environ.get("PASSWORD")
TIMEDELTA = timedelta(environ.get("TIMEDELTA", 1))


def get_date():
"""Return now - timedelta for blinkpy."""
return (datetime.now() - TIMEDELTA).isoformat()


def download_videos(blink, save_dir='/media'):
def download_videos(blink, save_dir="/media"):
"""Make request to download videos."""
blink.download_videos(save_dir, since=get_date())

Expand All @@ -26,6 +26,6 @@ def start():
return blink


if __name__ == '__main__':
if __name__ == "__main__":
BLINK = start()
download_videos(BLINK)
131 changes: 89 additions & 42 deletions blinkpy/api.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,27 +11,69 @@
MIN_THROTTLE_TIME = 2


def request_login(blink, url, username, password, is_retry=False):
def request_login(
blink,
url,
username,
password,
notification_key,
uid,
is_retry=False,
device_id="Blinkpy",
):
"""
Login request.

:param blink: Blink instance.
:param url: Login url.
:param username: Blink username.
:param password: Blink password.
:param notification_key: Randomly genereated key.
:param uid: Randomly generated unique id key.
:param is_retry: Is this part of a re-authorization attempt?
"""
headers = {
'Host': DEFAULT_URL,
'Content-Type': 'application/json'
}
data = dumps({
'email': username,
'password': password,
'client_specifier': 'iPhone 9.2 | 2.2 | 222'
})
return http_req(blink, url=url, headers=headers, data=data,
json_resp=False, reqtype='post', is_retry=is_retry)
:param device_id: Name of application to send at login.
"""
headers = {"Host": DEFAULT_URL, "Content-Type": "application/json"}
data = dumps(
{
"email": username,
"password": password,
"notification_key": notification_key,
"unique_id": uid,
"app_version": "6.0.7 (520300) #afb0be72a",
"client_name": "Computer",
"client_type": "android",
"device_identifier": device_id,
"device_name": "Blinkpy",
"os_version": "5.1.1",
"reauth": "true",
}
)
return http_req(
blink,
url=url,
headers=headers,
data=data,
json_resp=False,
reqtype="post",
is_retry=is_retry,
)


def request_verify(blink, verify_key):
"""Send verification key to blink servers."""
url = "{}/api/v4/account/{}/client/{}/pin/verify".format(
blink.urls.base_url, blink.account_id, blink.client_id
)
data = dumps({"pin": verify_key})
return http_req(
blink,
url=url,
headers=blink.auth_header,
data=data,
json_resp=False,
reqtype="post",
)


def request_networks(blink):
Expand Down Expand Up @@ -94,17 +136,16 @@ def request_command_status(blink, network, command_id):
:param network: Sync module network id.
:param command_id: Command id to check.
"""
url = "{}/network/{}/command/{}".format(blink.urls.base_url,
network,
command_id)
url = "{}/network/{}/command/{}".format(blink.urls.base_url, network, command_id)
return http_get(blink, url)


@Throttle(seconds=MIN_THROTTLE_TIME)
def request_homescreen(blink):
"""Request homescreen info."""
url = "{}/api/v3/accounts/{}/homescreen".format(blink.urls.base_url,
blink.account_id)
url = "{}/api/v3/accounts/{}/homescreen".format(
blink.urls.base_url, blink.account_id
)
return http_get(blink, url)


Expand All @@ -129,9 +170,9 @@ def request_new_image(blink, network, camera_id):
:param network: Sync module network id.
:param camera_id: Camera ID of camera to request new image from.
"""
url = "{}/network/{}/camera/{}/thumbnail".format(blink.urls.base_url,
network,
camera_id)
url = "{}/network/{}/camera/{}/thumbnail".format(
blink.urls.base_url, network, camera_id
)
return http_post(blink, url)


Expand All @@ -144,9 +185,7 @@ def request_new_video(blink, network, camera_id):
:param network: Sync module network id.
:param camera_id: Camera ID of camera to request new video from.
"""
url = "{}/network/{}/camera/{}/clip".format(blink.urls.base_url,
network,
camera_id)
url = "{}/network/{}/camera/{}/clip".format(blink.urls.base_url, network, camera_id)
return http_post(blink, url)


Expand All @@ -167,7 +206,8 @@ def request_videos(blink, time=None, page=0):
"""
timestamp = get_time(time)
url = "{}/api/v1/accounts/{}/media/changed?since={}&page={}".format(
blink.urls.base_url, blink.account_id, timestamp, page)
blink.urls.base_url, blink.account_id, timestamp, page
)
return http_get(blink, url)


Expand All @@ -190,9 +230,9 @@ def request_camera_info(blink, network, camera_id):
:param network: Sync module network id.
:param camera_id: Camera ID of camera to request info from.
"""
url = "{}/network/{}/camera/{}/config".format(blink.urls.base_url,
network,
camera_id)
url = "{}/network/{}/camera/{}/config".format(
blink.urls.base_url, network, camera_id
)
return http_get(blink, url)


Expand All @@ -204,9 +244,9 @@ def request_camera_sensors(blink, network, camera_id):
:param network: Sync module network id.
:param camera_id: Camera ID of camera to request sesnor info from.
"""
url = "{}/network/{}/camera/{}/signals".format(blink.urls.base_url,
network,
camera_id)
url = "{}/network/{}/camera/{}/signals".format(
blink.urls.base_url, network, camera_id
)
return http_get(blink, url)


Expand All @@ -219,9 +259,9 @@ def request_motion_detection_enable(blink, network, camera_id):
:param network: Sync module network id.
:param camera_id: Camera ID of camera to enable.
"""
url = "{}/network/{}/camera/{}/enable".format(blink.urls.base_url,
network,
camera_id)
url = "{}/network/{}/camera/{}/enable".format(
blink.urls.base_url, network, camera_id
)
return http_post(blink, url)


Expand All @@ -233,9 +273,9 @@ def request_motion_detection_disable(blink, network, camera_id):
:param network: Sync module network id.
:param camera_id: Camera ID of camera to disable.
"""
url = "{}/network/{}/camera/{}/disable".format(blink.urls.base_url,
network,
camera_id)
url = "{}/network/{}/camera/{}/disable".format(
blink.urls.base_url, network, camera_id
)
return http_post(blink, url)


Expand All @@ -251,9 +291,15 @@ def http_get(blink, url, stream=False, json=True, is_retry=False):
if blink.auth_header is None:
raise BlinkException(ERROR.AUTH_TOKEN)
_LOGGER.debug("Making GET request to %s", url)
return http_req(blink, url=url, headers=blink.auth_header,
reqtype='get', stream=stream, json_resp=json,
is_retry=is_retry)
return http_req(
blink,
url=url,
headers=blink.auth_header,
reqtype="get",
stream=stream,
json_resp=json,
is_retry=is_retry,
)


def http_post(blink, url, is_retry=False):
Expand All @@ -266,5 +312,6 @@ def http_post(blink, url, is_retry=False):
if blink.auth_header is None:
raise BlinkException(ERROR.AUTH_TOKEN)
_LOGGER.debug("Making POST request to %s", url)
return http_req(blink, url=url, headers=blink.auth_header,
reqtype='post', is_retry=is_retry)
return http_req(
blink, url=url, headers=blink.auth_header, reqtype="post", is_retry=is_retry
)
Loading