fix: removing favorites not being commited to db

+ improve: collision of hashes on the favorite table
+ rename pages to collections
+ bump mix sleep time from 6hrs to 12hrs
This commit is contained in:
cwilvx
2025-02-25 23:30:51 +03:00
parent 0a1ab72932
commit 620974561c
8 changed files with 215 additions and 190 deletions
+2 -2
View File
@@ -18,11 +18,11 @@ from .plugins import mixes as mixes_plugin
from app.api import (
album,
artist,
collections,
colors,
favorites,
folder,
imgserver,
pages,
playlist,
search,
settings,
@@ -112,7 +112,7 @@ def create_api():
app.register_api(colors.api)
app.register_api(lyrics.api)
app.register_api(backup_and_restore.api)
app.register_api(pages.api)
app.register_api(collections.api)
# Plugins
app.register_api(plugins.api)
app.register_api(lyrics_plugin.api)
+182
View File
@@ -0,0 +1,182 @@
"""
Contains all the collection routes.
"""
from typing import Any
from flask_openapi3 import Tag
from flask_openapi3 import APIBlueprint
from pydantic import BaseModel, Field
from app.db.userdata import CollectionTable
from app.lib.pagelib import recover_page_items, remove_page_items, validate_page_items
from app.utils.auth import get_current_userid
bp_tag = Tag(name="Collections", description="Collections")
api = APIBlueprint(
"collections", __name__, url_prefix="/collections", abp_tags=[bp_tag]
)
class CreateCollectionBody(BaseModel):
name: str = Field(description="The name of the collection")
description: str = Field(description="The description of the collection")
items: list[dict[str, Any]] = Field(
description="The items to add to the collection",
json_schema_extra={"example": [{"type": "album", "hash": "1234567890"}]},
)
@api.post("")
def create_collection(body: CreateCollectionBody):
"""
Create a new collection.
"""
items = validate_page_items(body.items, existing=[])
if len(items) == 0:
return {"error": "No items to add"}, 400
payload = {
"name": body.name,
"items": items,
"userid": get_current_userid(),
"extra": {
"description": body.description,
},
}
CollectionTable.insert_one(payload)
return {"message": "collection created"}, 201
@api.get("")
def get_collections():
"""
Get all collections.
"""
return [collection for collection in CollectionTable.get_all()]
class AddCollectionItemBody(BaseModel):
item: dict[str, Any] = Field(
description="The item to add to the collection",
json_schema_extra={"example": {"type": "album", "hash": "1234567890"}},
)
class AddCollectionItemPath(BaseModel):
collection_id: int = Field(
description="The ID of the collection to add items to",
json_schema_extra={"example": 1},
)
@api.post("/<int:collection_id>/items")
def add_collection_item(path: AddCollectionItemPath, body: AddCollectionItemBody):
"""
Add an item to a collection.
"""
collection = CollectionTable.get_by_id(path.collection_id)
if collection is None:
return {"error": "Collection not found"}, 404
new_items = validate_page_items([body.item], existing=collection["items"])
if len(new_items) == 0:
return {"error": "items already in collection"}, 400
collection["items"].extend(new_items)
CollectionTable.update_items(collection["id"], collection["items"])
return {"message": "Items added to collection"}
class RemoveCollectionItemBody(BaseModel):
item: dict[str, Any] = Field(
description="The item to remove from the collection",
json_schema_extra={"example": {"type": "album", "hash": "1234567890"}},
)
class RemoveCollectionItemPath(BaseModel):
collection_id: int = Field(
description="The ID of the collection to remove items from"
)
@api.delete("/<int:collection_id>/items")
def remove_collection_item(
path: RemoveCollectionItemPath, body: RemoveCollectionItemBody
):
"""
Remove an item from a collection.
"""
collection = CollectionTable.get_by_id(path.collection_id)
if collection is None:
return {"error": "Collection not found"}, 404
remaining = remove_page_items(collection["items"], body.item)
CollectionTable.update_items(collection["id"], remaining)
return {"message": "Item removed from collection"}
class GetCollectionBody(BaseModel):
collection_id: int = Field(description="The ID of the collection to get")
@api.get("/<int:collection_id>")
def get_collection(path: GetCollectionBody):
"""
Get a collection.
"""
collection = CollectionTable.get_by_id(path.collection_id)
if not collection:
return {"error": "Collection not found"}, 404
items = recover_page_items(collection["items"])
return {
"id": collection["id"],
"name": collection["name"],
"items": items,
"extra": collection["extra"],
}
class UpdateCollectionBody(BaseModel):
name: str = Field(description="The name of the collection")
description: str = Field(
description="The description of the collection", default=""
)
@api.put("/<int:collection_id>")
def update_collection(path: GetCollectionBody, body: UpdateCollectionBody):
"""
Update a collection.
"""
payload = {
"id": path.collection_id,
"name": body.name,
"extra": {"description": body.description},
}
CollectionTable.update_one(payload)
return payload
class DeleteCollectionPath(BaseModel):
collection_id: int = Field(description="The ID of the collection to delete")
@api.delete("/<int:collection_id>")
def delete_collection(path: DeleteCollectionPath):
"""
Delete a collection.
"""
CollectionTable.delete_by_id(path.collection_id)
return {"message": "Collection deleted"}
+1 -6
View File
@@ -39,9 +39,8 @@ class FavoritesAddBody(BaseModel):
description="The hash of the item",
min_length=Defaults.HASH_LENGTH,
max_length=Defaults.HASH_LENGTH,
example=Defaults.API_ALBUMHASH,
)
type: str = Field(description="The type of the item", example=FavType.album)
type: str = Field(description="The type of the item")
def toggle_fav(type: str, hash: str):
@@ -110,7 +109,6 @@ class GetAllOfTypeQuery(GenericLimitSchema):
start: int = Field(
description="Where to start from",
example=Defaults.API_CARD_LIMIT,
default=Defaults.API_CARD_LIMIT,
)
@@ -167,19 +165,16 @@ class GetAllFavoritesQuery(BaseModel):
track_limit: int = Field(
description="The number of tracks to return",
example=Defaults.API_CARD_LIMIT,
default=Defaults.API_CARD_LIMIT,
)
album_limit: int = Field(
description="The number of albums to return",
example=Defaults.API_CARD_LIMIT,
default=Defaults.API_CARD_LIMIT,
)
artist_limit: int = Field(
description="The number of artists to return",
example=Defaults.API_CARD_LIMIT,
default=Defaults.API_CARD_LIMIT,
)
-173
View File
@@ -1,173 +0,0 @@
"""
Contains all the page routes.
"""
from typing import Any
from flask_openapi3 import Tag
from flask_openapi3 import APIBlueprint
from pydantic import BaseModel, Field
from app.db.userdata import PageTable
from app.lib.pagelib import recover_page_items, remove_page_items, validate_page_items
from app.utils.auth import get_current_userid
bp_tag = Tag(name="Pages", description="Pages")
api = APIBlueprint("pages", __name__, url_prefix="/pages", abp_tags=[bp_tag])
class CreatePageBody(BaseModel):
name: str = Field(description="The name of the page", example="My Page")
description: str = Field(
description="The description of the page", example="My Page"
)
items: list[dict[str, Any]] = Field(
description="The items to add to the page",
example=[{"type": "album", "hash": "1234567890"}],
)
@api.post("")
def create_page(body: CreatePageBody):
"""
Create a new page.
"""
items = validate_page_items(body.items, existing=[])
if len(items) == 0:
return {"error": "No items to add"}, 400
payload = {
"name": body.name,
"items": items,
"userid": get_current_userid(),
"extra": {
"description": body.description,
},
}
PageTable.insert_one(payload)
return {"message": "Page created"}, 201
@api.get("")
def get_pages():
"""
Get all pages.
"""
return [page for page in PageTable.get_all()]
class AddPageItemBody(BaseModel):
item: dict[str, Any] = Field(
description="The item to add to the page",
example={"type": "album", "hash": "1234567890"},
)
class AddPageItemPath(BaseModel):
page_id: int = Field(description="The ID of the page to add items to", example=1)
@api.post("/<int:page_id>/items")
def add_page_item(path: AddPageItemPath, body: AddPageItemBody):
"""
Add an item to a page.
"""
page = PageTable.get_by_id(path.page_id)
if page is None:
return {"error": "Page not found"}, 404
new_items = validate_page_items([body.item], existing=page["items"])
if len(new_items) == 0:
return {"error": "items already in page"}, 400
page["items"].extend(new_items)
PageTable.update_items(page["id"], page["items"])
return {"message": "Items added to page"}
class RemovePageItemBody(BaseModel):
item: dict[str, Any] = Field(
description="The item to remove from the page",
example={"type": "album", "hash": "1234567890"},
)
class RemovePageItemPath(BaseModel):
page_id: int = Field(description="The ID of the page to remove items from")
@api.delete("/<int:page_id>/items")
def remove_page_item(path: RemovePageItemPath, body: RemovePageItemBody):
"""
Remove an item from a page.
"""
page = PageTable.get_by_id(path.page_id)
if page is None:
return {"error": "Page not found"}, 404
remaining = remove_page_items(page["items"], body.item)
PageTable.update_items(page["id"], remaining)
return {"message": "Item removed from page"}
class GetPageBody(BaseModel):
page_id: int = Field(description="The ID of the page to get", example=1)
@api.get("/<int:page_id>")
def get_page(path: GetPageBody):
"""
Get a page.
"""
page = PageTable.get_by_id(path.page_id)
if not page:
return {"error": "Page not found"}, 404
items = recover_page_items(page["items"])
return {
"id": page["id"],
"name": page["name"],
"items": items,
"extra": page["extra"],
}
class UpdatePageBody(BaseModel):
name: str = Field(description="The name of the page")
description: str = Field(description="The description of the page", default="")
@api.put("/<int:page_id>")
def update_page(path: GetPageBody, body: UpdatePageBody):
"""
Update a page.
"""
payload = {
"id": path.page_id,
"name": body.name,
"extra": {"description": body.description},
}
PageTable.update_one(payload)
return {"page": payload}
class DeletePagePath(BaseModel):
page_id: int = Field(description="The ID of the page to delete")
@api.delete("/<int:page_id>")
def delete_page(path: DeletePagePath):
"""
Delete a page.
"""
PageTable.delete_by_id(path.page_id)
return {"message": "Page deleted"}