diff --git a/ServiceRegistrator.cs b/ServiceRegistrator.cs
index 15379ff..43112d3 100644
--- a/ServiceRegistrator.cs
+++ b/ServiceRegistrator.cs
@@ -14,7 +14,7 @@ namespace Jellyfin.Plugin.Webdav
public void RegisterServices(IServiceCollection services, IServerApplicationHost applicationHost)
{
services.AddSingleton
();
- services.AddSingleton();
+ services.AddHostedService();
}
}
}
\ No newline at end of file
diff --git a/WebDavSyncService.cs b/WebDavSyncService.cs
new file mode 100644
index 0000000..f89cc01
--- /dev/null
+++ b/WebDavSyncService.cs
@@ -0,0 +1,75 @@
+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
+{
+ ///
+ /// Hosted service that synchronizes WebDAV content into a local cache directory
+ /// and registers it as a Jellyfin virtual folder.
+ ///
+ 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;
+ }
+}
\ No newline at end of file