Fix custom filename formats for paid messages and posts, and fix creator config empty strings
This commit is contained in:
parent
aee920a9f1
commit
03dd66a842
@ -115,22 +115,22 @@ public class Config : IFileNameFormatConfig
|
|||||||
|
|
||||||
if (CreatorConfigs.TryGetValue(username, out CreatorConfig? creatorConfig))
|
if (CreatorConfigs.TryGetValue(username, out CreatorConfig? creatorConfig))
|
||||||
{
|
{
|
||||||
if (creatorConfig.PaidPostFileNameFormat != null)
|
if (!string.IsNullOrEmpty(creatorConfig.PaidPostFileNameFormat))
|
||||||
{
|
{
|
||||||
combinedFilenameFormatConfig.PaidPostFileNameFormat = creatorConfig.PaidPostFileNameFormat;
|
combinedFilenameFormatConfig.PaidPostFileNameFormat = creatorConfig.PaidPostFileNameFormat;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (creatorConfig.PostFileNameFormat != null)
|
if (!string.IsNullOrEmpty(creatorConfig.PostFileNameFormat))
|
||||||
{
|
{
|
||||||
combinedFilenameFormatConfig.PostFileNameFormat = creatorConfig.PostFileNameFormat;
|
combinedFilenameFormatConfig.PostFileNameFormat = creatorConfig.PostFileNameFormat;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (creatorConfig.PaidMessageFileNameFormat != null)
|
if (!string.IsNullOrEmpty(creatorConfig.PaidMessageFileNameFormat))
|
||||||
{
|
{
|
||||||
combinedFilenameFormatConfig.PaidMessageFileNameFormat = creatorConfig.PaidMessageFileNameFormat;
|
combinedFilenameFormatConfig.PaidMessageFileNameFormat = creatorConfig.PaidMessageFileNameFormat;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (creatorConfig.MessageFileNameFormat != null)
|
if (!string.IsNullOrEmpty(creatorConfig.MessageFileNameFormat))
|
||||||
{
|
{
|
||||||
combinedFilenameFormatConfig.MessageFileNameFormat = creatorConfig.MessageFileNameFormat;
|
combinedFilenameFormatConfig.MessageFileNameFormat = creatorConfig.MessageFileNameFormat;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1363,11 +1363,12 @@ public class DownloadService(
|
|||||||
PurchasedEntities.ListItem? messageInfo = paidMessageCollection.PaidMessageObjects.FirstOrDefault(p =>
|
PurchasedEntities.ListItem? messageInfo = paidMessageCollection.PaidMessageObjects.FirstOrDefault(p =>
|
||||||
p.Media?.Any(m => m.Id == kvpEntry.Key) == true);
|
p.Media?.Any(m => m.Id == kvpEntry.Key) == true);
|
||||||
string filenameFormat =
|
string filenameFormat =
|
||||||
configService.CurrentConfig.GetCreatorFileNameFormatConfig(username).MessageFileNameFormat ?? "";
|
configService.CurrentConfig.GetCreatorFileNameFormatConfig(username).PaidMessageFileNameFormat ?? "";
|
||||||
string paidMsgPath = configService.CurrentConfig.FolderPerPaidMessage && messageInfo != null &&
|
string paidMsgPath = configService.CurrentConfig.FolderPerPaidMessage && messageInfo != null &&
|
||||||
messageInfo.Id != 0 && messageInfo.CreatedAt is not null
|
messageInfo.Id != 0 && messageInfo.CreatedAt is not null
|
||||||
? $"/Messages/Paid/{messageInfo.Id} {messageInfo.CreatedAt.Value:yyyy-MM-dd HH-mm-ss}"
|
? $"/Messages/Paid/{messageInfo.Id} {messageInfo.CreatedAt.Value:yyyy-MM-dd HH-mm-ss}"
|
||||||
: "/Messages/Paid";
|
: "/Messages/Paid";
|
||||||
|
object? messageAuthor = messageInfo?.FromUser ?? (object?)messageInfo?.Author;
|
||||||
|
|
||||||
if (kvpEntry.Value.Contains("cdn3.onlyfans.com/dash/files"))
|
if (kvpEntry.Value.Contains("cdn3.onlyfans.com/dash/files"))
|
||||||
{
|
{
|
||||||
@ -1383,12 +1384,12 @@ public class DownloadService(
|
|||||||
isNew = await DownloadDrmVideo(parsed[1], parsed[2], parsed[3], parsed[0],
|
isNew = await DownloadDrmVideo(parsed[1], parsed[2], parsed[3], parsed[0],
|
||||||
drmInfo.Value.decryptionKey, path, drmInfo.Value.lastModified, kvpEntry.Key, "Messages",
|
drmInfo.Value.decryptionKey, path, drmInfo.Value.lastModified, kvpEntry.Key, "Messages",
|
||||||
progressReporter, paidMsgPath + "/Videos", filenameFormat,
|
progressReporter, paidMsgPath + "/Videos", filenameFormat,
|
||||||
messageInfo, mediaInfo, messageInfo?.FromUser, users);
|
messageInfo, mediaInfo, messageAuthor, users);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
isNew = await DownloadMedia(kvpEntry.Value, path, kvpEntry.Key, "Messages", progressReporter,
|
isNew = await DownloadMedia(kvpEntry.Value, path, kvpEntry.Key, "Messages", progressReporter,
|
||||||
paidMsgPath, filenameFormat, messageInfo, mediaInfo, messageInfo?.FromUser, users);
|
paidMsgPath, filenameFormat, messageInfo, mediaInfo, messageAuthor, users);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isNew)
|
if (isNew)
|
||||||
@ -1640,11 +1641,12 @@ public class DownloadService(
|
|||||||
PurchasedEntities.ListItem? postInfo =
|
PurchasedEntities.ListItem? postInfo =
|
||||||
purchasedPosts.PaidPostObjects.FirstOrDefault(p => p.Media?.Any(m => m.Id == postKvp.Key) == true);
|
purchasedPosts.PaidPostObjects.FirstOrDefault(p => p.Media?.Any(m => m.Id == postKvp.Key) == true);
|
||||||
string filenameFormat =
|
string filenameFormat =
|
||||||
configService.CurrentConfig.GetCreatorFileNameFormatConfig(username).PostFileNameFormat ?? "";
|
configService.CurrentConfig.GetCreatorFileNameFormatConfig(username).PaidPostFileNameFormat ?? "";
|
||||||
string paidPostPath = configService.CurrentConfig.FolderPerPaidPost && postInfo != null &&
|
string paidPostPath = configService.CurrentConfig.FolderPerPaidPost && postInfo != null &&
|
||||||
postInfo.Id != 0 && postInfo.PostedAt is not null
|
postInfo.Id != 0 && postInfo.PostedAt is not null
|
||||||
? $"/Posts/Paid/{postInfo.Id} {postInfo.PostedAt.Value:yyyy-MM-dd HH-mm-ss}"
|
? $"/Posts/Paid/{postInfo.Id} {postInfo.PostedAt.Value:yyyy-MM-dd HH-mm-ss}"
|
||||||
: "/Posts/Paid";
|
: "/Posts/Paid";
|
||||||
|
object? postAuthor = postInfo?.FromUser ?? (object?)postInfo?.Author;
|
||||||
|
|
||||||
if (postKvp.Value.Contains("cdn3.onlyfans.com/dash/files"))
|
if (postKvp.Value.Contains("cdn3.onlyfans.com/dash/files"))
|
||||||
{
|
{
|
||||||
@ -1660,12 +1662,12 @@ public class DownloadService(
|
|||||||
isNew = await DownloadDrmVideo(parsed[1], parsed[2], parsed[3], parsed[0],
|
isNew = await DownloadDrmVideo(parsed[1], parsed[2], parsed[3], parsed[0],
|
||||||
drmInfo.Value.decryptionKey, path, drmInfo.Value.lastModified, postKvp.Key, "Posts",
|
drmInfo.Value.decryptionKey, path, drmInfo.Value.lastModified, postKvp.Key, "Posts",
|
||||||
progressReporter, paidPostPath + "/Videos", filenameFormat,
|
progressReporter, paidPostPath + "/Videos", filenameFormat,
|
||||||
postInfo, mediaInfo, postInfo?.FromUser, users);
|
postInfo, mediaInfo, postAuthor, users);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
isNew = await DownloadMedia(postKvp.Value, path, postKvp.Key, "Posts", progressReporter,
|
isNew = await DownloadMedia(postKvp.Value, path, postKvp.Key, "Posts", progressReporter,
|
||||||
paidPostPath, filenameFormat, postInfo, mediaInfo, postInfo?.FromUser, users);
|
paidPostPath, filenameFormat, postInfo, mediaInfo, postAuthor, users);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isNew)
|
if (isNew)
|
||||||
@ -1729,6 +1731,7 @@ public class DownloadService(
|
|||||||
postInfo.Id != 0 && postInfo.PostedAt is not null
|
postInfo.Id != 0 && postInfo.PostedAt is not null
|
||||||
? $"/Posts/Paid/{postInfo.Id} {postInfo.PostedAt.Value:yyyy-MM-dd HH-mm-ss}"
|
? $"/Posts/Paid/{postInfo.Id} {postInfo.PostedAt.Value:yyyy-MM-dd HH-mm-ss}"
|
||||||
: "/Posts/Paid";
|
: "/Posts/Paid";
|
||||||
|
object? postAuthor = postInfo?.FromUser ?? (object?)postInfo?.Author;
|
||||||
|
|
||||||
if (purchasedPostKvp.Value.Contains("cdn3.onlyfans.com/dash/files"))
|
if (purchasedPostKvp.Value.Contains("cdn3.onlyfans.com/dash/files"))
|
||||||
{
|
{
|
||||||
@ -1744,13 +1747,13 @@ public class DownloadService(
|
|||||||
isNew = await DownloadDrmVideo(parsed[1], parsed[2], parsed[3], parsed[0],
|
isNew = await DownloadDrmVideo(parsed[1], parsed[2], parsed[3], parsed[0],
|
||||||
drmInfo.Value.decryptionKey, path, drmInfo.Value.lastModified, purchasedPostKvp.Key,
|
drmInfo.Value.decryptionKey, path, drmInfo.Value.lastModified, purchasedPostKvp.Key,
|
||||||
"Posts", progressReporter, paidPostPath + "/Videos", filenameFormat,
|
"Posts", progressReporter, paidPostPath + "/Videos", filenameFormat,
|
||||||
postInfo, mediaInfo, postInfo?.FromUser, users);
|
postInfo, mediaInfo, postAuthor, users);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
isNew = await DownloadMedia(purchasedPostKvp.Value, path,
|
isNew = await DownloadMedia(purchasedPostKvp.Value, path,
|
||||||
purchasedPostKvp.Key, "Posts", progressReporter,
|
purchasedPostKvp.Key, "Posts", progressReporter,
|
||||||
paidPostPath, filenameFormat, postInfo, mediaInfo, postInfo?.FromUser, users);
|
paidPostPath, filenameFormat, postInfo, mediaInfo, postAuthor, users);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isNew)
|
if (isNew)
|
||||||
@ -1813,6 +1816,7 @@ public class DownloadService(
|
|||||||
messageInfo.Id != 0 && messageInfo.CreatedAt is not null
|
messageInfo.Id != 0 && messageInfo.CreatedAt is not null
|
||||||
? $"/Messages/Paid/{messageInfo.Id} {messageInfo.CreatedAt.Value:yyyy-MM-dd HH-mm-ss}"
|
? $"/Messages/Paid/{messageInfo.Id} {messageInfo.CreatedAt.Value:yyyy-MM-dd HH-mm-ss}"
|
||||||
: "/Messages/Paid";
|
: "/Messages/Paid";
|
||||||
|
object? messageAuthor = messageInfo?.FromUser ?? (object?)messageInfo?.Author;
|
||||||
|
|
||||||
if (paidMessageKvp.Value.Contains("cdn3.onlyfans.com/dash/files"))
|
if (paidMessageKvp.Value.Contains("cdn3.onlyfans.com/dash/files"))
|
||||||
{
|
{
|
||||||
@ -1828,13 +1832,13 @@ public class DownloadService(
|
|||||||
isNew = await DownloadDrmVideo(parsed[1], parsed[2], parsed[3], parsed[0],
|
isNew = await DownloadDrmVideo(parsed[1], parsed[2], parsed[3], parsed[0],
|
||||||
drmInfo.Value.decryptionKey, path, drmInfo.Value.lastModified, paidMessageKvp.Key,
|
drmInfo.Value.decryptionKey, path, drmInfo.Value.lastModified, paidMessageKvp.Key,
|
||||||
"Messages", progressReporter, paidMsgPath + "/Videos", filenameFormat,
|
"Messages", progressReporter, paidMsgPath + "/Videos", filenameFormat,
|
||||||
messageInfo, mediaInfo, messageInfo?.FromUser, users);
|
messageInfo, mediaInfo, messageAuthor, users);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
isNew = await DownloadMedia(paidMessageKvp.Value, path,
|
isNew = await DownloadMedia(paidMessageKvp.Value, path,
|
||||||
paidMessageKvp.Key, "Messages", progressReporter,
|
paidMessageKvp.Key, "Messages", progressReporter,
|
||||||
paidMsgPath, filenameFormat, messageInfo, mediaInfo, messageInfo?.FromUser, users);
|
paidMsgPath, filenameFormat, messageInfo, mediaInfo, messageAuthor, users);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isNew)
|
if (isNew)
|
||||||
|
|||||||
@ -200,8 +200,18 @@ public class FileNameService(IAuthService authService) : IFileNameService
|
|||||||
object? value = source;
|
object? value = source;
|
||||||
foreach (string propertyName in propertyPath.Split('.'))
|
foreach (string propertyName in propertyPath.Split('.'))
|
||||||
{
|
{
|
||||||
PropertyInfo property = value?.GetType().GetProperty(propertyName) ??
|
if (value == null)
|
||||||
throw new ArgumentException($"Property '{propertyName}' not found.");
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
PropertyInfo? property = value.GetType().GetProperty(propertyName,
|
||||||
|
BindingFlags.Public | BindingFlags.Instance | BindingFlags.IgnoreCase);
|
||||||
|
if (property == null)
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
value = property.GetValue(value);
|
value = property.GetValue(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
122
OF DL.Tests/Models/Config/ConfigTests.cs
Normal file
122
OF DL.Tests/Models/Config/ConfigTests.cs
Normal file
@ -0,0 +1,122 @@
|
|||||||
|
using OF_DL.Models.Config;
|
||||||
|
|
||||||
|
namespace OF_DL.Tests.Models.Config;
|
||||||
|
|
||||||
|
public class ConfigTests
|
||||||
|
{
|
||||||
|
[Fact]
|
||||||
|
public void GetCreatorFileNameFormatConfig_UsesCreatorFormatWhenDefined()
|
||||||
|
{
|
||||||
|
OF_DL.Models.Config.Config config = new()
|
||||||
|
{
|
||||||
|
PaidPostFileNameFormat = "global-paid-post",
|
||||||
|
PostFileNameFormat = "global-post",
|
||||||
|
PaidMessageFileNameFormat = "global-paid-message",
|
||||||
|
MessageFileNameFormat = "global-message",
|
||||||
|
CreatorConfigs = new Dictionary<string, CreatorConfig>
|
||||||
|
{
|
||||||
|
["creator"] = new()
|
||||||
|
{
|
||||||
|
PaidPostFileNameFormat = "creator-paid-post",
|
||||||
|
PostFileNameFormat = "creator-post",
|
||||||
|
PaidMessageFileNameFormat = "creator-paid-message",
|
||||||
|
MessageFileNameFormat = "creator-message"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
IFileNameFormatConfig result = config.GetCreatorFileNameFormatConfig("creator");
|
||||||
|
|
||||||
|
Assert.Equal("creator-paid-post", result.PaidPostFileNameFormat);
|
||||||
|
Assert.Equal("creator-post", result.PostFileNameFormat);
|
||||||
|
Assert.Equal("creator-paid-message", result.PaidMessageFileNameFormat);
|
||||||
|
Assert.Equal("creator-message", result.MessageFileNameFormat);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void GetCreatorFileNameFormatConfig_FallsBackToGlobalWhenCreatorFormatIsNullOrEmpty()
|
||||||
|
{
|
||||||
|
OF_DL.Models.Config.Config config = new()
|
||||||
|
{
|
||||||
|
PaidPostFileNameFormat = "global-paid-post",
|
||||||
|
PostFileNameFormat = "global-post",
|
||||||
|
PaidMessageFileNameFormat = "global-paid-message",
|
||||||
|
MessageFileNameFormat = "global-message",
|
||||||
|
CreatorConfigs = new Dictionary<string, CreatorConfig>
|
||||||
|
{
|
||||||
|
["creator"] = new()
|
||||||
|
{
|
||||||
|
PaidPostFileNameFormat = null,
|
||||||
|
PostFileNameFormat = "",
|
||||||
|
PaidMessageFileNameFormat = null,
|
||||||
|
MessageFileNameFormat = ""
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
IFileNameFormatConfig result = config.GetCreatorFileNameFormatConfig("creator");
|
||||||
|
|
||||||
|
Assert.Equal("global-paid-post", result.PaidPostFileNameFormat);
|
||||||
|
Assert.Equal("global-post", result.PostFileNameFormat);
|
||||||
|
Assert.Equal("global-paid-message", result.PaidMessageFileNameFormat);
|
||||||
|
Assert.Equal("global-message", result.MessageFileNameFormat);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void GetCreatorFileNameFormatConfig_UsesGlobalWhenCreatorConfigDoesNotExist()
|
||||||
|
{
|
||||||
|
OF_DL.Models.Config.Config config = new()
|
||||||
|
{
|
||||||
|
PaidPostFileNameFormat = "global-paid-post",
|
||||||
|
PostFileNameFormat = "global-post",
|
||||||
|
PaidMessageFileNameFormat = "global-paid-message",
|
||||||
|
MessageFileNameFormat = "global-message",
|
||||||
|
CreatorConfigs = new Dictionary<string, CreatorConfig>
|
||||||
|
{
|
||||||
|
["other-creator"] = new()
|
||||||
|
{
|
||||||
|
PaidPostFileNameFormat = "other-paid-post",
|
||||||
|
PostFileNameFormat = "other-post",
|
||||||
|
PaidMessageFileNameFormat = "other-paid-message",
|
||||||
|
MessageFileNameFormat = "other-message"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
IFileNameFormatConfig result = config.GetCreatorFileNameFormatConfig("creator");
|
||||||
|
|
||||||
|
Assert.Equal("global-paid-post", result.PaidPostFileNameFormat);
|
||||||
|
Assert.Equal("global-post", result.PostFileNameFormat);
|
||||||
|
Assert.Equal("global-paid-message", result.PaidMessageFileNameFormat);
|
||||||
|
Assert.Equal("global-message", result.MessageFileNameFormat);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void GetCreatorFileNameFormatConfig_ReturnsEmptyFormatsWhenCreatorAndGlobalAreUndefined()
|
||||||
|
{
|
||||||
|
OF_DL.Models.Config.Config config = new()
|
||||||
|
{
|
||||||
|
PaidPostFileNameFormat = "",
|
||||||
|
PostFileNameFormat = "",
|
||||||
|
PaidMessageFileNameFormat = "",
|
||||||
|
MessageFileNameFormat = "",
|
||||||
|
CreatorConfigs = new Dictionary<string, CreatorConfig>
|
||||||
|
{
|
||||||
|
["creator"] = new()
|
||||||
|
{
|
||||||
|
PaidPostFileNameFormat = "",
|
||||||
|
PostFileNameFormat = null,
|
||||||
|
PaidMessageFileNameFormat = "",
|
||||||
|
MessageFileNameFormat = null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
IFileNameFormatConfig result = config.GetCreatorFileNameFormatConfig("creator");
|
||||||
|
|
||||||
|
Assert.True(string.IsNullOrEmpty(result.PaidPostFileNameFormat));
|
||||||
|
Assert.True(string.IsNullOrEmpty(result.PostFileNameFormat));
|
||||||
|
Assert.True(string.IsNullOrEmpty(result.PaidMessageFileNameFormat));
|
||||||
|
Assert.True(string.IsNullOrEmpty(result.MessageFileNameFormat));
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -1,5 +1,9 @@
|
|||||||
using OF_DL.Models.Config;
|
using OF_DL.Models.Config;
|
||||||
using OF_DL.Models.Downloads;
|
using OF_DL.Models.Downloads;
|
||||||
|
using OF_DL.Models;
|
||||||
|
using PostEntities = OF_DL.Models.Entities.Posts;
|
||||||
|
using PurchasedEntities = OF_DL.Models.Entities.Purchased;
|
||||||
|
using MessageEntities = OF_DL.Models.Entities.Messages;
|
||||||
using OF_DL.Services;
|
using OF_DL.Services;
|
||||||
|
|
||||||
namespace OF_DL.Tests.Services;
|
namespace OF_DL.Tests.Services;
|
||||||
@ -150,11 +154,218 @@ public class DownloadServiceTests
|
|||||||
Assert.Equal(2, progress.Total);
|
Assert.Equal(2, progress.Total);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static DownloadService CreateService(FakeConfigService configService, MediaTrackingDbService dbService,
|
[Fact]
|
||||||
StaticApiService? apiService = null) =>
|
public async Task DownloadFreePosts_UsesDefaultFilenameWhenNoGlobalOrCreatorFormatIsDefined()
|
||||||
new(new FakeAuthService(), configService, dbService, new FakeFileNameService(),
|
{
|
||||||
apiService ?? new StaticApiService());
|
using TempFolder temp = new();
|
||||||
|
string folder = NormalizeFolder(Path.Combine(temp.Path, "creator"));
|
||||||
|
const string serverFilename = "server-name";
|
||||||
|
string existingFilePath = $"{folder}/Posts/Free/Images/{serverFilename}.jpg";
|
||||||
|
Directory.CreateDirectory(Path.GetDirectoryName(existingFilePath) ?? throw new InvalidOperationException());
|
||||||
|
await File.WriteAllTextAsync(existingFilePath, "abc");
|
||||||
|
|
||||||
private static string NormalizeFolder(string folder) => folder.Replace("\\", "/");
|
Config config = new()
|
||||||
|
{
|
||||||
|
ShowScrapeSize = false,
|
||||||
|
PostFileNameFormat = "",
|
||||||
|
CreatorConfigs = new Dictionary<string, CreatorConfig>
|
||||||
|
{
|
||||||
|
["creator"] = new() { PostFileNameFormat = "" }
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
MediaTrackingDbService dbService = new() { CheckDownloadedResult = false };
|
||||||
|
DownloadService service = CreateService(new FakeConfigService(config), dbService);
|
||||||
|
ProgressRecorder progress = new();
|
||||||
|
PostEntities.PostCollection posts = new()
|
||||||
|
{
|
||||||
|
Posts = new Dictionary<long, string> { { 1, $"https://example.com/{serverFilename}.jpg" } }
|
||||||
|
};
|
||||||
|
|
||||||
|
DownloadResult result = await service.DownloadFreePosts("creator", 1, folder, new Dictionary<string, long>(),
|
||||||
|
false, false, posts, progress);
|
||||||
|
|
||||||
|
Assert.Equal(1, result.TotalCount);
|
||||||
|
Assert.Equal(0, result.NewDownloads);
|
||||||
|
Assert.Equal(1, result.ExistingDownloads);
|
||||||
|
Assert.NotNull(dbService.LastUpdateMedia);
|
||||||
|
Assert.Equal($"{serverFilename}.jpg", dbService.LastUpdateMedia.Value.filename);
|
||||||
|
Assert.Equal(1, progress.Total);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public async Task DownloadFreePosts_UsesGlobalCustomFormatWhenCreatorCustomFormatNotDefined()
|
||||||
|
{
|
||||||
|
using TempFolder temp = new();
|
||||||
|
string folder = NormalizeFolder(Path.Combine(temp.Path, "creator"));
|
||||||
|
const string serverFilename = "server-name";
|
||||||
|
string existingFilePath = $"{folder}/Posts/Free/Images/{serverFilename}.jpg";
|
||||||
|
Directory.CreateDirectory(Path.GetDirectoryName(existingFilePath) ?? throw new InvalidOperationException());
|
||||||
|
await File.WriteAllTextAsync(existingFilePath, "abc");
|
||||||
|
|
||||||
|
Config config = new()
|
||||||
|
{
|
||||||
|
ShowScrapeSize = false,
|
||||||
|
PostFileNameFormat = "global-custom-name",
|
||||||
|
CreatorConfigs = new Dictionary<string, CreatorConfig>
|
||||||
|
{
|
||||||
|
["creator"] = new() { PostFileNameFormat = "" }
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
MediaTrackingDbService dbService = new() { CheckDownloadedResult = false };
|
||||||
|
DownloadService service = CreateService(new FakeConfigService(config), dbService,
|
||||||
|
fileNameService: new DeterministicFileNameService());
|
||||||
|
ProgressRecorder progress = new();
|
||||||
|
PostEntities.PostCollection posts = CreatePostCollection(1, serverFilename);
|
||||||
|
|
||||||
|
DownloadResult result = await service.DownloadFreePosts("creator", 1, folder, new Dictionary<string, long>(),
|
||||||
|
false, false, posts, progress);
|
||||||
|
|
||||||
|
string renamedPath = $"{folder}/Posts/Free/Images/global-custom-name.jpg";
|
||||||
|
Assert.Equal(1, result.TotalCount);
|
||||||
|
Assert.Equal(0, result.NewDownloads);
|
||||||
|
Assert.Equal(1, result.ExistingDownloads);
|
||||||
|
Assert.False(File.Exists(existingFilePath));
|
||||||
|
Assert.True(File.Exists(renamedPath));
|
||||||
|
Assert.NotNull(dbService.LastUpdateMedia);
|
||||||
|
Assert.Equal("global-custom-name.jpg", dbService.LastUpdateMedia.Value.filename);
|
||||||
|
Assert.Equal(1, progress.Total);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public async Task DownloadFreePosts_UsesCreatorCustomFormatWhenGlobalAndCreatorFormatsAreDefined()
|
||||||
|
{
|
||||||
|
using TempFolder temp = new();
|
||||||
|
string folder = NormalizeFolder(Path.Combine(temp.Path, "creator"));
|
||||||
|
const string serverFilename = "server-name";
|
||||||
|
string existingFilePath = $"{folder}/Posts/Free/Images/{serverFilename}.jpg";
|
||||||
|
Directory.CreateDirectory(Path.GetDirectoryName(existingFilePath) ?? throw new InvalidOperationException());
|
||||||
|
await File.WriteAllTextAsync(existingFilePath, "abc");
|
||||||
|
|
||||||
|
Config config = new()
|
||||||
|
{
|
||||||
|
ShowScrapeSize = false,
|
||||||
|
PostFileNameFormat = "global-custom-name",
|
||||||
|
CreatorConfigs = new Dictionary<string, CreatorConfig>
|
||||||
|
{
|
||||||
|
["creator"] = new() { PostFileNameFormat = "creator-custom-name" }
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
MediaTrackingDbService dbService = new() { CheckDownloadedResult = false };
|
||||||
|
DownloadService service = CreateService(new FakeConfigService(config), dbService,
|
||||||
|
fileNameService: new DeterministicFileNameService());
|
||||||
|
ProgressRecorder progress = new();
|
||||||
|
PostEntities.PostCollection posts = CreatePostCollection(1, serverFilename);
|
||||||
|
|
||||||
|
DownloadResult result = await service.DownloadFreePosts("creator", 1, folder, new Dictionary<string, long>(),
|
||||||
|
false, false, posts, progress);
|
||||||
|
|
||||||
|
string renamedPath = $"{folder}/Posts/Free/Images/creator-custom-name.jpg";
|
||||||
|
Assert.Equal(1, result.TotalCount);
|
||||||
|
Assert.Equal(0, result.NewDownloads);
|
||||||
|
Assert.Equal(1, result.ExistingDownloads);
|
||||||
|
Assert.False(File.Exists(existingFilePath));
|
||||||
|
Assert.True(File.Exists(renamedPath));
|
||||||
|
Assert.NotNull(dbService.LastUpdateMedia);
|
||||||
|
Assert.Equal("creator-custom-name.jpg", dbService.LastUpdateMedia.Value.filename);
|
||||||
|
Assert.Equal(1, progress.Total);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public async Task DownloadPaidPosts_AppliesPaidCustomFormatForDrm_WhenAuthorExistsButFromUserMissing()
|
||||||
|
{
|
||||||
|
using TempFolder temp = new();
|
||||||
|
string folder = NormalizeFolder(Path.Combine(temp.Path, "creator"));
|
||||||
|
const string customName = "paid-custom-name";
|
||||||
|
const string drmBaseFilename = "video-file";
|
||||||
|
string basePath = $"{folder}/Posts/Paid/Videos";
|
||||||
|
Directory.CreateDirectory(basePath);
|
||||||
|
await File.WriteAllTextAsync($"{basePath}/{customName}.mp4", "custom");
|
||||||
|
await File.WriteAllTextAsync($"{basePath}/{drmBaseFilename}_source.mp4", "server");
|
||||||
|
|
||||||
|
Config config = new() { ShowScrapeSize = false, PaidPostFileNameFormat = customName, PostFileNameFormat = "" };
|
||||||
|
|
||||||
|
MediaTrackingDbService dbService = new() { CheckDownloadedResult = false };
|
||||||
|
StaticApiService apiService = new();
|
||||||
|
FakeAuthService authService = new()
|
||||||
|
{
|
||||||
|
CurrentAuth = new Auth { Cookie = "sess=test;", UserAgent = "unit-test-agent" }
|
||||||
|
};
|
||||||
|
|
||||||
|
DownloadService service = CreateService(new FakeConfigService(config), dbService,
|
||||||
|
apiService, new DeterministicFileNameService(), authService);
|
||||||
|
ProgressRecorder progress = new();
|
||||||
|
PurchasedEntities.PaidPostCollection posts = CreatePaidPostCollectionForDrm(1,
|
||||||
|
$"https://cdn3.onlyfans.com/dash/files/{drmBaseFilename}.mpd,policy,signature,kvp,1,2");
|
||||||
|
|
||||||
|
DownloadResult result = await service.DownloadPaidPosts("creator", 1, folder, new Dictionary<string, long>(),
|
||||||
|
false, false, posts, progress);
|
||||||
|
|
||||||
|
Assert.Equal(1, result.TotalCount);
|
||||||
|
Assert.Equal(0, result.NewDownloads);
|
||||||
|
Assert.Equal(1, result.ExistingDownloads);
|
||||||
|
Assert.NotNull(dbService.LastUpdateMedia);
|
||||||
|
Assert.Equal($"{customName}.mp4", dbService.LastUpdateMedia.Value.filename);
|
||||||
|
Assert.Equal(1, progress.Total);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static DownloadService CreateService(FakeConfigService configService, MediaTrackingDbService dbService,
|
||||||
|
StaticApiService? apiService = null, IFileNameService? fileNameService = null,
|
||||||
|
IAuthService? authService = null) =>
|
||||||
|
new(authService ?? new FakeAuthService(), configService, dbService,
|
||||||
|
fileNameService ?? new FakeFileNameService(),
|
||||||
|
apiService ?? new StaticApiService());
|
||||||
|
|
||||||
|
private static PostEntities.PostCollection CreatePostCollection(long mediaId, string serverFilename)
|
||||||
|
{
|
||||||
|
PostEntities.Medium media = new() { Id = mediaId };
|
||||||
|
PostEntities.ListItem post = new()
|
||||||
|
{
|
||||||
|
Id = 10,
|
||||||
|
PostedAt = new DateTime(2024, 1, 1),
|
||||||
|
Author = new OF_DL.Models.Entities.Common.Author { Id = 99 },
|
||||||
|
Media = [media]
|
||||||
|
};
|
||||||
|
|
||||||
|
return new PostEntities.PostCollection
|
||||||
|
{
|
||||||
|
Posts = new Dictionary<long, string> { { mediaId, $"https://example.com/{serverFilename}.jpg" } },
|
||||||
|
PostMedia = [media],
|
||||||
|
PostObjects = [post]
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
private static PurchasedEntities.PaidPostCollection CreatePaidPostCollectionForDrm(long mediaId, string drmUrl)
|
||||||
|
{
|
||||||
|
MessageEntities.Medium media = new() { Id = mediaId };
|
||||||
|
PurchasedEntities.ListItem post = new()
|
||||||
|
{
|
||||||
|
Id = 20,
|
||||||
|
PostedAt = new DateTime(2024, 1, 1),
|
||||||
|
Author = new OF_DL.Models.Entities.Common.Author { Id = 99 },
|
||||||
|
FromUser = null,
|
||||||
|
Media = [media]
|
||||||
|
};
|
||||||
|
|
||||||
|
return new PurchasedEntities.PaidPostCollection
|
||||||
|
{
|
||||||
|
PaidPosts = new Dictionary<long, string> { { mediaId, drmUrl } },
|
||||||
|
PaidPostMedia = [media],
|
||||||
|
PaidPostObjects = [post]
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
private static string NormalizeFolder(string folder) => folder.Replace("\\", "/");
|
||||||
|
|
||||||
|
private sealed class DeterministicFileNameService : IFileNameService
|
||||||
|
{
|
||||||
|
public Task<string> BuildFilename(string fileFormat, Dictionary<string, string> values) =>
|
||||||
|
Task.FromResult(fileFormat);
|
||||||
|
|
||||||
|
public Task<Dictionary<string, string>> GetFilename(object info, object media, object author,
|
||||||
|
List<string> selectedProperties, string username, Dictionary<string, long>? users = null) =>
|
||||||
|
Task.FromResult(new Dictionary<string, string>());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@ -20,7 +20,7 @@ internal sealed class TestMedia
|
|||||||
|
|
||||||
internal sealed class TestMediaFiles
|
internal sealed class TestMediaFiles
|
||||||
{
|
{
|
||||||
public TestMediaFull Full { get; set; } = new();
|
public TestMediaFull? Full { get; set; } = new();
|
||||||
public object? Drm { get; set; }
|
public object? Drm { get; set; }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -76,4 +76,24 @@ public class FileNameServiceTests
|
|||||||
|
|
||||||
Assert.Equal("creator_99", result);
|
Assert.Equal("creator_99", result);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public async Task GetFilename_UsesDrmFilenameWhenFullUrlMissing()
|
||||||
|
{
|
||||||
|
TestMedia media = new()
|
||||||
|
{
|
||||||
|
Id = 99,
|
||||||
|
Files = new TestMediaFiles
|
||||||
|
{
|
||||||
|
Full = null,
|
||||||
|
Drm = new { Manifest = new { Dash = "https://cdn.test/drm-name.mpd" } }
|
||||||
|
}
|
||||||
|
};
|
||||||
|
FileNameService service = new(new FakeAuthService());
|
||||||
|
|
||||||
|
Dictionary<string, string> values =
|
||||||
|
await service.GetFilename(new TestInfo(), media, new TestAuthor(), ["filename"], "creator");
|
||||||
|
|
||||||
|
Assert.Equal("drm-name_source", values["filename"]);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user