only the WebDavSyncService is now registered, syncing into Jellyfin’s DefaultUserViewsPath

This commit is contained in:
copyrights 2025-04-21 09:38:08 +02:00
parent eacb6134a0
commit 28bc6d6a28
2 changed files with 88 additions and 16 deletions

View file

@ -8,31 +8,55 @@ namespace Jellyfin.Plugin.Webdav
using System;
using System.Collections.Generic;
using System.IO;
using System.Net;
using System.Threading.Tasks;
using Jellyfin.Plugin.Webdav.Configuration;
using WebDav.Client;
/// <summary>
/// Service for interacting with WebDAV endpoints.
/// </summary>
public sealed class WebDavClientService
{
private readonly PluginConfiguration _configuration;
private readonly PluginConfiguration _config;
private readonly WebDavClient _client;
public WebDavClientService(PluginConfiguration configuration)
/// <summary>
/// Initializes a new instance of the <see cref="WebDavClientService"/> class.
/// </summary>
/// <param name="config">Plugin configuration.</param>
public WebDavClientService(PluginConfiguration config)
{
_configuration = configuration;
_config = config;
var parameters = new WebDavClientParams
{
BaseAddress = new Uri(_config.BaseUrl.TrimEnd('/')),
Credentials = new NetworkCredential(_config.Username, _config.Password),
PreAuthenticate = true
};
_client = new WebDavClient(parameters);
}
/// <summary>List resources at the specified WebDAV path.</summary>
public Task<IEnumerable<object>> ListAsync(string path)
/// <summary>
/// Lists resources at the specified WebDAV path.
/// </summary>
/// <param name="path">Remote path.</param>
/// <returns>A collection of WebDAV resources.</returns>
public async Task<IEnumerable<WebDavResource>> ListAsync(string path)
{
return Task.FromResult<IEnumerable<object>>(Array.Empty<object>());
var response = await _client.Propfind(path).ConfigureAwait(false);
return response.Resources;
}
/// <summary>Get a raw file stream from the WebDAV endpoint.</summary>
public Task<Stream> GetStreamAsync(string path)
/// <summary>
/// Gets a raw file stream from the WebDAV endpoint.
/// </summary>
/// <param name="path">Remote file path.</param>
/// <returns>A stream for the remote file.</returns>
public async Task<Stream> GetStreamAsync(string path)
{
return Task.FromResult<Stream>(Stream.Null);
var response = await _client.GetRawFile(path).ConfigureAwait(false);
return response.Stream;
}
}
}

View file

@ -6,28 +6,39 @@
namespace Jellyfin.Plugin.Webdav
{
using System.IO;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using MediaBrowser.Controller;
using Jellyfin.Plugin.Webdav.Configuration;
using MediaBrowser.Controller.Library;
using MediaBrowser.Model.Configuration;
using Microsoft.Extensions.Hosting;
/// <summary>
/// Hosted service that registers the WebDAV cache as a virtual folder on startup.
/// Hosted service that synchronizes WebDAV content into the local cache directory
/// and registers it as a Jellyfin virtual folder.
/// </summary>
public sealed class WebDavSyncService : IHostedService
{
private readonly WebDavClientService client;
private readonly PluginConfiguration config;
private readonly IServerApplicationPaths appPaths;
private readonly ILibraryManager libraryManager;
/// <summary>
/// Initializes a new instance of the <see cref="WebDavSyncService"/> class.
/// </summary>
/// <param name="client">The WebDAV client service.</param>
/// <param name="config">The plugin configuration.</param>
/// <param name="appPaths">Server application paths.</param>
/// <param name="libraryManager">Library manager.</param>
public WebDavSyncService(IServerApplicationPaths appPaths, ILibraryManager libraryManager)
public WebDavSyncService(
WebDavClientService client,
PluginConfiguration config,
IServerApplicationPaths appPaths,
ILibraryManager libraryManager)
{
this.client = client;
this.config = config;
this.appPaths = appPaths;
this.libraryManager = libraryManager;
}
@ -35,15 +46,52 @@ namespace Jellyfin.Plugin.Webdav
/// <inheritdoc/>
public async Task StartAsync(CancellationToken cancellationToken)
{
var localRoot = Path.Combine(this.appPaths.DefaultUserViewsPath, "WebDAV");
Directory.CreateDirectory(localRoot);
var localRoot = config.CacheDirectory;
if (!Directory.Exists(localRoot))
{
Directory.CreateDirectory(localRoot);
}
await SyncDirectoryAsync(config.RootPath.Trim('/'), localRoot, cancellationToken)
.ConfigureAwait(false);
var options = new LibraryOptions();
await this.libraryManager
await libraryManager
.AddVirtualFolder("WebDAV", null, options, true)
.ConfigureAwait(false);
}
private async Task SyncDirectoryAsync(string remotePath, string localPath, CancellationToken token)
{
var resources = await client.ListAsync(remotePath).ConfigureAwait(false);
foreach (var item in resources.Where(r => !string.IsNullOrEmpty(r.DisplayName)))
{
if (token.IsCancellationRequested)
{
break;
}
var name = item.DisplayName!;
var remoteItem = $"{remotePath}/{name}";
var localItem = Path.Combine(localPath, name);
if (item.IsCollection)
{
if (!Directory.Exists(localItem))
{
Directory.CreateDirectory(localItem);
}
await SyncDirectoryAsync(remoteItem, localItem, token).ConfigureAwait(false);
}
else
{
using var stream = await client.GetStreamAsync(remoteItem).ConfigureAwait(false);
using var fs = File.Create(localItem);
await stream.CopyToAsync(fs, token).ConfigureAwait(false);
}
}
}
/// <inheritdoc/>
public Task StopAsync(CancellationToken cancellationToken) => Task.CompletedTask;
}