Jellyfin.Plugin.Webdav/NextcloudPluginPlan.md
2025-04-21 23:13:46 +02:00

140 lines
5.6 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# Nextcloud/WebDAV Jellyfin Plugin Plan
Below is a high-level plan for a Jellyfin plugin that integrates Nextcloud/WebDAV sources as library content.
```mermaid
flowchart TD
subgraph Plugin Core
A[PluginConfiguration<br/> holds URL, creds, paths]
B[Plugin<br/> BasePlugin<Config>]
C[IPluginServiceRegistrator<br/> registers services]
D[IHostedService<br/> hook on startup]
end
subgraph Services
E[WebDavClientService<br/> wraps WebDav.Client]
F[RemoteLibraryProvider<br/> implements virtual folder scanning]
G[CachingLayer<br/> buffer / temporary file cache]
H[StreamingController<br/> ControllerBase for proxying streams]
end
subgraph Jellyfin Core
I[ILibraryManager<br/> library registration]
J[Scan Engine<br/> calls provider to enumerate items]
K[HTTP Pipeline<br/> routes to controllers]
end
A --> B
B --> C
C --> E
C --> F
E --> F
F --> J
F --> G
G --> H
H --> K
D --> I
I --> J
```
## 1. Skeleton & Setup
- Copy the `jellyfin-plugin-template` and rename to `Jellyfin.Plugin.Nextcloud`.
- Update project metadata: plugin ID, name, version in `.csproj`.
- Add NuGet reference to `WebDav.Client`.
## 2. Configuration & Dependency Injection
- Define `PluginConfiguration` with URL, credentials, root path, and cache settings.
- Implement `Plugin : BasePlugin<PluginConfiguration>` to override `Name`, `Id`, and inject DI.
- Create `IPluginServiceRegistrator` to register services:
- `WebDavClientService` (singleton)
- `RemoteLibraryProvider` (scanning)
- `StreamingController` (ASP.NET Controller)
- Register virtual folder with `ILibraryManager.RegisterVirtualFolder` on startup.
## 3. Scanning Proof-of-Concept (M2)
```mermaid
flowchart TD
subgraph Plugin Core
Cfg[PluginConfiguration<br/> holds URL, creds, rootPath, cache settings]
Reg[ServiceRegistrator<br/> registers DI & virtual folder]
end
subgraph Scanning POC
WCS[WebDavClientService<br/> list, HEAD for size]
RLP[RemoteLibraryProvider<br/> implements scanning]
MI[MediaInfoParser<br/> extract duration]
Items[BaseItem list]
end
Cfg --> Reg
Reg --> WCS
Reg --> RLP
WCS --> RLP
RLP --> MI
RLP --> Items
Items --> ScanEngine[Jellyfin Scan Engine]
```
**POC Interface Choice:**
Use an `IHostedService` (the existing `WebDavSyncService`) to sync remote content into a local cache directory, then register that directory via `ILibraryManager.AddVirtualFolder`. This leverages the builtin file system scan engine for enumeration and HEAD/partial reads for metadata retrieval.
### 3.1 Dependency Injection & Registration
- Add `RemoteLibraryProvider` to DI with `serviceCollection.AddSingleton<RemoteLibraryProvider>();`.
- On startup in a hosted service, call `ILibraryManager.RegisterVirtualFolder("Nextcloud", providerInstance)` to hook into Jellyfin's scan pipeline.
### 3.2 Plugin Configuration
- Ensure `PluginConfiguration` exposes:
- `WebDavUrl`, `Username`, `Password`
- `RootPath`, `CacheDirectory`, `CacheSizeMb`
### 3.3 RemoteLibraryProvider Implementation
- Inject `WebDavClientService`, `PluginConfiguration`, and `ILogger<RemoteLibraryProvider>` in the constructor.
- Implement `GetItemsAsync(BaseItem parent, CancellationToken ct)`:
1. Call `webDav.ListAsync(cfg.RootPath + parent.Path)` to enumerate remote children.
2. For directories: create `new BaseItem { Name = dirName, IsFolder = true, Id = GenerateId(path) }`.
3. For video files:
- Use `webDav.HeadAsync(path)` to get `Content-Length` for size.
- Download a small buffer and parse with `MediaInfoParser.Parse(stream)` to get `Duration`.
- Create `new BaseItem { Name = fileName, RunTimeTicks = durationTicks, MediaSources = { new MediaSourceInfo { Size = size } }, Id = GenerateId(path) }`.
4. Return the list of `BaseItem`s.
### 3.4 Logging & Diagnostics
- Log total items found per folder and individual metadata (size, duration) for verification.
### 3.5 Manual Validation
- Deploy locally, configure plugin with test Nextcloud credentials.
- Restart Jellyfin and trigger a library scan.
- Verify in logs that the `RemoteLibraryProvider` runs and emits items with correct size and duration.
## 4. Streaming & Caching
- Create `StreamingController : ControllerBase` with endpoint `/WebDav/Stream/{itemId}`.
- Map `itemId` to remote path and stream via `WebDavClientService.GetStream`.
- Implement `CachingLayer` to buffer chunks and write to temp files to prevent stalls.
## 5. Admin UI
- Define `configPage.html` as an embedded resource and implement `IHasWebPages` in `Plugin.cs` to return a `PluginPageInfo` for the settings page.
- Update `build.yaml` to include a `pages` section:
```yaml
pages:
- name: WebDAV
embeddedResourcePath: Jellyfin.Plugin.Webdav.Configuration.configPage.html
```
- Rebuild the plugin so that MSBuild generates a `plugin.json` manifest containing the pages definition.
- Deploy the `plugin.json`, DLL, and dependencies to Jellyfins `plugins` folder.
- Restart Jellyfin to verify the “WebDAV” settings page appears under Admin → Plugins.
## 6. Testing & Validation
- Unit-test `WebDavClientService` using a test Nextcloud instance or mock.
- Deploy plugin locally; verify library shows Nextcloud virtual folders.
- Test playback to ensure smooth streaming.
## 7. Documentation & Release
- Write README with installation, configuration, and troubleshooting guidance.
- Bump version, package plugin (`.nupkg`), and publish to GitHub Releases.
### Milestones
- **M1**: Plugin skeleton & DI wiring
- **M2**: Scanning proof-of-concept
- **M3**: Streaming proxy & caching
- **M4**: Admin UI & settings page
- **M5**: Testing, documentation, release