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

5.6 KiB
Raw Permalink Blame History

Nextcloud/WebDAV Jellyfin Plugin Plan

Below is a high-level plan for a Jellyfin plugin that integrates Nextcloud/WebDAV sources as library content.

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)

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 BaseItems.

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:
    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