Skip to content

Commit

Permalink
Merge pull request #76 from projectmovio/update-episode-progress
Browse files Browse the repository at this point in the history
Update episode progress
  • Loading branch information
fulder authored Oct 25, 2021
2 parents 599d0eb + 9d18d05 commit 5f28d35
Show file tree
Hide file tree
Showing 7 changed files with 165 additions and 31 deletions.
8 changes: 8 additions & 0 deletions src/lambdas/api/episode_by_collection_item/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -160,6 +160,14 @@ def _post_episode(username, collection_name, item_id, body, token):
body
)

watch_history_db.change_watched_eps(
username,
collection_name,
item_id,
1,
special=res["is_special"]
)

if "dates_watched" not in body:
return {
"statusCode": 200,
Expand Down
28 changes: 25 additions & 3 deletions src/lambdas/api/episode_by_id/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -39,9 +39,10 @@ def handle(event, context):
elif method == "PUT":
body = event.get("body")
return _put_episode(username, collection_name, item_id, episode_id,
body, auth_header)
body, auth_header)
elif method == "DELETE":
return _delete_episode(username, collection_name, episode_id)
return _delete_episode(username, collection_name, item_id, episode_id,
auth_header)


def _get_episode(username, collection_name, item_id, episode_id, token):
Expand Down Expand Up @@ -125,6 +126,27 @@ def _put_episode(username, collection_name, item_id, episode_id, body, token):
return {"statusCode": 204}


def _delete_episode(username, collection_name, episode_id):
def _delete_episode(username, collection_name, item_id, episode_id, token):
res = None
try:
if collection_name == "anime":
res = anime_api.get_episode(item_id, episode_id, token)
elif collection_name == "show":
res = shows_api.get_episode(item_id, episode_id)
except utils.HttpError as e:
err_msg = f"Could not get {collection_name} episode for " \
f"item: {item_id} and episode_id: {episode_id}"
log.error(f"{err_msg}. Error: {str(e)}")
return {"statusCode": e.status_code,
"body": json.dumps({"message": err_msg}), "error": str(e)}

episodes_db.delete_episode(username, collection_name, episode_id)

watch_history_db.change_watched_eps(
username,
collection_name,
item_id,
-1,
special=res["is_special"]
)
return {"statusCode": 204}
9 changes: 4 additions & 5 deletions src/lambdas/subscribers/show_updates/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,11 +16,10 @@ def handle(event, context):
for item in items:
print(f"Updating item: {item}")

if "ep_progress" not in item:
item["ep_progress"] = 0
if "watched_eps" not in item:
item["watched_eps"] = 0
item["special_progress"] = 0
item["watched_special"] = 0
if "watched_specials" not in item:
item["watched_specials"] = 0

item["ep_count"] = show["ep_count"]
if item["ep_count"] == 0:
Expand All @@ -33,7 +32,7 @@ def handle(event, context):
if item["special_count"] == 0:
special_progress = 0
else:
special_progress = item["watched_special"] / item["special_count"]
special_progress = item["watched_specials"] / item["special_count"]
item["special_progress"] = str(round(special_progress * 100, 2))

watch_history_db.put_item(item)
32 changes: 31 additions & 1 deletion src/layers/databases/python/watch_history_db.py
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,8 @@ def add_item(username, collection_name, item_id, data=None):
except NotFoundError:
data["created_at"] = datetime.now().strftime("%Y-%m-%d %H:%M:%S")

update_item(username, collection_name, item_id, data, clean_whitelist=["deleted_at"])
update_item(username, collection_name, item_id, data,
clean_whitelist=["deleted_at"])


def delete_item(username, collection_name, item_id):
Expand Down Expand Up @@ -128,6 +129,35 @@ def update_item(username, collection_name, item_id, data,
)


def change_watched_eps(username, collection_name, item_id, change, special=False):
field_name = "ep"
if special:
field_name = "special"

item = get_item(username, collection_name, item_id)
if item[f"{field_name}_count"] == 0:
ep_progress = 0
else:
ep_progress = (item[f"watched_{field_name}s"] + (change)) / item[f"{field_name}_count"]
ep_progress = str(round(ep_progress * 100, 2))

