2022-01-29 16:50:22 -07:00
|
|
|
import pathlib
|
|
|
|
|
from typing import List
|
|
|
|
|
from urllib.request import Request
|
|
|
|
|
|
|
|
|
|
from sanic import response
|
2022-01-31 21:45:46 -07:00
|
|
|
from sanic_ext import validate
|
|
|
|
|
from sanic_ext.extensions.openapi import openapi
|
2022-01-29 16:50:22 -07:00
|
|
|
|
2022-01-31 17:00:40 -07:00
|
|
|
from wrolpi.common import get_media_directory, api_param_limiter
|
2022-02-01 12:22:29 -07:00
|
|
|
from wrolpi.errors import InvalidFile
|
2022-01-29 16:50:22 -07:00
|
|
|
from wrolpi.root_api import get_blueprint, json_response
|
|
|
|
|
from . import lib, schema
|
|
|
|
|
|
|
|
|
|
bp = get_blueprint('Files', '/api/files')
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def paths_to_files(paths: List[pathlib.Path]):
|
2022-01-29 21:24:39 -07:00
|
|
|
"""Convert Paths to what the React UI expects."""
|
2022-01-29 16:50:22 -07:00
|
|
|
media_directory = get_media_directory()
|
|
|
|
|
new_files = []
|
|
|
|
|
for path in paths:
|
|
|
|
|
stat = path.stat()
|
|
|
|
|
key = path.relative_to(media_directory)
|
|
|
|
|
modified = stat.st_mtime
|
|
|
|
|
if path.is_dir():
|
|
|
|
|
key = f'{key}/'
|
|
|
|
|
new_files.append(dict(
|
|
|
|
|
key=key,
|
|
|
|
|
modified=modified,
|
|
|
|
|
url=key,
|
|
|
|
|
name=path.name,
|
|
|
|
|
))
|
|
|
|
|
else:
|
|
|
|
|
# A File should know it's size.
|
|
|
|
|
new_files.append(dict(
|
|
|
|
|
key=key,
|
|
|
|
|
modified=modified,
|
|
|
|
|
size=stat.st_size,
|
|
|
|
|
url=key,
|
|
|
|
|
name=path.name,
|
|
|
|
|
))
|
|
|
|
|
return new_files
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@bp.post('/')
|
2022-02-03 11:36:26 -07:00
|
|
|
@openapi.definition(
|
|
|
|
|
summary='List files in a directory',
|
|
|
|
|
body=schema.FilesRequest,
|
|
|
|
|
)
|
2022-01-31 21:45:46 -07:00
|
|
|
@validate(schema.FilesRequest)
|
|
|
|
|
async def get_files(_: Request, body: schema.FilesRequest):
|
|
|
|
|
directories = body.directories or []
|
2022-01-29 16:50:22 -07:00
|
|
|
|
|
|
|
|
files = lib.list_files(directories)
|
|
|
|
|
files = paths_to_files(files)
|
|
|
|
|
return json_response({'files': files})
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@bp.post('/delete')
|
2022-02-03 11:36:26 -07:00
|
|
|
@openapi.definition(
|
|
|
|
|
summary='Delete a single file. Returns an error if WROL Mode is enabled.',
|
|
|
|
|
body=schema.DeleteRequest,
|
|
|
|
|
)
|
2022-01-31 21:45:46 -07:00
|
|
|
@validate(schema.DeleteRequest)
|
|
|
|
|
async def delete_file(_: Request, body: schema.DeleteRequest):
|
|
|
|
|
if not body.file:
|
2022-01-29 16:50:22 -07:00
|
|
|
raise InvalidFile('file cannot be empty')
|
2022-01-31 21:45:46 -07:00
|
|
|
lib.delete_file(body.file)
|
2022-01-29 16:50:22 -07:00
|
|
|
return response.empty()
|
2022-01-31 17:00:40 -07:00
|
|
|
|
|
|
|
|
|
|
|
|
|
files_limit_limiter = api_param_limiter(100)
|
|
|
|
|
files_offset_limiter = api_param_limiter(100, 0)
|
|
|
|
|
|
|
|
|
|
|
2022-02-01 12:22:29 -07:00
|
|
|
@bp.post('/refresh')
|
|
|
|
|
@openapi.description('Find and index all files')
|
|
|
|
|
async def refresh(_: Request):
|
|
|
|
|
lib.refresh_files()
|
|
|
|
|
return response.empty()
|
|
|
|
|
|
|
|
|
|
|
2022-01-31 17:00:40 -07:00
|
|
|
@bp.post('/search')
|
2022-02-03 11:36:26 -07:00
|
|
|
@openapi.definition(
|
|
|
|
|
summary='Search Files',
|
|
|
|
|
body=schema.FilesSearchRequest,
|
|
|
|
|
)
|
2022-02-01 12:22:29 -07:00
|
|
|
@validate(schema.FilesSearchRequest)
|
|
|
|
|
async def search_files(_: Request, body: schema.FilesSearchRequest):
|
|
|
|
|
files, total = lib.search(body.search_str, body.limit, body.offset)
|
|
|
|
|
return json_response(dict(files=files, totals=dict(files=total)))
|