Jellyfin.Plugin.Webdav/WebDavSyncService.cs
copyrights 2811ed4aad The WebDAV integration plugin (Jellyfin.Plugin.Webdav) has been scaffolded according to the approved plan:
• Project renamed and updated (Jellyfin.Plugin.Webdav.csproj) with WebDav.Client reference

• Plugin.cs set to “WebDAV” with the new GUID

• Configuration/PluginConfiguration.cs defines the connection and cache settings

• ServiceRegistrator.cs wires DI for WebDavClientService and the WebDavSyncService hosted service

• WebDavClientService.cs wraps WebDav.Client for directory listing and streaming

• WebDavSyncService.cs syncs remote files into a local cache and registers it as a virtual folder

• StreamingController.cs exposes /WebDav/Stream/{*path} for streaming

• Configuration/configPage.html implements the dashboard configuration UI

Next step: build and deploy the plugin to your Jellyfin server’s plugins folder.
2025-04-19 21:59:22 +02:00

75 lines
2.9 KiB
C#

using System;
using System.IO;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.Extensions.Hosting;
using MediaBrowser.Controller.Library;
using MediaBrowser.Controller.Plugins;
namespace Jellyfin.Plugin.Webdav
{
/// <summary>
/// Hosted service that synchronizes WebDAV content into a local cache directory
/// and registers it as a Jellyfin virtual folder.
/// </summary>
public class WebDavSyncService : IHostedService
{
private readonly WebDavClientService _client;
private readonly PluginConfiguration _config;
private readonly ILibraryManager _libraryManager;
private readonly IServerApplicationHost _appHost;
public WebDavSyncService(WebDavClientService client, PluginConfiguration config, ILibraryManager libraryManager, IServerApplicationHost appHost)
{
_client = client;
_config = config;
_libraryManager = libraryManager;
_appHost = appHost;
}
public async Task StartAsync(CancellationToken cancellationToken)
{
// Compute local root under DefaultUserViewsPath
var localRoot = Path.Combine(_appHost.ApplicationPaths.DefaultUserViewsPath, "WebDAV");
Directory.CreateDirectory(localRoot);
// Sync directories recursively
await SyncDirectory(_config.RootPath, localRoot, cancellationToken).ConfigureAwait(false);
// Register the virtual folder pointing to the synced cache
var options = new LibraryOptions();
await _libraryManager.AddVirtualFolder("WebDAV", null, options, true).ConfigureAwait(false);
}
private async Task SyncDirectory(string remotePath, string localPath, CancellationToken cancellationToken)
{
var resources = await _client.ListAsync(remotePath).ConfigureAwait(false);
foreach (var res in resources.Where(r => r.DisplayName != null))
{
if (cancellationToken.IsCancellationRequested)
{
break;
}
var name = res.DisplayName;
var remoteSub = $"{remotePath.TrimEnd('/')}/{name}";
var localSub = Path.Combine(localPath, name);
if (res.IsCollection)
{
Directory.CreateDirectory(localSub);
await SyncDirectory(remoteSub, localSub, cancellationToken).ConfigureAwait(false);
}
else
{
using var stream = await _client.GetStreamAsync(remoteSub).ConfigureAwait(false);
using var fs = File.Create(localSub);
await stream.CopyToAsync(fs, cancellationToken).ConfigureAwait(false);
}
}
}
public Task StopAsync(CancellationToken cancellationToken) => Task.CompletedTask;
}
}