Skip to content

Commit 5be3c7e

Browse files
committed
Added static README file to webdav root.
1 parent 1f20a2a commit 5be3c7e

File tree

8 files changed

+93
-9
lines changed

8 files changed

+93
-9
lines changed

backend/Api/Controllers/GetWebdavItem/GetWebdavItemController.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,7 @@ public async Task HandleRequest()
7676

7777
private static string GetContentType(string item)
7878
{
79+
if (item == "README") return "text/plain";
7980
var extension = Path.GetExtension(item).ToLower();
8081
return extension == ".mkv" ? "video/webm"
8182
: extension == ".rclonelink" ? "text/plain"

backend/NzbWebDAV.csproj

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424

2525
<ItemGroup>
2626
<EmbeddedResource Include="Api\SabControllers\GetConfig\config_template.json" />
27+
<EmbeddedResource Include="WebDav\StaticFiles\root\README.md" />
2728
</ItemGroup>
2829

2930
</Project>

backend/Utils/EmbeddedResourceUtil.cs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,12 @@ public static string ReadAllText(string resourcePath)
1919
return reader.ReadToEnd();
2020
}
2121

22+
public static long GetLength(string resourcePath)
23+
{
24+
using var stream = GetStream(resourcePath);
25+
return stream.Length;
26+
}
27+
2228
public static async Task<string> ReadAllTextAsync(string resourcePath)
2329
{
2430
await using var stream = GetStream(resourcePath);

backend/WebDav/DatabaseStoreCollection.cs

Lines changed: 19 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -26,19 +26,32 @@ WebsocketManager websocketManager
2626
public override string Name => davDirectory.Name;
2727
public override string UniqueKey => davDirectory.Id.ToString();
2828
public override DateTime CreatedAt => davDirectory.CreatedAt;
29+
private static readonly StaticEmbeddedFile Readme = new("StaticFiles.root.README.md", "README");
2930

3031
protected override async Task<IStoreItem?> GetItemAsync(GetItemRequest request)
3132
{
32-
var child = await dbClient.GetDirectoryChildAsync(davDirectory.Id, request.Name, request.CancellationToken).ConfigureAwait(false);
33+
if (davDirectory.Id == DavItem.Root.Id && request.Name == Readme.Name) return Readme;
34+
var child = await dbClient.GetDirectoryChildAsync(davDirectory.Id, request.Name, request.CancellationToken)
35+
.ConfigureAwait(false);
3336
if (child is null) return null;
3437
return GetItem(child);
3538
}
3639

3740
protected override async Task<IStoreItem[]> GetAllItemsAsync(CancellationToken cancellationToken)
3841
{
39-
return (await dbClient.GetDirectoryChildrenAsync(davDirectory.Id, cancellationToken).ConfigureAwait(false))
40-
.Select(GetItem)
41-
.ToArray();
42+
// read DavItems from the database
43+
var children = await dbClient
44+
.GetDirectoryChildrenAsync(davDirectory.Id, cancellationToken)
45+
.ConfigureAwait(false);
46+
47+
// map DavItems to IStoreItems
48+
var result = children.Select(GetItem);
49+
50+
// include the readme file
51+
if (davDirectory.Id == DavItem.Root.Id)
52+
result = result.Append(Readme);
53+
54+
return result.ToArray();
4255
}
4356

4457
protected override bool SupportsFastMove(SupportsFastMoveRequest request)
@@ -57,7 +70,8 @@ protected override async Task<DavStatusCode> DeleteItemAsync(DeleteItemRequest r
5770
return DavStatusCode.Forbidden;
5871

5972
// Get the item being deleted
60-
var davItem = await dbClient.GetDirectoryChildAsync(davDirectory.Id, request.Name, request.CancellationToken).ConfigureAwait(false);
73+
var davItem = await dbClient.GetDirectoryChildAsync(davDirectory.Id, request.Name, request.CancellationToken)
74+
.ConfigureAwait(false);
6175
if (davItem is null) return DavStatusCode.NotFound;
6276

6377
// If the item is a file, simply delete it and we're done.

backend/WebDav/DatabaseStoreSymlinkCollection.cs

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,8 @@ ConfigManager configManager
2727
{
2828
if (DeletedFiles.IsDeleted(request.Name)) return null;
2929
var name = Regex.Replace(request.Name, @"\.rclonelink$", "");
30-
var child = await dbClient.GetDirectoryChildAsync(TargetId, name, request.CancellationToken).ConfigureAwait(false);
30+
var child = await dbClient.GetDirectoryChildAsync(TargetId, name, request.CancellationToken)
31+
.ConfigureAwait(false);
3132
if (child is null) return null;
3233
return GetItem(child);
3334
}
@@ -38,9 +39,11 @@ protected override async Task<IStoreItem[]> GetAllItemsAsync(CancellationToken c
3839
// then we only want to show children that correspond to Completed History items.
3940
var isCategoryFolder = davDirectory.ParentId == DavItem.ContentFolder.Id;
4041
var children = isCategoryFolder
41-
? await dbClient.GetCompletedSymlinkCategoryChildren(davDirectory.Name, cancellationToken).ConfigureAwait(false)
42+
? await dbClient.GetCompletedSymlinkCategoryChildren(davDirectory.Name, cancellationToken)
43+
.ConfigureAwait(false)
4244
: await dbClient.GetDirectoryChildrenAsync(TargetId, cancellationToken).ConfigureAwait(false);
4345

46+
// map DavItems to IStoreItems
4447
return children
4548
.Select(GetItem)
4649
.Where(x => !DeletedFiles.IsDeleted(x.Name)) // must appear after Select(GetItem) for correct Name.
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
using NzbWebDAV.Utils;
2+
using NzbWebDAV.WebDav.Base;
3+
4+
namespace NzbWebDAV.WebDav;
5+
6+
public class StaticEmbeddedFile(string resourcePath, string name) : BaseStoreReadonlyItem
7+
{
8+
public override string Name => name;
9+
public override string UniqueKey => resourcePath;
10+
public override long FileSize { get; } = EmbeddedResourceUtil.GetLength(resourcePath);
11+
public override DateTime CreatedAt { get; } = DateTime.Now;
12+
13+
public override Task<Stream> GetReadableStreamAsync(CancellationToken cancellationToken)
14+
{
15+
return Task.FromResult(EmbeddedResourceUtil.GetStream(resourcePath));
16+
}
17+
}
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
# About `/content`
2+
3+
This directory contains all streamable files that have finished processing from the nzbdav queue.
4+
5+
It is mostly read-only. Files cannot be created, renamed, or moved within this directory.
6+
7+
However, files can be deleted from this directory if you no longer want them, using any compatible webdav client (or using Rclone). But only when the setting under `Settings -> WebDAV -> Enforce Read-Only` is disabled. Deleting items from this directory may break symlinks that point to those items, so be certain you no longer need them before doing so.
8+
9+
> Note: You can run the maintenance task under `Settings -> Maintenance -> Remove Orphaned Files` to remove all files from the `/content` folder that are no longer symlinked by your media library.
10+
11+
---
12+
13+
# About `/completed-symlinks`
14+
15+
This directory contains symlinks for items that have finished processing the nzbdav queue and are still present in the nzbdav history table.
16+
17+
It is read-only. Files cannot be created, renamed, moved, or deleted from this directory. Files in this directory can only be read and copied out of the webdav.
18+
19+
All items under this directory have the *.rclonelink extension, since true symlinks cannot exist on a webdav. Instead, the *.rclonelink files are simple text files whose contents contain the target path of where the symlink should point to.
20+
21+
If using Rclone to mount the webdav onto your filesystem, then Rclone will take care of translating these *.rclonelink files to actual symlinks. You'll need to use the `--links` argument for Rclone to perform this translation.
22+
23+
> NOTE: Be sure to use an updated version of rclone that supports the `--links` argument.
24+
> * Version `v1.70.3` has been known to support it.
25+
> * Version `v1.60.1-DEV` has been known _not_ to support it.
26+
27+
---
28+
29+
# About `/nzbs`
30+
31+
This directory mirrors the nzbdav queue
32+
* Any nzb currently in the queue can be retrieved from this directory.
33+
* You can remove items from the queue by deleting the corresponding nzb from this directory
34+
* You can add items to the queue by uploading nzb files to this directory
35+
36+
> Note: You must perform file operations using any compatible webdav client (or Rclone). The "Dav Explore" page on nzbdav UI does not currently support file operations.

frontend/app/routes/explore/route.tsx

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ export async function loader({ request }: Route.LoaderArgs) {
3333
return {
3434
...x,
3535
mimeType: getMimeType(x.name),
36-
downloadKey: getDownloadKey(`${path}/${x.name}`)
36+
downloadKey: getDownloadKey(getRelativePath(path, x.name))
3737
};
3838
})
3939
}
@@ -61,7 +61,8 @@ function Body(props: ExplorePageData) {
6161

6262
const getFilePath = useCallback((file: ExploreFile) => {
6363
var pathname = getWebdavPath(location.pathname);
64-
return `/view/${pathname}/${encodeURIComponent(file.name)}?downloadKey=${file.downloadKey}`;
64+
var relativePath = getRelativePath(pathname, encodeURIComponent(file.name));
65+
return `/view/${relativePath}?downloadKey=${file.downloadKey}`;
6566
}, [location.pathname]);
6667

6768
return (
@@ -109,6 +110,11 @@ function getWebdavPathDecoded(pathname: string): string {
109110
return decodeURIComponent(getWebdavPath(pathname));
110111
}
111112

113+
function getRelativePath(path: string, filename: string) {
114+
if (path === "") return filename;
115+
return `${path}/${filename}`;
116+
}
117+
112118
function getParentDirectories(webdavPath: string): string[] {
113119
return webdavPath == "" ? [] : webdavPath.split('/');
114120
}

0 commit comments

Comments
 (0)