_get_table().update_item(
Key={
"username": username,
"item_id": item_id,
},
UpdateExpression="SET #w=#w+:i, #p=:p",
ExpressionAttributeNames={
"#w": f"watched_{field_name}s",
"#e": f"{field_name}_progress",
},
ExpressionAttributeValues={
":p": ep_progress,
":i": change,
}
)


def get_watch_history(username, collection_name=None,
index_name=None, status_filter=None):
paginator = _get_client().get_paginator('query')
Expand Down
12 changes: 8 additions & 4 deletions test/unittest/test_episode_by_collection.py
Original file line number Diff line number Diff line change
Expand Up @@ -203,10 +203,12 @@ class TestPost:
@patch("api.episode_by_collection_item.watch_history_db.get_item")
@patch("api.episode_by_collection_item.watch_history_db.update_item")
@patch("api.episode_by_collection_item.episodes_db.update_episode")
def test_success_anime(self, mocked_update_episode, mocked_update_item, mocked_get_item, mocked_post_episode, mocked_post):
@patch("api.episode_by_collection_item.watch_history_db.change_watched_eps")
def test_success_anime(self, mocked_change_watched_eps, mocked_update_episode, mocked_update_item, mocked_get_item, mocked_post_episode, mocked_post):
mocked_post.return_value = True
mocked_post_episode.return_value = {
"id": "123"
"id": "123",
"is_special": False,
}
mocked_get_item.return_value = {
"latest_watch_date": "2030-01-01 10:00:00"
Expand All @@ -223,10 +225,12 @@ def test_success_anime(self, mocked_update_episode, mocked_update_item, mocked_g
@patch("api.episode_by_collection_item.watch_history_db.get_item")
@patch("api.episode_by_collection_item.watch_history_db.update_item")
@patch("api.episode_by_collection_item.episodes_db.update_episode")
def test_success_show(self, mocked_update_episode, mocked_update_item, mocked_get_item, mocked_post_episode, mocked_post):
@patch("api.episode_by_collection_item.watch_history_db.change_watched_eps")
def test_success_show(self, mocked_change_watched_eps, mocked_update_episode, mocked_update_item, mocked_get_item, mocked_post_episode, mocked_post):
mocked_post.return_value = True
mocked_post_episode.return_value = {
"id": "123"
"id": "123",
"is_special": False,
}
mocked_get_item.return_value = {
"latest_watch_date": "2030-01-01 10:00:00"
Expand Down
4 changes: 3 additions & 1 deletion test/unittest/test_episode_by_id.py
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,9 @@ class TestDelete:
}

@patch("api.episode_by_id.episodes_db.delete_episode")
def test_success(self, mocked_delete):
@patch("api.episode_by_id.anime_api.get_episode")
@patch("api.episode_by_id.watch_history_db.change_watched_eps")
def test_success(self, mocked_change_watched_eps, mocked_anime_api, mocked_delete):
mocked_delete.return_value = True

ret = handle(self.event, None)
Expand Down
103 changes: 86 additions & 17 deletions test/unittest/test_watch_history_db.py
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ def test_get_watch_history(mocked_watch_history_db):
"KeyConditionExpression": "username = :username",
"ExpressionAttributeValues": {":username": {"S": "TEST_USERNAME"}},
"ScanIndexForward": False,
'FilterExpression': 'attribute_not_exists(deleted_at)',
"FilterExpression": "attribute_not_exists(deleted_at)",
}
assert res == mock_func.exp_res

Expand Down Expand Up @@ -78,8 +78,8 @@ def test_get_watch_history_by_collection_and_index(mocked_watch_history_db):
m.paginate = mock_func.f

res = mocked_watch_history_db.get_watch_history(TEST_USERNAME,
collection_name="ANIME",
index_name="test_index")
collection_name="ANIME",
index_name="test_index")

