101 lines
3.9 KiB
C#
101 lines
3.9 KiB
C#
namespace Jellyfin.Plugin.Webdav
|
|
{
|
|
using System.IO;
|
|
using MediaBrowser.Controller;
|
|
using System.Linq;
|
|
using System.Threading;
|
|
using System.Threading.Tasks;
|
|
using Jellyfin.Plugin.Webdav.Configuration;
|
|
using MediaBrowser.Controller.Library;
|
|
using System.Collections.Generic;
|
|
using Microsoft.Extensions.Hosting;
|
|
using MediaBrowser.Model.Configuration;
|
|
|
|
/// <summary>
|
|
/// 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(
|
|
WebDavClientService client,
|
|
PluginConfiguration config,
|
|
IServerApplicationPaths appPaths,
|
|
ILibraryManager libraryManager)
|
|
{
|
|
this.client = client;
|
|
this.config = config;
|
|
this.appPaths = appPaths;
|
|
this.libraryManager = libraryManager;
|
|
}
|
|
|
|
/// <inheritdoc/>
|
|
public async Task StartAsync(CancellationToken cancellationToken)
|
|
{
|
|
// Determine cache root: either configured directory or default user views path
|
|
var baseCache = string.IsNullOrWhiteSpace(config.CacheDirectory)
|
|
? appPaths.DefaultUserViewsPath
|
|
: config.CacheDirectory;
|
|
var localRoot = Path.Combine(baseCache, "WebDAV");
|
|
if (!Directory.Exists(localRoot))
|
|
{
|
|
Directory.CreateDirectory(localRoot);
|
|
}
|
|
|
|
await SyncDirectoryAsync(config.RootPath.Trim('/'), localRoot, cancellationToken)
|
|
.ConfigureAwait(false);
|
|
|
|
var options = new LibraryOptions();
|
|
await libraryManager
|
|
.AddVirtualFolder("WebDAV", null, options, true)
|
|
.ConfigureAwait(false);
|
|
libraryManager.AddMediaPath("WebDAV", new MediaPathInfo { Path = localRoot });
|
|
}
|
|
|
|
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;
|
|
}
|
|
} |