feat: add local files provider with indexing and rescan functionality

- Implemented LocalFilesProvider to manage local video files.
- Added LocalIndex for in-memory and SQLite-backed indexing of video files.
- Introduced scanning functionality to detect video files and extract metadata.
- Added API endpoints for listing collections, genres, and series based on provider capabilities.
- Enhanced existing routes to check for provider capabilities before processing requests.
- Updated frontend to utilize provider capabilities for conditional rendering of UI elements.
- Implemented rescan functionality to refresh the local files index.
- Added database migration for local files index schema.
This commit is contained in:
2026-03-14 03:44:32 +01:00
parent 9b6bcfc566
commit 8f42164bce
30 changed files with 1033 additions and 59 deletions

View File

@@ -136,6 +136,11 @@ async fn list_collections(
State(state): State<AppState>,
CurrentUser(_user): CurrentUser,
) -> Result<Json<Vec<CollectionResponse>>, ApiError> {
if !state.media_provider.capabilities().collections {
return Err(ApiError::not_implemented(
"collections not supported by this provider",
));
}
let collections = state.media_provider.list_collections().await?;
Ok(Json(collections.into_iter().map(Into::into).collect()))
}
@@ -146,6 +151,11 @@ async fn list_series(
CurrentUser(_user): CurrentUser,
Query(params): Query<SeriesQuery>,
) -> Result<Json<Vec<SeriesResponse>>, ApiError> {
if !state.media_provider.capabilities().series {
return Err(ApiError::not_implemented(
"series not supported by this provider",
));
}
let series = state
.media_provider
.list_series(params.collection.as_deref())
@@ -159,6 +169,11 @@ async fn list_genres(
CurrentUser(_user): CurrentUser,
Query(params): Query<GenresQuery>,
) -> Result<Json<Vec<String>>, ApiError> {
if !state.media_provider.capabilities().genres {
return Err(ApiError::not_implemented(
"genres not supported by this provider",
));
}
let ct = parse_content_type(params.content_type.as_deref())?;
let genres = state.media_provider.list_genres(ct.as_ref()).await?;
Ok(Json(genres))