assert mock_func.update_values == {
"ExpressionAttributeValues": {
Expand All @@ -103,24 +103,24 @@ def test_add_item(mocked_watch_history_db):
mocked_watch_history_db.add_item(TEST_USERNAME, "MOVIE", "123123")

assert mock_func.update_values == {
'ExpressionAttributeNames': {
'#collection_name': 'collection_name',
'#created_at': 'created_at',
'#deleted_at': 'deleted_at',
'#latest_watch_date': 'latest_watch_date',
'#updated_at': 'updated_at',
"ExpressionAttributeNames": {
"#collection_name": "collection_name",
"#created_at": "created_at",
"#deleted_at": "deleted_at",
"#latest_watch_date": "latest_watch_date",
"#updated_at": "updated_at",
},
'ExpressionAttributeValues': {
':collection_name': 'MOVIE',
"ExpressionAttributeValues": {
":collection_name": "MOVIE",
":created_at": datetime.now().strftime("%Y-%m-%d %H:%M:%S"),
':latest_watch_date': '0',
":latest_watch_date": "0",
":updated_at": datetime.now().strftime("%Y-%m-%d %H:%M:%S")
},
'Key': {
'username': TEST_USERNAME,
'item_id': '123123'},
'UpdateExpression': 'SET #latest_watch_date=:latest_watch_date,#created_at=:created_at,#collection_name=:collection_name,#updated_at=:updated_at '
'REMOVE #deleted_at'
"Key": {
"username": TEST_USERNAME,
"item_id": "123123"},
"UpdateExpression": "SET #latest_watch_date=:latest_watch_date,#created_at=:created_at,#collection_name=:collection_name,#updated_at=:updated_at "
"REMOVE #deleted_at"
}


Expand Down Expand Up @@ -328,3 +328,72 @@ def test_get_item_not_found(mocked_watch_history_db):

with pytest.raises(mocked_watch_history_db.NotFoundError):
mocked_watch_history_db.get_item(TEST_USERNAME, "MOVIE", "123123")


def test_change_watched_eps(mocked_watch_history_db):
mock_func = MockFunc()
mocked_watch_history_db.table.update_item = mock_func.f
mocked_watch_history_db.table.query.return_value = {
"Items": [
{
"ep_count": 10,
"watched_eps": 1,
}
]
}

mocked_watch_history_db.change_watched_eps(TEST_USERNAME, "MOVIE", "123123",
1)

assert mock_func.update_values == {
'ExpressionAttributeNames': {'#e': 'ep_progress', '#w': 'watched_eps'},
'ExpressionAttributeValues': {':i': 1, ':p': '20.0'},
'Key': {'item_id': '123123', 'username': 'TEST_USERNAME'},
'UpdateExpression': 'SET #w=#w+:i, #p=:p'
}


def test_change_watched_eps_removal(mocked_watch_history_db):
mock_func = MockFunc()
mocked_watch_history_db.table.update_item = mock_func.f
mocked_watch_history_db.table.query.return_value = {
"Items": [
{
"ep_count": 10,
"watched_eps": 1,
}
]
}

mocked_watch_history_db.change_watched_eps(TEST_USERNAME, "MOVIE", "123123",
-1)

assert mock_func.update_values == {
'ExpressionAttributeNames': {'#e': 'ep_progress', '#w': 'watched_eps'},
'ExpressionAttributeValues': {':i': -1, ':p': '0.0'},
'Key': {'item_id': '123123', 'username': 'TEST_USERNAME'},
'UpdateExpression': 'SET #w=#w+:i, #p=:p'
}


def test_change_watched_specials(mocked_watch_history_db):
mock_func = MockFunc()
mocked_watch_history_db.table.update_item = mock_func.f
mocked_watch_history_db.table.query.return_value = {
"Items": [
{
"special_count": 20,
"watched_specials": 2,
}
]
}

mocked_watch_history_db.change_watched_eps(TEST_USERNAME, "MOVIE", "123123",
1, special=True)

assert mock_func.update_values == {
'ExpressionAttributeNames': {'#e': 'special_progress', '#w': 'watched_specials'},
'ExpressionAttributeValues': {':i': 1, ':p': '15.0'},
'Key': {'item_id': '123123', 'username': 'TEST_USERNAME'},
'UpdateExpression': 'SET #w=#w+:i, #p=:p'
}

0 comments on commit 5f28d35

Please sign in to comment.