Major refactor #141
@ -37,8 +37,8 @@ using SinglePostCollection = OF_DL.Models.Entities.Posts.SinglePostCollection;
|
|||||||
|
|
||||||
namespace OF_DL.Services;
|
namespace OF_DL.Services;
|
||||||
|
|
||||||
public class ApiService(IAuthService authService, IConfigService configService, IDBService dbService)
|
public class ApiService(IAuthService authService, IConfigService configService, IDbService dbService)
|
||||||
: IAPIService
|
: IApiService
|
||||||
{
|
{
|
||||||
private const int MaxAttempts = 30;
|
private const int MaxAttempts = 30;
|
||||||
private const int DelayBetweenAttempts = 3000;
|
private const int DelayBetweenAttempts = 3000;
|
||||||
@ -200,9 +200,9 @@ public class ApiService(IAuthService authService, IConfigService configService,
|
|||||||
response.EnsureSuccessStatusCode();
|
response.EnsureSuccessStatusCode();
|
||||||
string body = await response.Content.ReadAsStringAsync();
|
string body = await response.Content.ReadAsStringAsync();
|
||||||
|
|
||||||
//if the content creator doesnt exist, we get a 200 response, but the content isnt usable
|
// if the content creator doesn't exist, we get a 200 response, but the content isn't usable
|
||||||
//so let's not throw an exception, since "content creator no longer exists" is handled elsewhere
|
// so let's not throw an exception, since "content creator no longer exists" is handled elsewhere
|
||||||
//which means we wont get loads of exceptions
|
// which means we won't get loads of exceptions
|
||||||
if (body.Equals("[]"))
|
if (body.Equals("[]"))
|
||||||
{
|
{
|
||||||
return null;
|
return null;
|
||||||
@ -2897,7 +2897,7 @@ public class ApiService(IAuthService authService, IConfigService configService,
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public async Task<string> GetDRMMPDPSSH(string mpdUrl, string policy, string signature, string kvp)
|
public async Task<string> GetDrmMpdPssh(string mpdUrl, string policy, string signature, string kvp)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
@ -2941,9 +2941,9 @@ public class ApiService(IAuthService authService, IConfigService configService,
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public async Task<DateTime> GetDRMMPDLastModified(string mpdUrl, string policy, string signature, string kvp)
|
public async Task<DateTime> GetDrmMpdLastModified(string mpdUrl, string policy, string signature, string kvp)
|
||||||
{
|
{
|
||||||
Log.Debug("Calling GetDRMMPDLastModified");
|
Log.Debug("Calling GetDrmMpdLastModified");
|
||||||
Log.Debug($"mpdUrl: {mpdUrl}");
|
Log.Debug($"mpdUrl: {mpdUrl}");
|
||||||
Log.Debug($"policy: {policy}");
|
Log.Debug($"policy: {policy}");
|
||||||
Log.Debug($"signature: {signature}");
|
Log.Debug($"signature: {signature}");
|
||||||
@ -2989,10 +2989,10 @@ public class ApiService(IAuthService authService, IConfigService configService,
|
|||||||
return DateTime.Now;
|
return DateTime.Now;
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<string> GetDecryptionKeyOFDL(Dictionary<string, string> drmHeaders, string licenceUrl,
|
public async Task<string> GetDecryptionKeyOfdl(Dictionary<string, string> drmHeaders, string licenceUrl,
|
||||||
string pssh)
|
string pssh)
|
||||||
{
|
{
|
||||||
Log.Debug("Calling GetDecryptionOFDL");
|
Log.Debug("Calling GetDecryptionKeyOfdl");
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
@ -3052,7 +3052,7 @@ public class ApiService(IAuthService authService, IConfigService configService,
|
|||||||
return string.Empty;
|
return string.Empty;
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<string> GetDecryptionKeyCDM(Dictionary<string, string> drmHeaders, string licenceUrl,
|
public async Task<string> GetDecryptionKeyCdm(Dictionary<string, string> drmHeaders, string licenceUrl,
|
||||||
string pssh)
|
string pssh)
|
||||||
{
|
{
|
||||||
Log.Debug("Calling GetDecryptionKeyCDM");
|
Log.Debug("Calling GetDecryptionKeyCDM");
|
||||||
|
|||||||
@ -161,8 +161,8 @@ public class AuthService(IServiceProvider serviceProvider) : IAuthService
|
|||||||
|
|
||||||
public async Task<UserEntities.User?> ValidateAuthAsync()
|
public async Task<UserEntities.User?> ValidateAuthAsync()
|
||||||
{
|
{
|
||||||
// Resolve IAPIService lazily to avoid circular dependency
|
// Resolve IApiService lazily to avoid circular dependency
|
||||||
IAPIService apiService = serviceProvider.GetRequiredService<IAPIService>();
|
IApiService apiService = serviceProvider.GetRequiredService<IApiService>();
|
||||||
return await apiService.GetUserInfo("/users/me");
|
return await apiService.GetUserInfo("/users/me");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -4,9 +4,9 @@ using Serilog;
|
|||||||
|
|
||||||
namespace OF_DL.Services;
|
namespace OF_DL.Services;
|
||||||
|
|
||||||
public class DBService(IConfigService configService) : IDBService
|
public class DbService(IConfigService configService) : IDbService
|
||||||
{
|
{
|
||||||
public async Task CreateDB(string folder)
|
public async Task CreateDb(string folder)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
@ -18,15 +18,15 @@ public class DBService(IConfigService configService) : IDBService
|
|||||||
string dbFilePath = $"{folder}/Metadata/user_data.db";
|
string dbFilePath = $"{folder}/Metadata/user_data.db";
|
||||||
|
|
||||||
// connect to the new database file
|
// connect to the new database file
|
||||||
using SqliteConnection connection = new($"Data Source={dbFilePath}");
|
await using SqliteConnection connection = new($"Data Source={dbFilePath}");
|
||||||
// open the connection
|
// open the connection
|
||||||
connection.Open();
|
connection.Open();
|
||||||
|
|
||||||
// create the 'medias' table
|
// create the 'medias' table
|
||||||
using (SqliteCommand cmd =
|
await using (SqliteCommand cmd =
|
||||||
new(
|
new(
|
||||||
"CREATE TABLE IF NOT EXISTS medias (id INTEGER NOT NULL, media_id INTEGER, post_id INTEGER NOT NULL, link VARCHAR, directory VARCHAR, filename VARCHAR, size INTEGER, api_type VARCHAR, media_type VARCHAR, preview INTEGER, linked VARCHAR, downloaded INTEGER, created_at TIMESTAMP, record_created_at TIMESTAMP, PRIMARY KEY(id), UNIQUE(media_id));",
|
"CREATE TABLE IF NOT EXISTS medias (id INTEGER NOT NULL, media_id INTEGER, post_id INTEGER NOT NULL, link VARCHAR, directory VARCHAR, filename VARCHAR, size INTEGER, api_type VARCHAR, media_type VARCHAR, preview INTEGER, linked VARCHAR, downloaded INTEGER, created_at TIMESTAMP, record_created_at TIMESTAMP, PRIMARY KEY(id), UNIQUE(media_id));",
|
||||||
connection))
|
connection))
|
||||||
{
|
{
|
||||||
await cmd.ExecuteNonQueryAsync();
|
await cmd.ExecuteNonQueryAsync();
|
||||||
}
|
}
|
||||||
@ -36,7 +36,7 @@ public class DBService(IConfigService configService) : IDBService
|
|||||||
//
|
//
|
||||||
// Alter existing databases to create unique constraint on `medias`
|
// Alter existing databases to create unique constraint on `medias`
|
||||||
//
|
//
|
||||||
using (SqliteCommand cmd = new(@"
|
await using (SqliteCommand cmd = new(@"
|
||||||
PRAGMA foreign_keys=off;
|
PRAGMA foreign_keys=off;
|
||||||
|
|
||||||
BEGIN TRANSACTION;
|
BEGIN TRANSACTION;
|
||||||
@ -74,55 +74,55 @@ public class DBService(IConfigService configService) : IDBService
|
|||||||
}
|
}
|
||||||
|
|
||||||
// create the 'messages' table
|
// create the 'messages' table
|
||||||
using (SqliteCommand cmd =
|
await using (SqliteCommand cmd =
|
||||||
new(
|
new(
|
||||||
"CREATE TABLE IF NOT EXISTS messages (id INTEGER NOT NULL, post_id INTEGER NOT NULL, text VARCHAR, price INTEGER, paid INTEGER, archived BOOLEAN, created_at TIMESTAMP, user_id INTEGER, record_created_at TIMESTAMP, PRIMARY KEY(id), UNIQUE(post_id));",
|
"CREATE TABLE IF NOT EXISTS messages (id INTEGER NOT NULL, post_id INTEGER NOT NULL, text VARCHAR, price INTEGER, paid INTEGER, archived BOOLEAN, created_at TIMESTAMP, user_id INTEGER, record_created_at TIMESTAMP, PRIMARY KEY(id), UNIQUE(post_id));",
|
||||||
connection))
|
connection))
|
||||||
{
|
{
|
||||||
await cmd.ExecuteNonQueryAsync();
|
await cmd.ExecuteNonQueryAsync();
|
||||||
}
|
}
|
||||||
|
|
||||||
// create the 'posts' table
|
// create the 'posts' table
|
||||||
using (SqliteCommand cmd =
|
await using (SqliteCommand cmd =
|
||||||
new(
|
new(
|
||||||
"CREATE TABLE IF NOT EXISTS posts (id INTEGER NOT NULL, post_id INTEGER NOT NULL, text VARCHAR, price INTEGER, paid INTEGER, archived BOOLEAN, created_at TIMESTAMP, record_created_at TIMESTAMP, PRIMARY KEY(id), UNIQUE(post_id));",
|
"CREATE TABLE IF NOT EXISTS posts (id INTEGER NOT NULL, post_id INTEGER NOT NULL, text VARCHAR, price INTEGER, paid INTEGER, archived BOOLEAN, created_at TIMESTAMP, record_created_at TIMESTAMP, PRIMARY KEY(id), UNIQUE(post_id));",
|
||||||
connection))
|
connection))
|
||||||
{
|
{
|
||||||
await cmd.ExecuteNonQueryAsync();
|
await cmd.ExecuteNonQueryAsync();
|
||||||
}
|
}
|
||||||
|
|
||||||
// create the 'stories' table
|
// create the 'stories' table
|
||||||
using (SqliteCommand cmd =
|
await using (SqliteCommand cmd =
|
||||||
new(
|
new(
|
||||||
"CREATE TABLE IF NOT EXISTS stories (id INTEGER NOT NULL, post_id INTEGER NOT NULL, text VARCHAR, price INTEGER, paid INTEGER, archived BOOLEAN, created_at TIMESTAMP, record_created_at TIMESTAMP, PRIMARY KEY(id), UNIQUE(post_id));",
|
"CREATE TABLE IF NOT EXISTS stories (id INTEGER NOT NULL, post_id INTEGER NOT NULL, text VARCHAR, price INTEGER, paid INTEGER, archived BOOLEAN, created_at TIMESTAMP, record_created_at TIMESTAMP, PRIMARY KEY(id), UNIQUE(post_id));",
|
||||||
connection))
|
connection))
|
||||||
{
|
{
|
||||||
await cmd.ExecuteNonQueryAsync();
|
await cmd.ExecuteNonQueryAsync();
|
||||||
}
|
}
|
||||||
|
|
||||||
// create the 'others' table
|
// create the 'others' table
|
||||||
using (SqliteCommand cmd =
|
await using (SqliteCommand cmd =
|
||||||
new(
|
new(
|
||||||
"CREATE TABLE IF NOT EXISTS others (id INTEGER NOT NULL, post_id INTEGER NOT NULL, text VARCHAR, price INTEGER, paid INTEGER, archived BOOLEAN, created_at TIMESTAMP, record_created_at TIMESTAMP, PRIMARY KEY(id), UNIQUE(post_id));",
|
"CREATE TABLE IF NOT EXISTS others (id INTEGER NOT NULL, post_id INTEGER NOT NULL, text VARCHAR, price INTEGER, paid INTEGER, archived BOOLEAN, created_at TIMESTAMP, record_created_at TIMESTAMP, PRIMARY KEY(id), UNIQUE(post_id));",
|
||||||
connection))
|
connection))
|
||||||
{
|
{
|
||||||
await cmd.ExecuteNonQueryAsync();
|
await cmd.ExecuteNonQueryAsync();
|
||||||
}
|
}
|
||||||
|
|
||||||
// create the 'products' table
|
// create the 'products' table
|
||||||
using (SqliteCommand cmd =
|
await using (SqliteCommand cmd =
|
||||||
new(
|
new(
|
||||||
"CREATE TABLE IF NOT EXISTS products (id INTEGER NOT NULL, post_id INTEGER NOT NULL, text VARCHAR, price INTEGER, paid INTEGER, archived BOOLEAN, created_at TIMESTAMP, title VARCHAR, record_created_at TIMESTAMP, PRIMARY KEY(id), UNIQUE(post_id));",
|
"CREATE TABLE IF NOT EXISTS products (id INTEGER NOT NULL, post_id INTEGER NOT NULL, text VARCHAR, price INTEGER, paid INTEGER, archived BOOLEAN, created_at TIMESTAMP, title VARCHAR, record_created_at TIMESTAMP, PRIMARY KEY(id), UNIQUE(post_id));",
|
||||||
connection))
|
connection))
|
||||||
{
|
{
|
||||||
await cmd.ExecuteNonQueryAsync();
|
await cmd.ExecuteNonQueryAsync();
|
||||||
}
|
}
|
||||||
|
|
||||||
// create the 'profiles' table
|
// create the 'profiles' table
|
||||||
using (SqliteCommand cmd =
|
await using (SqliteCommand cmd =
|
||||||
new(
|
new(
|
||||||
"CREATE TABLE IF NOT EXISTS profiles (id INTEGER NOT NULL, user_id INTEGER NOT NULL, username VARCHAR NOT NULL, record_created_at TIMESTAMP, PRIMARY KEY(id), UNIQUE(username));",
|
"CREATE TABLE IF NOT EXISTS profiles (id INTEGER NOT NULL, user_id INTEGER NOT NULL, username VARCHAR NOT NULL, record_created_at TIMESTAMP, PRIMARY KEY(id), UNIQUE(username));",
|
||||||
connection))
|
connection))
|
||||||
{
|
{
|
||||||
await cmd.ExecuteNonQueryAsync();
|
await cmd.ExecuteNonQueryAsync();
|
||||||
}
|
}
|
||||||
@ -144,19 +144,19 @@ public class DBService(IConfigService configService) : IDBService
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task CreateUsersDB(Dictionary<string, long> users)
|
public async Task CreateUsersDb(Dictionary<string, long> users)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
using SqliteConnection connection = new($"Data Source={Directory.GetCurrentDirectory()}/users.db");
|
await using SqliteConnection connection = new($"Data Source={Directory.GetCurrentDirectory()}/users.db");
|
||||||
Log.Debug("Database data source: " + connection.DataSource);
|
Log.Debug("Database data source: " + connection.DataSource);
|
||||||
|
|
||||||
connection.Open();
|
connection.Open();
|
||||||
|
|
||||||
using (SqliteCommand cmd =
|
await using (SqliteCommand cmd =
|
||||||
new(
|
new(
|
||||||
"CREATE TABLE IF NOT EXISTS users (id INTEGER NOT NULL, user_id INTEGER NOT NULL, username VARCHAR NOT NULL, PRIMARY KEY(id), UNIQUE(username));",
|
"CREATE TABLE IF NOT EXISTS users (id INTEGER NOT NULL, user_id INTEGER NOT NULL, username VARCHAR NOT NULL, PRIMARY KEY(id), UNIQUE(username));",
|
||||||
connection))
|
connection))
|
||||||
{
|
{
|
||||||
await cmd.ExecuteNonQueryAsync();
|
await cmd.ExecuteNonQueryAsync();
|
||||||
}
|
}
|
||||||
@ -164,29 +164,23 @@ public class DBService(IConfigService configService) : IDBService
|
|||||||
Log.Debug("Adding missing creators");
|
Log.Debug("Adding missing creators");
|
||||||
foreach (KeyValuePair<string, long> user in users)
|
foreach (KeyValuePair<string, long> user in users)
|
||||||
{
|
{
|
||||||
using (SqliteCommand checkCmd = new("SELECT user_id, username FROM users WHERE user_id = @userId;",
|
await using SqliteCommand checkCmd = new("SELECT user_id, username FROM users WHERE user_id = @userId;",
|
||||||
connection))
|
connection);
|
||||||
|
checkCmd.Parameters.AddWithValue("@userId", user.Value);
|
||||||
|
await using SqliteDataReader reader = await checkCmd.ExecuteReaderAsync();
|
||||||
|
if (!reader.Read())
|
||||||
{
|
{
|
||||||
checkCmd.Parameters.AddWithValue("@userId", user.Value);
|
await using SqliteCommand insertCmd =
|
||||||
using (SqliteDataReader reader = await checkCmd.ExecuteReaderAsync())
|
new("INSERT INTO users (user_id, username) VALUES (@userId, @username);",
|
||||||
{
|
connection);
|
||||||
if (!reader.Read())
|
insertCmd.Parameters.AddWithValue("@userId", user.Value);
|
||||||
{
|
insertCmd.Parameters.AddWithValue("@username", user.Key);
|
||||||
using (SqliteCommand insertCmd =
|
await insertCmd.ExecuteNonQueryAsync();
|
||||||
new("INSERT INTO users (user_id, username) VALUES (@userId, @username);",
|
Log.Debug("Inserted new creator: " + user.Key);
|
||||||
connection))
|
}
|
||||||
{
|
else
|
||||||
insertCmd.Parameters.AddWithValue("@userId", user.Value);
|
{
|
||||||
insertCmd.Parameters.AddWithValue("@username", user.Key);
|
Log.Debug("Creator " + user.Key + " already exists");
|
||||||
await insertCmd.ExecuteNonQueryAsync();
|
|
||||||
Log.Debug("Inserted new creator: " + user.Key);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
Log.Debug("Creator " + user.Key + " already exists");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -211,12 +205,12 @@ public class DBService(IConfigService configService) : IDBService
|
|||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
using SqliteConnection connection = new($"Data Source={Directory.GetCurrentDirectory()}/users.db");
|
await using SqliteConnection connection = new($"Data Source={Directory.GetCurrentDirectory()}/users.db");
|
||||||
|
|
||||||
connection.Open();
|
connection.Open();
|
||||||
|
|
||||||
using (SqliteCommand checkCmd = new("SELECT user_id, username FROM users WHERE user_id = @userId;",
|
await using (SqliteCommand checkCmd = new("SELECT user_id, username FROM users WHERE user_id = @userId;",
|
||||||
connection))
|
connection))
|
||||||
{
|
{
|
||||||
checkCmd.Parameters.AddWithValue("@userId", user.Value);
|
checkCmd.Parameters.AddWithValue("@userId", user.Value);
|
||||||
await using (SqliteDataReader reader = await checkCmd.ExecuteReaderAsync())
|
await using (SqliteDataReader reader = await checkCmd.ExecuteReaderAsync())
|
||||||
@ -264,16 +258,16 @@ public class DBService(IConfigService configService) : IDBService
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task AddMessage(string folder, long post_id, string message_text, string price, bool is_paid,
|
public async Task AddMessage(string folder, long postId, string messageText, string price, bool isPaid,
|
||||||
bool is_archived, DateTime created_at, long user_id)
|
bool isArchived, DateTime createdAt, long userId)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
using SqliteConnection connection = new($"Data Source={folder}/Metadata/user_data.db");
|
await using SqliteConnection connection = new($"Data Source={folder}/Metadata/user_data.db");
|
||||||
connection.Open();
|
connection.Open();
|
||||||
await EnsureCreatedAtColumnExists(connection, "messages");
|
await EnsureCreatedAtColumnExists(connection, "messages");
|
||||||
using SqliteCommand cmd = new("SELECT COUNT(*) FROM messages WHERE post_id=@post_id", connection);
|
await using SqliteCommand cmd = new("SELECT COUNT(*) FROM messages WHERE post_id=@post_id", connection);
|
||||||
cmd.Parameters.AddWithValue("@post_id", post_id);
|
cmd.Parameters.AddWithValue("@post_id", postId);
|
||||||
int count = Convert.ToInt32(await cmd.ExecuteScalarAsync());
|
int count = Convert.ToInt32(await cmd.ExecuteScalarAsync());
|
||||||
if (count == 0)
|
if (count == 0)
|
||||||
{
|
{
|
||||||
@ -282,13 +276,13 @@ public class DBService(IConfigService configService) : IDBService
|
|||||||
new(
|
new(
|
||||||
"INSERT INTO messages(post_id, text, price, paid, archived, created_at, user_id, record_created_at) VALUES(@post_id, @message_text, @price, @is_paid, @is_archived, @created_at, @user_id, @record_created_at)",
|
"INSERT INTO messages(post_id, text, price, paid, archived, created_at, user_id, record_created_at) VALUES(@post_id, @message_text, @price, @is_paid, @is_archived, @created_at, @user_id, @record_created_at)",
|
||||||
connection);
|
connection);
|
||||||
insertCmd.Parameters.AddWithValue("@post_id", post_id);
|
insertCmd.Parameters.AddWithValue("@post_id", postId);
|
||||||
insertCmd.Parameters.AddWithValue("@message_text", message_text);
|
insertCmd.Parameters.AddWithValue("@message_text", messageText);
|
||||||
insertCmd.Parameters.AddWithValue("@price", price);
|
insertCmd.Parameters.AddWithValue("@price", price);
|
||||||
insertCmd.Parameters.AddWithValue("@is_paid", is_paid);
|
insertCmd.Parameters.AddWithValue("@is_paid", isPaid);
|
||||||
insertCmd.Parameters.AddWithValue("@is_archived", is_archived);
|
insertCmd.Parameters.AddWithValue("@is_archived", isArchived);
|
||||||
insertCmd.Parameters.AddWithValue("@created_at", created_at);
|
insertCmd.Parameters.AddWithValue("@created_at", createdAt);
|
||||||
insertCmd.Parameters.AddWithValue("@user_id", user_id);
|
insertCmd.Parameters.AddWithValue("@user_id", userId);
|
||||||
insertCmd.Parameters.AddWithValue("@record_created_at", DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"));
|
insertCmd.Parameters.AddWithValue("@record_created_at", DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"));
|
||||||
await insertCmd.ExecuteNonQueryAsync();
|
await insertCmd.ExecuteNonQueryAsync();
|
||||||
}
|
}
|
||||||
@ -309,30 +303,30 @@ public class DBService(IConfigService configService) : IDBService
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public async Task AddPost(string folder, long post_id, string message_text, string price, bool is_paid,
|
public async Task AddPost(string folder, long postId, string messageText, string price, bool isPaid,
|
||||||
bool is_archived, DateTime created_at)
|
bool isArchived, DateTime createdAt)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
using SqliteConnection connection = new($"Data Source={folder}/Metadata/user_data.db");
|
await using SqliteConnection connection = new($"Data Source={folder}/Metadata/user_data.db");
|
||||||
connection.Open();
|
connection.Open();
|
||||||
await EnsureCreatedAtColumnExists(connection, "posts");
|
await EnsureCreatedAtColumnExists(connection, "posts");
|
||||||
using SqliteCommand cmd = new("SELECT COUNT(*) FROM posts WHERE post_id=@post_id", connection);
|
await using SqliteCommand cmd = new("SELECT COUNT(*) FROM posts WHERE post_id=@post_id", connection);
|
||||||
cmd.Parameters.AddWithValue("@post_id", post_id);
|
cmd.Parameters.AddWithValue("@post_id", postId);
|
||||||
int count = Convert.ToInt32(await cmd.ExecuteScalarAsync());
|
int count = Convert.ToInt32(await cmd.ExecuteScalarAsync());
|
||||||
if (count == 0)
|
if (count == 0)
|
||||||
{
|
{
|
||||||
// If the record doesn't exist, insert a new one
|
// If the record doesn't exist, insert a new one
|
||||||
using SqliteCommand insertCmd =
|
await using SqliteCommand insertCmd =
|
||||||
new(
|
new(
|
||||||
"INSERT INTO posts(post_id, text, price, paid, archived, created_at, record_created_at) VALUES(@post_id, @message_text, @price, @is_paid, @is_archived, @created_at, @record_created_at)",
|
"INSERT INTO posts(post_id, text, price, paid, archived, created_at, record_created_at) VALUES(@post_id, @message_text, @price, @is_paid, @is_archived, @created_at, @record_created_at)",
|
||||||
connection);
|
connection);
|
||||||
insertCmd.Parameters.AddWithValue("@post_id", post_id);
|
insertCmd.Parameters.AddWithValue("@post_id", postId);
|
||||||
insertCmd.Parameters.AddWithValue("@message_text", message_text);
|
insertCmd.Parameters.AddWithValue("@message_text", messageText);
|
||||||
insertCmd.Parameters.AddWithValue("@price", price);
|
insertCmd.Parameters.AddWithValue("@price", price);
|
||||||
insertCmd.Parameters.AddWithValue("@is_paid", is_paid);
|
insertCmd.Parameters.AddWithValue("@is_paid", isPaid);
|
||||||
insertCmd.Parameters.AddWithValue("@is_archived", is_archived);
|
insertCmd.Parameters.AddWithValue("@is_archived", isArchived);
|
||||||
insertCmd.Parameters.AddWithValue("@created_at", created_at);
|
insertCmd.Parameters.AddWithValue("@created_at", createdAt);
|
||||||
insertCmd.Parameters.AddWithValue("@record_created_at", DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"));
|
insertCmd.Parameters.AddWithValue("@record_created_at", DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"));
|
||||||
await insertCmd.ExecuteNonQueryAsync();
|
await insertCmd.ExecuteNonQueryAsync();
|
||||||
}
|
}
|
||||||
@ -353,30 +347,30 @@ public class DBService(IConfigService configService) : IDBService
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public async Task AddStory(string folder, long post_id, string message_text, string price, bool is_paid,
|
public async Task AddStory(string folder, long postId, string messageText, string price, bool isPaid,
|
||||||
bool is_archived, DateTime created_at)
|
bool isArchived, DateTime createdAt)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
using SqliteConnection connection = new($"Data Source={folder}/Metadata/user_data.db");
|
await using SqliteConnection connection = new($"Data Source={folder}/Metadata/user_data.db");
|
||||||
connection.Open();
|
connection.Open();
|
||||||
await EnsureCreatedAtColumnExists(connection, "stories");
|
await EnsureCreatedAtColumnExists(connection, "stories");
|
||||||
using SqliteCommand cmd = new("SELECT COUNT(*) FROM stories WHERE post_id=@post_id", connection);
|
await using SqliteCommand cmd = new("SELECT COUNT(*) FROM stories WHERE post_id=@post_id", connection);
|
||||||
cmd.Parameters.AddWithValue("@post_id", post_id);
|
cmd.Parameters.AddWithValue("@post_id", postId);
|
||||||
int count = Convert.ToInt32(await cmd.ExecuteScalarAsync());
|
int count = Convert.ToInt32(await cmd.ExecuteScalarAsync());
|
||||||
if (count == 0)
|
if (count == 0)
|
||||||
{
|
{
|
||||||
// If the record doesn't exist, insert a new one
|
// If the record doesn't exist, insert a new one
|
||||||
using SqliteCommand insertCmd =
|
await using SqliteCommand insertCmd =
|
||||||
new(
|
new(
|
||||||
"INSERT INTO stories(post_id, text, price, paid, archived, created_at, record_created_at) VALUES(@post_id, @message_text, @price, @is_paid, @is_archived, @created_at, @record_created_at)",
|
"INSERT INTO stories(post_id, text, price, paid, archived, created_at, record_created_at) VALUES(@post_id, @message_text, @price, @is_paid, @is_archived, @created_at, @record_created_at)",
|
||||||
connection);
|
connection);
|
||||||
insertCmd.Parameters.AddWithValue("@post_id", post_id);
|
insertCmd.Parameters.AddWithValue("@post_id", postId);
|
||||||
insertCmd.Parameters.AddWithValue("@message_text", message_text);
|
insertCmd.Parameters.AddWithValue("@message_text", messageText);
|
||||||
insertCmd.Parameters.AddWithValue("@price", price);
|
insertCmd.Parameters.AddWithValue("@price", price);
|
||||||
insertCmd.Parameters.AddWithValue("@is_paid", is_paid);
|
insertCmd.Parameters.AddWithValue("@is_paid", isPaid);
|
||||||
insertCmd.Parameters.AddWithValue("@is_archived", is_archived);
|
insertCmd.Parameters.AddWithValue("@is_archived", isArchived);
|
||||||
insertCmd.Parameters.AddWithValue("@created_at", created_at);
|
insertCmd.Parameters.AddWithValue("@created_at", createdAt);
|
||||||
insertCmd.Parameters.AddWithValue("@record_created_at", DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"));
|
insertCmd.Parameters.AddWithValue("@record_created_at", DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"));
|
||||||
await insertCmd.ExecuteNonQueryAsync();
|
await insertCmd.ExecuteNonQueryAsync();
|
||||||
}
|
}
|
||||||
@ -397,13 +391,13 @@ public class DBService(IConfigService configService) : IDBService
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public async Task AddMedia(string folder, long media_id, long post_id, string link, string? directory,
|
public async Task AddMedia(string folder, long mediaId, long postId, string link, string? directory,
|
||||||
string? filename, long? size, string api_type, string media_type, bool preview, bool downloaded,
|
string? filename, long? size, string apiType, string mediaType, bool preview, bool downloaded,
|
||||||
DateTime? created_at)
|
DateTime? createdAt)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
using SqliteConnection connection = new($"Data Source={folder}/Metadata/user_data.db");
|
await using SqliteConnection connection = new($"Data Source={folder}/Metadata/user_data.db");
|
||||||
connection.Open();
|
connection.Open();
|
||||||
await EnsureCreatedAtColumnExists(connection, "medias");
|
await EnsureCreatedAtColumnExists(connection, "medias");
|
||||||
StringBuilder sql = new("SELECT COUNT(*) FROM medias WHERE media_id=@media_id");
|
StringBuilder sql = new("SELECT COUNT(*) FROM medias WHERE media_id=@media_id");
|
||||||
@ -412,15 +406,15 @@ public class DBService(IConfigService configService) : IDBService
|
|||||||
sql.Append(" and api_type=@api_type");
|
sql.Append(" and api_type=@api_type");
|
||||||
}
|
}
|
||||||
|
|
||||||
using SqliteCommand cmd = new(sql.ToString(), connection);
|
await using SqliteCommand cmd = new(sql.ToString(), connection);
|
||||||
cmd.Parameters.AddWithValue("@media_id", media_id);
|
cmd.Parameters.AddWithValue("@media_id", mediaId);
|
||||||
cmd.Parameters.AddWithValue("@api_type", api_type);
|
cmd.Parameters.AddWithValue("@api_type", apiType);
|
||||||
int count = Convert.ToInt32(cmd.ExecuteScalar());
|
int count = Convert.ToInt32(cmd.ExecuteScalar());
|
||||||
if (count == 0)
|
if (count == 0)
|
||||||
{
|
{
|
||||||
// If the record doesn't exist, insert a new one
|
// If the record doesn't exist, insert a new one
|
||||||
using SqliteCommand insertCmd = new(
|
await using SqliteCommand insertCmd = new(
|
||||||
$"INSERT INTO medias(media_id, post_id, link, directory, filename, size, api_type, media_type, preview, downloaded, created_at, record_created_at) VALUES({media_id}, {post_id}, '{link}', '{directory ?? "NULL"}', '{filename ?? "NULL"}', {size?.ToString() ?? "NULL"}, '{api_type}', '{media_type}', {Convert.ToInt32(preview)}, {Convert.ToInt32(downloaded)}, '{created_at?.ToString("yyyy-MM-dd HH:mm:ss")}', '{DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss")}')",
|
$"INSERT INTO medias(media_id, post_id, link, directory, filename, size, api_type, media_type, preview, downloaded, created_at, record_created_at) VALUES({mediaId}, {postId}, '{link}', '{directory ?? "NULL"}', '{filename ?? "NULL"}', {size?.ToString() ?? "NULL"}, '{apiType}', '{mediaType}', {Convert.ToInt32(preview)}, {Convert.ToInt32(downloaded)}, '{createdAt?.ToString("yyyy-MM-dd HH:mm:ss")}', '{DateTime.Now:yyyy-MM-dd HH:mm:ss}')",
|
||||||
connection);
|
connection);
|
||||||
await insertCmd.ExecuteNonQueryAsync();
|
await insertCmd.ExecuteNonQueryAsync();
|
||||||
}
|
}
|
||||||
@ -441,12 +435,10 @@ public class DBService(IConfigService configService) : IDBService
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public async Task<bool> CheckDownloaded(string folder, long media_id, string api_type)
|
public async Task<bool> CheckDownloaded(string folder, long mediaId, string apiType)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
bool downloaded;
|
|
||||||
|
|
||||||
await using SqliteConnection connection = new($"Data Source={folder}/Metadata/user_data.db");
|
await using SqliteConnection connection = new($"Data Source={folder}/Metadata/user_data.db");
|
||||||
StringBuilder sql = new("SELECT downloaded FROM medias WHERE media_id=@media_id");
|
StringBuilder sql = new("SELECT downloaded FROM medias WHERE media_id=@media_id");
|
||||||
if (configService.CurrentConfig.DownloadDuplicatedMedia)
|
if (configService.CurrentConfig.DownloadDuplicatedMedia)
|
||||||
@ -456,9 +448,9 @@ public class DBService(IConfigService configService) : IDBService
|
|||||||
|
|
||||||
connection.Open();
|
connection.Open();
|
||||||
await using SqliteCommand cmd = new(sql.ToString(), connection);
|
await using SqliteCommand cmd = new(sql.ToString(), connection);
|
||||||
cmd.Parameters.AddWithValue("@media_id", media_id);
|
cmd.Parameters.AddWithValue("@media_id", mediaId);
|
||||||
cmd.Parameters.AddWithValue("@api_type", api_type);
|
cmd.Parameters.AddWithValue("@api_type", apiType);
|
||||||
downloaded = Convert.ToBoolean(await cmd.ExecuteScalarAsync());
|
bool downloaded = Convert.ToBoolean(await cmd.ExecuteScalarAsync());
|
||||||
|
|
||||||
return downloaded;
|
return downloaded;
|
||||||
}
|
}
|
||||||
@ -480,10 +472,10 @@ public class DBService(IConfigService configService) : IDBService
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public async Task UpdateMedia(string folder, long media_id, string api_type, string directory, string filename,
|
public async Task UpdateMedia(string folder, long mediaId, string apiType, string directory, string filename,
|
||||||
long size, bool downloaded, DateTime created_at)
|
long size, bool downloaded, DateTime createdAt)
|
||||||
{
|
{
|
||||||
using SqliteConnection connection = new($"Data Source={folder}/Metadata/user_data.db");
|
await using SqliteConnection connection = new($"Data Source={folder}/Metadata/user_data.db");
|
||||||
connection.Open();
|
connection.Open();
|
||||||
|
|
||||||
// Construct the update command
|
// Construct the update command
|
||||||
@ -496,33 +488,30 @@ public class DBService(IConfigService configService) : IDBService
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Create a new command object
|
// Create a new command object
|
||||||
using SqliteCommand command = new(sql.ToString(), connection);
|
await using SqliteCommand command = new(sql.ToString(), connection);
|
||||||
// Add parameters to the command object
|
// Add parameters to the command object
|
||||||
command.Parameters.AddWithValue("@directory", directory);
|
command.Parameters.AddWithValue("@directory", directory);
|
||||||
command.Parameters.AddWithValue("@filename", filename);
|
command.Parameters.AddWithValue("@filename", filename);
|
||||||
command.Parameters.AddWithValue("@size", size);
|
command.Parameters.AddWithValue("@size", size);
|
||||||
command.Parameters.AddWithValue("@downloaded", downloaded ? 1 : 0);
|
command.Parameters.AddWithValue("@downloaded", downloaded ? 1 : 0);
|
||||||
command.Parameters.AddWithValue("@created_at", created_at);
|
command.Parameters.AddWithValue("@created_at", createdAt);
|
||||||
command.Parameters.AddWithValue("@media_id", media_id);
|
command.Parameters.AddWithValue("@media_id", mediaId);
|
||||||
command.Parameters.AddWithValue("@api_type", api_type);
|
command.Parameters.AddWithValue("@api_type", apiType);
|
||||||
|
|
||||||
// Execute the command
|
// Execute the command
|
||||||
await command.ExecuteNonQueryAsync();
|
await command.ExecuteNonQueryAsync();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public async Task<long> GetStoredFileSize(string folder, long media_id, string api_type)
|
public async Task<long> GetStoredFileSize(string folder, long mediaId, string apiType)
|
||||||
{
|
{
|
||||||
long size;
|
await using SqliteConnection connection = new($"Data Source={folder}/Metadata/user_data.db");
|
||||||
using (SqliteConnection connection = new($"Data Source={folder}/Metadata/user_data.db"))
|
connection.Open();
|
||||||
{
|
await using SqliteCommand cmd = new("SELECT size FROM medias WHERE media_id=@media_id and api_type=@api_type",
|
||||||
connection.Open();
|
connection);
|
||||||
using SqliteCommand cmd = new("SELECT size FROM medias WHERE media_id=@media_id and api_type=@api_type",
|
cmd.Parameters.AddWithValue("@media_id", mediaId);
|
||||||
connection);
|
cmd.Parameters.AddWithValue("@api_type", apiType);
|
||||||
cmd.Parameters.AddWithValue("@media_id", media_id);
|
long size = Convert.ToInt64(await cmd.ExecuteScalarAsync());
|
||||||
cmd.Parameters.AddWithValue("@api_type", api_type);
|
|
||||||
size = Convert.ToInt64(await cmd.ExecuteScalarAsync());
|
|
||||||
}
|
|
||||||
|
|
||||||
return size;
|
return size;
|
||||||
}
|
}
|
||||||
@ -530,10 +519,9 @@ public class DBService(IConfigService configService) : IDBService
|
|||||||
public async Task<DateTime?> GetMostRecentPostDate(string folder)
|
public async Task<DateTime?> GetMostRecentPostDate(string folder)
|
||||||
{
|
{
|
||||||
DateTime? mostRecentDate = null;
|
DateTime? mostRecentDate = null;
|
||||||
using (SqliteConnection connection = new($"Data Source={folder}/Metadata/user_data.db"))
|
await using SqliteConnection connection = new($"Data Source={folder}/Metadata/user_data.db");
|
||||||
{
|
connection.Open();
|
||||||
connection.Open();
|
await using SqliteCommand cmd = new(@"
|
||||||
using SqliteCommand cmd = new(@"
|
|
||||||
SELECT
|
SELECT
|
||||||
MIN(created_at) AS created_at
|
MIN(created_at) AS created_at
|
||||||
FROM (
|
FROM (
|
||||||
@ -549,11 +537,10 @@ public class DBService(IConfigService configService) : IDBService
|
|||||||
ON P.post_id = m.post_id
|
ON P.post_id = m.post_id
|
||||||
WHERE m.downloaded = 0
|
WHERE m.downloaded = 0
|
||||||
)", connection);
|
)", connection);
|
||||||
object? scalarValue = await cmd.ExecuteScalarAsync();
|
object? scalarValue = await cmd.ExecuteScalarAsync();
|
||||||
if (scalarValue != null && scalarValue != DBNull.Value)
|
if (scalarValue != null && scalarValue != DBNull.Value)
|
||||||
{
|
{
|
||||||
mostRecentDate = Convert.ToDateTime(scalarValue);
|
mostRecentDate = Convert.ToDateTime(scalarValue);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return mostRecentDate;
|
return mostRecentDate;
|
||||||
@ -561,8 +548,8 @@ public class DBService(IConfigService configService) : IDBService
|
|||||||
|
|
||||||
private async Task EnsureCreatedAtColumnExists(SqliteConnection connection, string tableName)
|
private async Task EnsureCreatedAtColumnExists(SqliteConnection connection, string tableName)
|
||||||
{
|
{
|
||||||
using SqliteCommand cmd = new($"PRAGMA table_info({tableName});", connection);
|
await using SqliteCommand cmd = new($"PRAGMA table_info({tableName});", connection);
|
||||||
using SqliteDataReader reader = await cmd.ExecuteReaderAsync();
|
await using SqliteDataReader reader = await cmd.ExecuteReaderAsync();
|
||||||
bool columnExists = false;
|
bool columnExists = false;
|
||||||
|
|
||||||
while (await reader.ReadAsync())
|
while (await reader.ReadAsync())
|
||||||
@ -576,7 +563,7 @@ public class DBService(IConfigService configService) : IDBService
|
|||||||
|
|
||||||
if (!columnExists)
|
if (!columnExists)
|
||||||
{
|
{
|
||||||
using SqliteCommand alterCmd = new($"ALTER TABLE {tableName} ADD COLUMN record_created_at TIMESTAMP;",
|
await using SqliteCommand alterCmd = new($"ALTER TABLE {tableName} ADD COLUMN record_created_at TIMESTAMP;",
|
||||||
connection);
|
connection);
|
||||||
await alterCmd.ExecuteNonQueryAsync();
|
await alterCmd.ExecuteNonQueryAsync();
|
||||||
}
|
}
|
||||||
@ -10,10 +10,10 @@ using UserEntities = OF_DL.Models.Entities.Users;
|
|||||||
namespace OF_DL.Services;
|
namespace OF_DL.Services;
|
||||||
|
|
||||||
public class DownloadOrchestrationService(
|
public class DownloadOrchestrationService(
|
||||||
IAPIService apiService,
|
IApiService apiService,
|
||||||
IConfigService configService,
|
IConfigService configService,
|
||||||
IDownloadService downloadService,
|
IDownloadService downloadService,
|
||||||
IDBService dbService) : IDownloadOrchestrationService
|
IDbService dbService) : IDownloadOrchestrationService
|
||||||
{
|
{
|
||||||
public List<long> PaidPostIds { get; } = new();
|
public List<long> PaidPostIds { get; } = new();
|
||||||
|
|
||||||
@ -85,7 +85,7 @@ public class DownloadOrchestrationService(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
await dbService.CreateUsersDB(result.Users);
|
await dbService.CreateUsersDb(result.Users);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -113,7 +113,7 @@ public class DownloadOrchestrationService(
|
|||||||
Log.Debug($"Created folder for {username}");
|
Log.Debug($"Created folder for {username}");
|
||||||
}
|
}
|
||||||
|
|
||||||
await dbService.CreateDB(path);
|
await dbService.CreateDb(path);
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<CreatorDownloadResult> DownloadCreatorContentAsync(
|
public async Task<CreatorDownloadResult> DownloadCreatorContentAsync(
|
||||||
@ -346,7 +346,7 @@ public class DownloadOrchestrationService(
|
|||||||
}
|
}
|
||||||
|
|
||||||
await apiService.GetUserInfo($"/users/{user.Key}");
|
await apiService.GetUserInfo($"/users/{user.Key}");
|
||||||
await dbService.CreateDB(path);
|
await dbService.CreateDb(path);
|
||||||
}
|
}
|
||||||
|
|
||||||
string basePath = !string.IsNullOrEmpty(config.DownloadPath)
|
string basePath = !string.IsNullOrEmpty(config.DownloadPath)
|
||||||
|
|||||||
@ -19,9 +19,9 @@ namespace OF_DL.Services;
|
|||||||
public class DownloadService(
|
public class DownloadService(
|
||||||
IAuthService authService,
|
IAuthService authService,
|
||||||
IConfigService configService,
|
IConfigService configService,
|
||||||
IDBService dbService,
|
IDbService dbService,
|
||||||
IFileNameService fileNameService,
|
IFileNameService fileNameService,
|
||||||
IAPIService apiService)
|
IApiService apiService)
|
||||||
: IDownloadService
|
: IDownloadService
|
||||||
{
|
{
|
||||||
private TaskCompletionSource<bool> _completionSource = new();
|
private TaskCompletionSource<bool> _completionSource = new();
|
||||||
@ -67,7 +67,7 @@ public class DownloadService(
|
|||||||
Directory.CreateDirectory(folder + subFolder);
|
Directory.CreateDirectory(folder + subFolder);
|
||||||
}
|
}
|
||||||
|
|
||||||
List<string> md5Hashes = CalculateFolderMD5(folder + subFolder);
|
List<string> md5Hashes = CalculateFolderMd5(folder + subFolder);
|
||||||
|
|
||||||
Uri uri = new(url);
|
Uri uri = new(url);
|
||||||
string destinationPath = $"{folder}{subFolder}/";
|
string destinationPath = $"{folder}{subFolder}/";
|
||||||
@ -205,7 +205,7 @@ public class DownloadService(
|
|||||||
}
|
}
|
||||||
|
|
||||||
private async Task OnFFMPEGDownloadComplete(string tempFilename, DateTime lastModified, string folder, string path,
|
private async Task OnFFMPEGDownloadComplete(string tempFilename, DateTime lastModified, string folder, string path,
|
||||||
string customFileName, string filename, long media_id, string api_type, IProgressReporter progressReporter)
|
string customFileName, string filename, long mediaId, string apiType, IProgressReporter progressReporter)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
@ -223,16 +223,9 @@ public class DownloadService(
|
|||||||
long fileSizeInBytes = new FileInfo(!string.IsNullOrEmpty(customFileName)
|
long fileSizeInBytes = new FileInfo(!string.IsNullOrEmpty(customFileName)
|
||||||
? folder + path + "/" + customFileName + ".mp4"
|
? folder + path + "/" + customFileName + ".mp4"
|
||||||
: tempFilename).Length;
|
: tempFilename).Length;
|
||||||
if (configService.CurrentConfig.ShowScrapeSize)
|
progressReporter.ReportProgress(configService.CurrentConfig.ShowScrapeSize ? fileSizeInBytes : 1);
|
||||||
{
|
|
||||||
progressReporter.ReportProgress(fileSizeInBytes);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
progressReporter.ReportProgress(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
await dbService.UpdateMedia(folder, media_id, api_type, folder + path,
|
await dbService.UpdateMedia(folder, mediaId, apiType, folder + path,
|
||||||
!string.IsNullOrEmpty(customFileName) ? customFileName + ".mp4" : filename + "_source.mp4",
|
!string.IsNullOrEmpty(customFileName) ? customFileName + ".mp4" : filename + "_source.mp4",
|
||||||
fileSizeInBytes, true, lastModified);
|
fileSizeInBytes, true, lastModified);
|
||||||
}
|
}
|
||||||
@ -266,32 +259,27 @@ public class DownloadService(
|
|||||||
_completionSource.TrySetResult(false);
|
_completionSource.TrySetResult(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static List<string> CalculateFolderMD5(string folder)
|
private static List<string> CalculateFolderMd5(string folder)
|
||||||
{
|
{
|
||||||
List<string> md5Hashes = new();
|
List<string> md5Hashes = [];
|
||||||
if (Directory.Exists(folder))
|
if (!Directory.Exists(folder))
|
||||||
{
|
{
|
||||||
string[] files = Directory.GetFiles(folder);
|
return md5Hashes;
|
||||||
|
|
||||||
foreach (string file in files)
|
|
||||||
{
|
|
||||||
md5Hashes.Add(CalculateMD5(file));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
string[] files = Directory.GetFiles(folder);
|
||||||
|
|
||||||
|
md5Hashes.AddRange(files.Select(CalculateMd5));
|
||||||
|
|
||||||
return md5Hashes;
|
return md5Hashes;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static string CalculateMD5(string filePath)
|
private static string CalculateMd5(string filePath)
|
||||||
{
|
{
|
||||||
using (MD5 md5 = MD5.Create())
|
using MD5 md5 = MD5.Create();
|
||||||
{
|
using FileStream stream = File.OpenRead(filePath);
|
||||||
using (FileStream stream = File.OpenRead(filePath))
|
byte[] hash = md5.ComputeHash(stream);
|
||||||
{
|
return BitConverter.ToString(hash).Replace("-", "").ToLowerInvariant();
|
||||||
byte[] hash = md5.ComputeHash(stream);
|
|
||||||
return BitConverter.ToString(hash).Replace("-", "").ToLowerInvariant();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@ -299,17 +287,17 @@ public class DownloadService(
|
|||||||
/// <param name="path"></param>
|
/// <param name="path"></param>
|
||||||
/// <param name="url"></param>
|
/// <param name="url"></param>
|
||||||
/// <param name="folder"></param>
|
/// <param name="folder"></param>
|
||||||
/// <param name="media_id"></param>
|
/// <param name="mediaId"></param>
|
||||||
/// <param name="api_type"></param>
|
/// <param name="apiType"></param>
|
||||||
/// <param name="progressReporter"></param>
|
/// <param name="progressReporter"></param>
|
||||||
/// <param name="serverFileName"></param>
|
/// <param name="serverFileName"></param>
|
||||||
/// <param name="resolvedFileName"></param>
|
/// <param name="resolvedFileName"></param>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
protected async Task<bool> CreateDirectoriesAndDownloadMedia(string path,
|
private async Task<bool> CreateDirectoriesAndDownloadMedia(string path,
|
||||||
string url,
|
string url,
|
||||||
string folder,
|
string folder,
|
||||||
long media_id,
|
long mediaId,
|
||||||
string api_type,
|
string apiType,
|
||||||
IProgressReporter progressReporter,
|
IProgressReporter progressReporter,
|
||||||
string serverFileName,
|
string serverFileName,
|
||||||
string resolvedFileName)
|
string resolvedFileName)
|
||||||
@ -325,7 +313,7 @@ public class DownloadService(
|
|||||||
|
|
||||||
path = UpdatePathBasedOnExtension(folder, path, extension);
|
path = UpdatePathBasedOnExtension(folder, path, extension);
|
||||||
|
|
||||||
return await ProcessMediaDownload(folder, media_id, api_type, url, path, serverFileName, resolvedFileName,
|
return await ProcessMediaDownload(folder, mediaId, apiType, url, path, serverFileName, resolvedFileName,
|
||||||
extension, progressReporter);
|
extension, progressReporter);
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
@ -461,12 +449,12 @@ public class DownloadService(
|
|||||||
if (uri.Host == "cdn3.onlyfans.com" && uri.LocalPath.Contains("/dash/files"))
|
if (uri.Host == "cdn3.onlyfans.com" && uri.LocalPath.Contains("/dash/files"))
|
||||||
{
|
{
|
||||||
string[] messageUrlParsed = url.Split(',');
|
string[] messageUrlParsed = url.Split(',');
|
||||||
string mpdURL = messageUrlParsed[0];
|
string mpdUrl = messageUrlParsed[0];
|
||||||
string policy = messageUrlParsed[1];
|
string policy = messageUrlParsed[1];
|
||||||
string signature = messageUrlParsed[2];
|
string signature = messageUrlParsed[2];
|
||||||
string kvp = messageUrlParsed[3];
|
string kvp = messageUrlParsed[3];
|
||||||
|
|
||||||
mpdURL = mpdURL.Replace(".mpd", "_source.mp4");
|
mpdUrl = mpdUrl.Replace(".mpd", "_source.mp4");
|
||||||
|
|
||||||
using HttpClient client = new();
|
using HttpClient client = new();
|
||||||
client.DefaultRequestHeaders.Add("Cookie",
|
client.DefaultRequestHeaders.Add("Cookie",
|
||||||
@ -474,7 +462,7 @@ public class DownloadService(
|
|||||||
client.DefaultRequestHeaders.Add("User-Agent", authService.CurrentAuth.UserAgent);
|
client.DefaultRequestHeaders.Add("User-Agent", authService.CurrentAuth.UserAgent);
|
||||||
|
|
||||||
using HttpResponseMessage response =
|
using HttpResponseMessage response =
|
||||||
await client.GetAsync(mpdURL, HttpCompletionOption.ResponseHeadersRead);
|
await client.GetAsync(mpdUrl, HttpCompletionOption.ResponseHeadersRead);
|
||||||
if (response.IsSuccessStatusCode)
|
if (response.IsSuccessStatusCode)
|
||||||
{
|
{
|
||||||
fileSize = response.Content.Headers.ContentLength ?? 0;
|
fileSize = response.Content.Headers.ContentLength ?? 0;
|
||||||
@ -500,7 +488,7 @@ public class DownloadService(
|
|||||||
return fileSize;
|
return fileSize;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static async Task<DateTime> GetDRMVideoLastModified(string url, Auth auth)
|
public static async Task<DateTime> GetDrmVideoLastModified(string url, Auth auth)
|
||||||
{
|
{
|
||||||
string[] messageUrlParsed = url.Split(',');
|
string[] messageUrlParsed = url.Split(',');
|
||||||
string mpdUrl = messageUrlParsed[0];
|
string mpdUrl = messageUrlParsed[0];
|
||||||
@ -532,15 +520,12 @@ public class DownloadService(
|
|||||||
using HttpClient client = new();
|
using HttpClient client = new();
|
||||||
|
|
||||||
using HttpResponseMessage response = await client.GetAsync(url, HttpCompletionOption.ResponseHeadersRead);
|
using HttpResponseMessage response = await client.GetAsync(url, HttpCompletionOption.ResponseHeadersRead);
|
||||||
if (response.IsSuccessStatusCode)
|
if (!response.IsSuccessStatusCode)
|
||||||
{
|
{
|
||||||
if (response.Content.Headers.LastModified != null)
|
return DateTime.Now;
|
||||||
{
|
|
||||||
return response.Content.Headers.LastModified.Value.DateTime;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return DateTime.Now;
|
return response.Content.Headers.LastModified?.DateTime ?? DateTime.Now;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@ -636,8 +621,8 @@ public class DownloadService(
|
|||||||
/// Handles new media by downloading and updating the database.
|
/// Handles new media by downloading and updating the database.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="folder"></param>
|
/// <param name="folder"></param>
|
||||||
/// <param name="media_id"></param>
|
/// <param name="mediaId"></param>
|
||||||
/// <param name="api_type"></param>
|
/// <param name="apiType"></param>
|
||||||
/// <param name="url"></param>
|
/// <param name="url"></param>
|
||||||
/// <param name="path"></param>
|
/// <param name="path"></param>
|
||||||
/// <param name="serverFilename"></param>
|
/// <param name="serverFilename"></param>
|
||||||
@ -646,8 +631,8 @@ public class DownloadService(
|
|||||||
/// <param name="progressReporter"></param>
|
/// <param name="progressReporter"></param>
|
||||||
/// <returns>A Task resulting in a boolean indicating whether the media is newly downloaded or not.</returns>
|
/// <returns>A Task resulting in a boolean indicating whether the media is newly downloaded or not.</returns>
|
||||||
private async Task<bool> HandleNewMedia(string folder,
|
private async Task<bool> HandleNewMedia(string folder,
|
||||||
long media_id,
|
long mediaId,
|
||||||
string api_type,
|
string apiType,
|
||||||
string url,
|
string url,
|
||||||
string path,
|
string path,
|
||||||
string serverFilename,
|
string serverFilename,
|
||||||
@ -696,32 +681,18 @@ public class DownloadService(
|
|||||||
|
|
||||||
fileSizeInBytes = GetLocalFileSize(finalPath);
|
fileSizeInBytes = GetLocalFileSize(finalPath);
|
||||||
lastModified = File.GetLastWriteTime(finalPath);
|
lastModified = File.GetLastWriteTime(finalPath);
|
||||||
if (configService.CurrentConfig.ShowScrapeSize)
|
progressReporter.ReportProgress(configService.CurrentConfig.ShowScrapeSize ? fileSizeInBytes : 1);
|
||||||
{
|
|
||||||
progressReporter.ReportProgress(fileSizeInBytes);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
progressReporter.ReportProgress(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
status = false;
|
status = false;
|
||||||
}
|
}
|
||||||
// Handle the case where the file has been downloaded in the past with a custom filename.
|
// Handle the case where the file has been downloaded in the past with a custom filename.
|
||||||
//but it has downloaded outsite of this application so it doesn't exist in the database
|
// but it has downloaded outside of this application so it doesn't exist in the database
|
||||||
// this is a bit improbable but we should check for that.
|
// this is a bit improbable but we should check for that.
|
||||||
else if (File.Exists(fullPathWithTheNewFileName))
|
else if (File.Exists(fullPathWithTheNewFileName))
|
||||||
{
|
{
|
||||||
fileSizeInBytes = GetLocalFileSize(fullPathWithTheNewFileName);
|
fileSizeInBytes = GetLocalFileSize(fullPathWithTheNewFileName);
|
||||||
lastModified = File.GetLastWriteTime(fullPathWithTheNewFileName);
|
lastModified = File.GetLastWriteTime(fullPathWithTheNewFileName);
|
||||||
if (configService.CurrentConfig.ShowScrapeSize)
|
progressReporter.ReportProgress(configService.CurrentConfig.ShowScrapeSize ? fileSizeInBytes : 1);
|
||||||
{
|
|
||||||
progressReporter.ReportProgress(fileSizeInBytes);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
progressReporter.ReportProgress(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
status = false;
|
status = false;
|
||||||
}
|
}
|
||||||
@ -733,9 +704,9 @@ public class DownloadService(
|
|||||||
}
|
}
|
||||||
|
|
||||||
//finaly check which filename we should use. Custom or the server one.
|
//finaly check which filename we should use. Custom or the server one.
|
||||||
//if a custom is used, then the servefilename will be different from the resolved filename.
|
//if a custom is used, then the serverFilename will be different from the resolved filename.
|
||||||
string finalName = serverFilename == resolvedFilename ? serverFilename : resolvedFilename;
|
string finalName = serverFilename == resolvedFilename ? serverFilename : resolvedFilename;
|
||||||
await dbService.UpdateMedia(folder, media_id, api_type, folder + path, finalName + extension, fileSizeInBytes,
|
await dbService.UpdateMedia(folder, mediaId, apiType, folder + path, finalName + extension, fileSizeInBytes,
|
||||||
true, lastModified);
|
true, lastModified);
|
||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
@ -745,16 +716,16 @@ public class DownloadService(
|
|||||||
/// Handles media that has been previously downloaded and updates the task accordingly.
|
/// Handles media that has been previously downloaded and updates the task accordingly.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="folder"></param>
|
/// <param name="folder"></param>
|
||||||
/// <param name="media_id"></param>
|
/// <param name="mediaId"></param>
|
||||||
/// <param name="api_type"></param>
|
/// <param name="apiType"></param>
|
||||||
/// <param name="progressReporter"></param>
|
/// <param name="progressReporter"></param>
|
||||||
/// <returns>A boolean indicating whether the media is newly downloaded or not.</returns>
|
/// <returns>A boolean indicating whether the media is newly downloaded or not.</returns>
|
||||||
private async Task<bool> HandlePreviouslyDownloadedMediaAsync(string folder, long media_id, string api_type,
|
private async Task<bool> HandlePreviouslyDownloadedMediaAsync(string folder, long mediaId, string apiType,
|
||||||
IProgressReporter progressReporter)
|
IProgressReporter progressReporter)
|
||||||
{
|
{
|
||||||
if (configService.CurrentConfig.ShowScrapeSize)
|
if (configService.CurrentConfig.ShowScrapeSize)
|
||||||
{
|
{
|
||||||
long size = await dbService.GetStoredFileSize(folder, media_id, api_type);
|
long size = await dbService.GetStoredFileSize(folder, mediaId, apiType);
|
||||||
progressReporter.ReportProgress(size);
|
progressReporter.ReportProgress(size);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@ -791,11 +762,12 @@ public class DownloadService(
|
|||||||
Stream body = await response.Content.ReadAsStreamAsync();
|
Stream body = await response.Content.ReadAsStreamAsync();
|
||||||
|
|
||||||
// Wrap the body stream with the ThrottledStream to limit read rate.
|
// Wrap the body stream with the ThrottledStream to limit read rate.
|
||||||
using (ThrottledStream throttledStream = new(body,
|
await using (ThrottledStream throttledStream = new(body,
|
||||||
configService.CurrentConfig.DownloadLimitInMbPerSec * 1_000_000,
|
configService.CurrentConfig.DownloadLimitInMbPerSec * 1_000_000,
|
||||||
configService.CurrentConfig.LimitDownloadRate))
|
configService.CurrentConfig.LimitDownloadRate))
|
||||||
{
|
{
|
||||||
using FileStream fileStream = new(destinationPath, FileMode.Create, FileAccess.Write, FileShare.None, 16384,
|
await using FileStream fileStream = new(destinationPath, FileMode.Create, FileAccess.Write, FileShare.None,
|
||||||
|
16384,
|
||||||
true);
|
true);
|
||||||
byte[] buffer = new byte[16384];
|
byte[] buffer = new byte[16384];
|
||||||
int read;
|
int read;
|
||||||
@ -854,7 +826,7 @@ public class DownloadService(
|
|||||||
return totalFileSize;
|
return totalFileSize;
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<bool> DownloadMedia(string url, string folder, long media_id, string api_type,
|
public async Task<bool> DownloadMedia(string url, string folder, long mediaId, string apiType,
|
||||||
IProgressReporter progressReporter, string path,
|
IProgressReporter progressReporter, string path,
|
||||||
string? filenameFormat, object? postInfo, object? postMedia,
|
string? filenameFormat, object? postInfo, object? postMedia,
|
||||||
object? author, Dictionary<string, long> users)
|
object? author, Dictionary<string, long> users)
|
||||||
@ -864,12 +836,12 @@ public class DownloadService(
|
|||||||
string resolvedFilename = await GenerateCustomFileName(filename, filenameFormat, postInfo, postMedia, author,
|
string resolvedFilename = await GenerateCustomFileName(filename, filenameFormat, postInfo, postMedia, author,
|
||||||
folder.Split("/")[^1], users, fileNameService, CustomFileNameOption.ReturnOriginal);
|
folder.Split("/")[^1], users, fileNameService, CustomFileNameOption.ReturnOriginal);
|
||||||
|
|
||||||
return await CreateDirectoriesAndDownloadMedia(path, url, folder, media_id, api_type, progressReporter,
|
return await CreateDirectoriesAndDownloadMedia(path, url, folder, mediaId, apiType, progressReporter,
|
||||||
filename, resolvedFilename);
|
filename, resolvedFilename);
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<bool> DownloadDRMVideo(string policy, string signature, string kvp, string url,
|
public async Task<bool> DownloadDrmVideo(string policy, string signature, string kvp, string url,
|
||||||
string decryptionKey, string folder, DateTime lastModified, long media_id, string api_type,
|
string decryptionKey, string folder, DateTime lastModified, long mediaId, string apiType,
|
||||||
IProgressReporter progressReporter, string path,
|
IProgressReporter progressReporter, string path,
|
||||||
string? filenameFormat, object? postInfo, object? postMedia,
|
string? filenameFormat, object? postInfo, object? postMedia,
|
||||||
object? author, Dictionary<string, long> users)
|
object? author, Dictionary<string, long> users)
|
||||||
@ -902,14 +874,14 @@ public class DownloadService(
|
|||||||
string customFileName = await GenerateCustomFileName(filename, filenameFormat, postInfo, postMedia, author,
|
string customFileName = await GenerateCustomFileName(filename, filenameFormat, postInfo, postMedia, author,
|
||||||
folder.Split("/")[^1], users, fileNameService, CustomFileNameOption.ReturnEmpty);
|
folder.Split("/")[^1], users, fileNameService, CustomFileNameOption.ReturnEmpty);
|
||||||
|
|
||||||
if (!await dbService.CheckDownloaded(folder, media_id, api_type))
|
if (!await dbService.CheckDownloaded(folder, mediaId, apiType))
|
||||||
{
|
{
|
||||||
if (!string.IsNullOrEmpty(customFileName)
|
if (!string.IsNullOrEmpty(customFileName)
|
||||||
? !File.Exists(folder + path + "/" + customFileName + ".mp4")
|
? !File.Exists(folder + path + "/" + customFileName + ".mp4")
|
||||||
: !File.Exists(folder + path + "/" + filename + "_source.mp4"))
|
: !File.Exists(folder + path + "/" + filename + "_source.mp4"))
|
||||||
{
|
{
|
||||||
return await DownloadDrmMedia(authService.CurrentAuth.UserAgent, policy, signature, kvp,
|
return await DownloadDrmMedia(authService.CurrentAuth.UserAgent, policy, signature, kvp,
|
||||||
authService.CurrentAuth.Cookie, url, decryptionKey, folder, lastModified, media_id, api_type,
|
authService.CurrentAuth.Cookie, url, decryptionKey, folder, lastModified, mediaId, apiType,
|
||||||
progressReporter, customFileName, filename, path);
|
progressReporter, customFileName, filename, path);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -918,7 +890,7 @@ public class DownloadService(
|
|||||||
: folder + path + "/" + filename + "_source.mp4").Length;
|
: folder + path + "/" + filename + "_source.mp4").Length;
|
||||||
ReportProgress(progressReporter, fileSizeInBytes);
|
ReportProgress(progressReporter, fileSizeInBytes);
|
||||||
|
|
||||||
await dbService.UpdateMedia(folder, media_id, api_type, folder + path,
|
await dbService.UpdateMedia(folder, mediaId, apiType, folder + path,
|
||||||
!string.IsNullOrEmpty(customFileName) ? customFileName + ".mp4" : filename + "_source.mp4",
|
!string.IsNullOrEmpty(customFileName) ? customFileName + ".mp4" : filename + "_source.mp4",
|
||||||
fileSizeInBytes, true, lastModified);
|
fileSizeInBytes, true, lastModified);
|
||||||
}
|
}
|
||||||
@ -946,15 +918,15 @@ public class DownloadService(
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
long size = await dbService.GetStoredFileSize(folder, media_id, api_type);
|
long size = await dbService.GetStoredFileSize(folder, mediaId, apiType);
|
||||||
await dbService.UpdateMedia(folder, media_id, api_type, folder + path, customFileName + ".mp4",
|
await dbService.UpdateMedia(folder, mediaId, apiType, folder + path, customFileName + ".mp4",
|
||||||
size, true, lastModified);
|
size, true, lastModified);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (configService.CurrentConfig.ShowScrapeSize)
|
if (configService.CurrentConfig.ShowScrapeSize)
|
||||||
{
|
{
|
||||||
long size = await dbService.GetStoredFileSize(folder, media_id, api_type);
|
long size = await dbService.GetStoredFileSize(folder, mediaId, apiType);
|
||||||
progressReporter.ReportProgress(size);
|
progressReporter.ReportProgress(size);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@ -982,26 +954,17 @@ public class DownloadService(
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void ReportProgress(IProgressReporter reporter, long sizeOrCount)
|
private void ReportProgress(IProgressReporter reporter, long sizeOrCount) =>
|
||||||
{
|
reporter.ReportProgress(configService.CurrentConfig.ShowScrapeSize ? sizeOrCount : 1);
|
||||||
if (configService.CurrentConfig.ShowScrapeSize)
|
|
||||||
{
|
|
||||||
reporter.ReportProgress(sizeOrCount);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
reporter.ReportProgress(1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public async Task<(string decryptionKey, DateTime lastModified)?> GetDecryptionInfo(
|
public async Task<(string decryptionKey, DateTime lastModified)?> GetDecryptionInfo(
|
||||||
string mpdUrl, string policy, string signature, string kvp,
|
string mpdUrl, string policy, string signature, string kvp,
|
||||||
string mediaId, string contentId, string drmType,
|
string mediaId, string contentId, string drmType,
|
||||||
bool clientIdBlobMissing, bool devicePrivateKeyMissing)
|
bool clientIdBlobMissing, bool devicePrivateKeyMissing)
|
||||||
{
|
{
|
||||||
string pssh = await apiService.GetDRMMPDPSSH(mpdUrl, policy, signature, kvp);
|
string pssh = await apiService.GetDrmMpdPssh(mpdUrl, policy, signature, kvp);
|
||||||
|
|
||||||
DateTime lastModified = await apiService.GetDRMMPDLastModified(mpdUrl, policy, signature, kvp);
|
DateTime lastModified = await apiService.GetDrmMpdLastModified(mpdUrl, policy, signature, kvp);
|
||||||
Dictionary<string, string> drmHeaders =
|
Dictionary<string, string> drmHeaders =
|
||||||
apiService.GetDynamicHeaders($"/api2/v2/users/media/{mediaId}/drm/{drmType}/{contentId}",
|
apiService.GetDynamicHeaders($"/api2/v2/users/media/{mediaId}/drm/{drmType}/{contentId}",
|
||||||
"?type=widevine");
|
"?type=widevine");
|
||||||
@ -1009,8 +972,8 @@ public class DownloadService(
|
|||||||
$"https://onlyfans.com/api2/v2/users/media/{mediaId}/drm/{drmType}/{contentId}?type=widevine";
|
$"https://onlyfans.com/api2/v2/users/media/{mediaId}/drm/{drmType}/{contentId}?type=widevine";
|
||||||
|
|
||||||
string decryptionKey = clientIdBlobMissing || devicePrivateKeyMissing
|
string decryptionKey = clientIdBlobMissing || devicePrivateKeyMissing
|
||||||
? await apiService.GetDecryptionKeyOFDL(drmHeaders, licenseUrl, pssh)
|
? await apiService.GetDecryptionKeyOfdl(drmHeaders, licenseUrl, pssh)
|
||||||
: await apiService.GetDecryptionKeyCDM(drmHeaders, licenseUrl, pssh);
|
: await apiService.GetDecryptionKeyCdm(drmHeaders, licenseUrl, pssh);
|
||||||
|
|
||||||
return (decryptionKey, lastModified);
|
return (decryptionKey, lastModified);
|
||||||
}
|
}
|
||||||
@ -1041,10 +1004,10 @@ public class DownloadService(
|
|||||||
int oldHighlightsCount = 0;
|
int oldHighlightsCount = 0;
|
||||||
int newHighlightsCount = 0;
|
int newHighlightsCount = 0;
|
||||||
|
|
||||||
foreach (KeyValuePair<long, string> highlightKVP in highlights)
|
foreach (KeyValuePair<long, string> highlightKvp in highlights)
|
||||||
{
|
{
|
||||||
bool isNew =
|
bool isNew =
|
||||||
await DownloadMedia(highlightKVP.Value, path, highlightKVP.Key, "Stories", progressReporter,
|
await DownloadMedia(highlightKvp.Value, path, highlightKvp.Key, "Stories", progressReporter,
|
||||||
"/Stories/Free", null, null, null, null, new Dictionary<string, long>());
|
"/Stories/Free", null, null, null, null, new Dictionary<string, long>());
|
||||||
if (isNew)
|
if (isNew)
|
||||||
{
|
{
|
||||||
@ -1095,9 +1058,9 @@ public class DownloadService(
|
|||||||
int oldStoriesCount = 0;
|
int oldStoriesCount = 0;
|
||||||
int newStoriesCount = 0;
|
int newStoriesCount = 0;
|
||||||
|
|
||||||
foreach (KeyValuePair<long, string> storyKVP in stories)
|
foreach (KeyValuePair<long, string> storyKvp in stories)
|
||||||
{
|
{
|
||||||
bool isNew = await DownloadMedia(storyKVP.Value, path, storyKVP.Key, "Stories", progressReporter,
|
bool isNew = await DownloadMedia(storyKvp.Value, path, storyKvp.Key, "Stories", progressReporter,
|
||||||
"/Stories/Free", null, null, null, null, new Dictionary<string, long>());
|
"/Stories/Free", null, null, null, null, new Dictionary<string, long>());
|
||||||
if (isNew)
|
if (isNew)
|
||||||
{
|
{
|
||||||
@ -1146,20 +1109,20 @@ public class DownloadService(
|
|||||||
int oldArchivedCount = 0;
|
int oldArchivedCount = 0;
|
||||||
int newArchivedCount = 0;
|
int newArchivedCount = 0;
|
||||||
|
|
||||||
foreach (KeyValuePair<long, string> archivedKVP in archived.ArchivedPosts)
|
foreach (KeyValuePair<long, string> archivedKvp in archived.ArchivedPosts)
|
||||||
{
|
{
|
||||||
bool isNew;
|
bool isNew;
|
||||||
ArchivedEntities.Medium? mediaInfo =
|
ArchivedEntities.Medium? mediaInfo =
|
||||||
archived.ArchivedPostMedia.FirstOrDefault(m => m.Id == archivedKVP.Key);
|
archived.ArchivedPostMedia.FirstOrDefault(m => m.Id == archivedKvp.Key);
|
||||||
ArchivedEntities.ListItem? postInfo = mediaInfo == null
|
ArchivedEntities.ListItem? postInfo = mediaInfo == null
|
||||||
? null
|
? null
|
||||||
: archived.ArchivedPostObjects.FirstOrDefault(p => p.Media?.Contains(mediaInfo) == true);
|
: archived.ArchivedPostObjects.FirstOrDefault(p => p.Media?.Contains(mediaInfo) == true);
|
||||||
string filenameFormat =
|
string filenameFormat =
|
||||||
configService.CurrentConfig.GetCreatorFileNameFormatConfig(username).PostFileNameFormat ?? "";
|
configService.CurrentConfig.GetCreatorFileNameFormatConfig(username).PostFileNameFormat ?? "";
|
||||||
|
|
||||||
if (archivedKVP.Value.Contains("cdn3.onlyfans.com/dash/files"))
|
if (archivedKvp.Value.Contains("cdn3.onlyfans.com/dash/files"))
|
||||||
{
|
{
|
||||||
string[] parsed = archivedKVP.Value.Split(',');
|
string[] parsed = archivedKvp.Value.Split(',');
|
||||||
(string decryptionKey, DateTime lastModified)? drmInfo = await GetDecryptionInfo(parsed[0], parsed[1],
|
(string decryptionKey, DateTime lastModified)? drmInfo = await GetDecryptionInfo(parsed[0], parsed[1],
|
||||||
parsed[2], parsed[3],
|
parsed[2], parsed[3],
|
||||||
parsed[4], parsed[5], "post", clientIdBlobMissing, devicePrivateKeyMissing);
|
parsed[4], parsed[5], "post", clientIdBlobMissing, devicePrivateKeyMissing);
|
||||||
@ -1168,14 +1131,14 @@ public class DownloadService(
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
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, archivedKVP.Key, "Posts",
|
drmInfo.Value.decryptionKey, path, drmInfo.Value.lastModified, archivedKvp.Key, "Posts",
|
||||||
progressReporter, "/Archived/Posts/Free/Videos", filenameFormat,
|
progressReporter, "/Archived/Posts/Free/Videos", filenameFormat,
|
||||||
postInfo, mediaInfo, postInfo?.Author, users);
|
postInfo, mediaInfo, postInfo?.Author, users);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
isNew = await DownloadMedia(archivedKVP.Value, path, archivedKVP.Key, "Posts", progressReporter,
|
isNew = await DownloadMedia(archivedKvp.Value, path, archivedKvp.Key, "Posts", progressReporter,
|
||||||
"/Archived/Posts/Free", filenameFormat, postInfo, mediaInfo, postInfo?.Author, users);
|
"/Archived/Posts/Free", filenameFormat, postInfo, mediaInfo, postInfo?.Author, users);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1226,12 +1189,12 @@ public class DownloadService(
|
|||||||
int oldMessagesCount = 0;
|
int oldMessagesCount = 0;
|
||||||
int newMessagesCount = 0;
|
int newMessagesCount = 0;
|
||||||
|
|
||||||
foreach (KeyValuePair<long, string> messageKVP in messages.Messages)
|
foreach (KeyValuePair<long, string> messageKvp in messages.Messages)
|
||||||
{
|
{
|
||||||
bool isNew;
|
bool isNew;
|
||||||
MessageEntities.Medium? mediaInfo = messages.MessageMedia.FirstOrDefault(m => m.Id == messageKVP.Key);
|
MessageEntities.Medium? mediaInfo = messages.MessageMedia.FirstOrDefault(m => m.Id == messageKvp.Key);
|
||||||
MessageEntities.ListItem? messageInfo = messages.MessageObjects.FirstOrDefault(p =>
|
MessageEntities.ListItem? messageInfo = messages.MessageObjects.FirstOrDefault(p =>
|
||||||
p.Media?.Any(m => m.Id == messageKVP.Key) == true);
|
p.Media?.Any(m => m.Id == messageKvp.Key) == true);
|
||||||
string filenameFormat =
|
string filenameFormat =
|
||||||
configService.CurrentConfig.GetCreatorFileNameFormatConfig(username).MessageFileNameFormat ?? "";
|
configService.CurrentConfig.GetCreatorFileNameFormatConfig(username).MessageFileNameFormat ?? "";
|
||||||
string messagePath = configService.CurrentConfig.FolderPerMessage && messageInfo != null &&
|
string messagePath = configService.CurrentConfig.FolderPerMessage && messageInfo != null &&
|
||||||
@ -1239,9 +1202,9 @@ public class DownloadService(
|
|||||||
? $"/Messages/Free/{messageInfo.Id} {messageInfo.CreatedAt.Value:yyyy-MM-dd HH-mm-ss}"
|
? $"/Messages/Free/{messageInfo.Id} {messageInfo.CreatedAt.Value:yyyy-MM-dd HH-mm-ss}"
|
||||||
: "/Messages/Free";
|
: "/Messages/Free";
|
||||||
|
|
||||||
if (messageKVP.Value.Contains("cdn3.onlyfans.com/dash/files"))
|
if (messageKvp.Value.Contains("cdn3.onlyfans.com/dash/files"))
|
||||||
{
|
{
|
||||||
string[] parsed = messageKVP.Value.Split(',');
|
string[] parsed = messageKvp.Value.Split(',');
|
||||||
(string decryptionKey, DateTime lastModified)? drmInfo = await GetDecryptionInfo(parsed[0], parsed[1],
|
(string decryptionKey, DateTime lastModified)? drmInfo = await GetDecryptionInfo(parsed[0], parsed[1],
|
||||||
parsed[2], parsed[3],
|
parsed[2], parsed[3],
|
||||||
parsed[4], parsed[5], "message", clientIdBlobMissing, devicePrivateKeyMissing);
|
parsed[4], parsed[5], "message", clientIdBlobMissing, devicePrivateKeyMissing);
|
||||||
@ -1250,14 +1213,14 @@ public class DownloadService(
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
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, messageKVP.Key, "Messages",
|
drmInfo.Value.decryptionKey, path, drmInfo.Value.lastModified, messageKvp.Key, "Messages",
|
||||||
progressReporter, messagePath + "/Videos", filenameFormat,
|
progressReporter, messagePath + "/Videos", filenameFormat,
|
||||||
messageInfo, mediaInfo, messageInfo?.FromUser, users);
|
messageInfo, mediaInfo, messageInfo?.FromUser, users);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
isNew = await DownloadMedia(messageKVP.Value, path, messageKVP.Key, "Messages", progressReporter,
|
isNew = await DownloadMedia(messageKvp.Value, path, messageKvp.Key, "Messages", progressReporter,
|
||||||
messagePath, filenameFormat, messageInfo, mediaInfo, messageInfo?.FromUser, users);
|
messagePath, filenameFormat, messageInfo, mediaInfo, messageInfo?.FromUser, users);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1335,7 +1298,7 @@ public class DownloadService(
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
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, messageInfo?.FromUser, users);
|
||||||
@ -1415,7 +1378,7 @@ public class DownloadService(
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
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, "Streams",
|
drmInfo.Value.decryptionKey, path, drmInfo.Value.lastModified, kvpEntry.Key, "Streams",
|
||||||
progressReporter, streamPath + "/Videos", filenameFormat,
|
progressReporter, streamPath + "/Videos", filenameFormat,
|
||||||
streamInfo, mediaInfo, streamInfo?.Author, users);
|
streamInfo, mediaInfo, streamInfo?.Author, users);
|
||||||
@ -1471,10 +1434,10 @@ public class DownloadService(
|
|||||||
|
|
||||||
int oldCount = 0, newCount = 0;
|
int oldCount = 0, newCount = 0;
|
||||||
|
|
||||||
foreach (KeyValuePair<long, string> postKVP in posts.Posts)
|
foreach (KeyValuePair<long, string> postKvp in posts.Posts)
|
||||||
{
|
{
|
||||||
bool isNew;
|
bool isNew;
|
||||||
PostEntities.Medium? mediaInfo = posts.PostMedia.FirstOrDefault(m => m.Id == postKVP.Key);
|
PostEntities.Medium? mediaInfo = posts.PostMedia.FirstOrDefault(m => m.Id == postKvp.Key);
|
||||||
PostEntities.ListItem? postInfo = mediaInfo == null
|
PostEntities.ListItem? postInfo = mediaInfo == null
|
||||||
? null
|
? null
|
||||||
: posts.PostObjects.FirstOrDefault(p => p.Media?.Contains(mediaInfo) == true);
|
: posts.PostObjects.FirstOrDefault(p => p.Media?.Contains(mediaInfo) == true);
|
||||||
@ -1484,9 +1447,9 @@ public class DownloadService(
|
|||||||
? $"/Posts/Free/{postInfo.Id} {postInfo.PostedAt:yyyy-MM-dd HH-mm-ss}"
|
? $"/Posts/Free/{postInfo.Id} {postInfo.PostedAt:yyyy-MM-dd HH-mm-ss}"
|
||||||
: "/Posts/Free";
|
: "/Posts/Free";
|
||||||
|
|
||||||
if (postKVP.Value.Contains("cdn3.onlyfans.com/dash/files"))
|
if (postKvp.Value.Contains("cdn3.onlyfans.com/dash/files"))
|
||||||
{
|
{
|
||||||
string[] parsed = postKVP.Value.Split(',');
|
string[] parsed = postKvp.Value.Split(',');
|
||||||
(string decryptionKey, DateTime lastModified)? drmInfo = await GetDecryptionInfo(parsed[0], parsed[1],
|
(string decryptionKey, DateTime lastModified)? drmInfo = await GetDecryptionInfo(parsed[0], parsed[1],
|
||||||
parsed[2], parsed[3],
|
parsed[2], parsed[3],
|
||||||
parsed[4], parsed[5], "post", clientIdBlobMissing, devicePrivateKeyMissing);
|
parsed[4], parsed[5], "post", clientIdBlobMissing, devicePrivateKeyMissing);
|
||||||
@ -1495,14 +1458,14 @@ public class DownloadService(
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
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, postPath + "/Videos", filenameFormat,
|
progressReporter, postPath + "/Videos", filenameFormat,
|
||||||
postInfo, mediaInfo, postInfo?.Author, users);
|
postInfo, mediaInfo, postInfo?.Author, users);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
isNew = await DownloadMedia(postKVP.Value, path, postKVP.Key, "Posts", progressReporter,
|
isNew = await DownloadMedia(postKvp.Value, path, postKvp.Key, "Posts", progressReporter,
|
||||||
postPath, filenameFormat, postInfo, mediaInfo, postInfo?.Author, users);
|
postPath, filenameFormat, postInfo, mediaInfo, postInfo?.Author, users);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1551,13 +1514,13 @@ public class DownloadService(
|
|||||||
|
|
||||||
int oldCount = 0, newCount = 0;
|
int oldCount = 0, newCount = 0;
|
||||||
|
|
||||||
foreach (KeyValuePair<long, string> postKVP in purchasedPosts.PaidPosts)
|
foreach (KeyValuePair<long, string> postKvp in purchasedPosts.PaidPosts)
|
||||||
{
|
{
|
||||||
bool isNew;
|
bool isNew;
|
||||||
MessageEntities.Medium? mediaInfo =
|
MessageEntities.Medium? mediaInfo =
|
||||||
purchasedPosts.PaidPostMedia.FirstOrDefault(m => m.Id == postKVP.Key);
|
purchasedPosts.PaidPostMedia.FirstOrDefault(m => m.Id == postKvp.Key);
|
||||||
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).PostFileNameFormat ?? "";
|
||||||
string paidPostPath = configService.CurrentConfig.FolderPerPaidPost && postInfo != null &&
|
string paidPostPath = configService.CurrentConfig.FolderPerPaidPost && postInfo != null &&
|
||||||
@ -1565,9 +1528,9 @@ public class DownloadService(
|
|||||||
? $"/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";
|
||||||
|
|
||||||
if (postKVP.Value.Contains("cdn3.onlyfans.com/dash/files"))
|
if (postKvp.Value.Contains("cdn3.onlyfans.com/dash/files"))
|
||||||
{
|
{
|
||||||
string[] parsed = postKVP.Value.Split(',');
|
string[] parsed = postKvp.Value.Split(',');
|
||||||
(string decryptionKey, DateTime lastModified)? drmInfo = await GetDecryptionInfo(parsed[0], parsed[1],
|
(string decryptionKey, DateTime lastModified)? drmInfo = await GetDecryptionInfo(parsed[0], parsed[1],
|
||||||
parsed[2], parsed[3],
|
parsed[2], parsed[3],
|
||||||
parsed[4], parsed[5], "post", clientIdBlobMissing, devicePrivateKeyMissing);
|
parsed[4], parsed[5], "post", clientIdBlobMissing, devicePrivateKeyMissing);
|
||||||
@ -1576,14 +1539,14 @@ public class DownloadService(
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
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, postInfo?.FromUser, 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, postInfo?.FromUser, users);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1622,14 +1585,14 @@ public class DownloadService(
|
|||||||
|
|
||||||
int oldCount = 0, newCount = 0;
|
int oldCount = 0, newCount = 0;
|
||||||
|
|
||||||
foreach (KeyValuePair<long, string> purchasedPostKVP in purchasedPosts.PaidPosts)
|
foreach (KeyValuePair<long, string> purchasedPostKvp in purchasedPosts.PaidPosts)
|
||||||
{
|
{
|
||||||
bool isNew;
|
bool isNew;
|
||||||
MessageEntities.Medium? mediaInfo =
|
MessageEntities.Medium? mediaInfo =
|
||||||
purchasedPosts?.PaidPostMedia?.FirstOrDefault(m => m.Id == purchasedPostKVP.Key);
|
purchasedPosts?.PaidPostMedia?.FirstOrDefault(m => m.Id == purchasedPostKvp.Key);
|
||||||
PurchasedEntities.ListItem? postInfo = mediaInfo != null
|
PurchasedEntities.ListItem? postInfo = mediaInfo != null
|
||||||
? purchasedPosts?.PaidPostObjects?.FirstOrDefault(p =>
|
? purchasedPosts?.PaidPostObjects?.FirstOrDefault(p =>
|
||||||
p.Media?.Any(m => m.Id == purchasedPostKVP.Key) == true)
|
p.Media?.Any(m => m.Id == purchasedPostKvp.Key) == true)
|
||||||
: null;
|
: null;
|
||||||
string filenameFormat = configService.CurrentConfig.GetCreatorFileNameFormatConfig(username)
|
string filenameFormat = configService.CurrentConfig.GetCreatorFileNameFormatConfig(username)
|
||||||
.PaidPostFileNameFormat ?? "";
|
.PaidPostFileNameFormat ?? "";
|
||||||
@ -1638,9 +1601,9 @@ public class DownloadService(
|
|||||||
? $"/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";
|
||||||
|
|
||||||
if (purchasedPostKVP.Value.Contains("cdn3.onlyfans.com/dash/files"))
|
if (purchasedPostKvp.Value.Contains("cdn3.onlyfans.com/dash/files"))
|
||||||
{
|
{
|
||||||
string[] parsed = purchasedPostKVP.Value.Split(',');
|
string[] parsed = purchasedPostKvp.Value.Split(',');
|
||||||
(string decryptionKey, DateTime lastModified)? drmInfo =
|
(string decryptionKey, DateTime lastModified)? drmInfo =
|
||||||
await GetDecryptionInfo(parsed[0], parsed[1], parsed[2], parsed[3],
|
await GetDecryptionInfo(parsed[0], parsed[1], parsed[2], parsed[3],
|
||||||
parsed[4], parsed[5], "post", clientIdBlobMissing, devicePrivateKeyMissing);
|
parsed[4], parsed[5], "post", clientIdBlobMissing, devicePrivateKeyMissing);
|
||||||
@ -1649,15 +1612,15 @@ public class DownloadService(
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
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, postInfo?.FromUser, 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, postInfo?.FromUser, users);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1696,14 +1659,14 @@ public class DownloadService(
|
|||||||
|
|
||||||
int oldCount = 0, newCount = 0;
|
int oldCount = 0, newCount = 0;
|
||||||
|
|
||||||
foreach (KeyValuePair<long, string> paidMessageKVP in paidMessageCollection.PaidMessages)
|
foreach (KeyValuePair<long, string> paidMessageKvp in paidMessageCollection.PaidMessages)
|
||||||
{
|
{
|
||||||
bool isNew;
|
bool isNew;
|
||||||
MessageEntities.Medium? mediaInfo =
|
MessageEntities.Medium? mediaInfo =
|
||||||
paidMessageCollection.PaidMessageMedia.FirstOrDefault(m => m.Id == paidMessageKVP.Key);
|
paidMessageCollection.PaidMessageMedia.FirstOrDefault(m => m.Id == paidMessageKvp.Key);
|
||||||
PurchasedEntities.ListItem? messageInfo =
|
PurchasedEntities.ListItem? messageInfo =
|
||||||
paidMessageCollection.PaidMessageObjects.FirstOrDefault(p =>
|
paidMessageCollection.PaidMessageObjects.FirstOrDefault(p =>
|
||||||
p.Media?.Any(m => m.Id == paidMessageKVP.Key) == true);
|
p.Media?.Any(m => m.Id == paidMessageKvp.Key) == true);
|
||||||
string filenameFormat = configService.CurrentConfig.GetCreatorFileNameFormatConfig(username)
|
string filenameFormat = configService.CurrentConfig.GetCreatorFileNameFormatConfig(username)
|
||||||
.PaidMessageFileNameFormat ?? "";
|
.PaidMessageFileNameFormat ?? "";
|
||||||
string paidMsgPath = configService.CurrentConfig.FolderPerPaidMessage && messageInfo != null &&
|
string paidMsgPath = configService.CurrentConfig.FolderPerPaidMessage && messageInfo != null &&
|
||||||
@ -1711,9 +1674,9 @@ public class DownloadService(
|
|||||||
? $"/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";
|
||||||
|
|
||||||
if (paidMessageKVP.Value.Contains("cdn3.onlyfans.com/dash/files"))
|
if (paidMessageKvp.Value.Contains("cdn3.onlyfans.com/dash/files"))
|
||||||
{
|
{
|
||||||
string[] parsed = paidMessageKVP.Value.Split(',');
|
string[] parsed = paidMessageKvp.Value.Split(',');
|
||||||
(string decryptionKey, DateTime lastModified)? drmInfo =
|
(string decryptionKey, DateTime lastModified)? drmInfo =
|
||||||
await GetDecryptionInfo(parsed[0], parsed[1], parsed[2], parsed[3],
|
await GetDecryptionInfo(parsed[0], parsed[1], parsed[2], parsed[3],
|
||||||
parsed[4], parsed[5], "message", clientIdBlobMissing, devicePrivateKeyMissing);
|
parsed[4], parsed[5], "message", clientIdBlobMissing, devicePrivateKeyMissing);
|
||||||
@ -1722,15 +1685,15 @@ public class DownloadService(
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
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, messageInfo?.FromUser, 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, messageInfo?.FromUser, users);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1769,9 +1732,9 @@ public class DownloadService(
|
|||||||
|
|
||||||
int oldCount = 0, newCount = 0;
|
int oldCount = 0, newCount = 0;
|
||||||
|
|
||||||
foreach (KeyValuePair<long, string> postKVP in post.SinglePosts)
|
foreach (KeyValuePair<long, string> postKvp in post.SinglePosts)
|
||||||
{
|
{
|
||||||
PostEntities.Medium? mediaInfo = post.SinglePostMedia.FirstOrDefault(m => m.Id == postKVP.Key);
|
PostEntities.Medium? mediaInfo = post.SinglePostMedia.FirstOrDefault(m => m.Id == postKvp.Key);
|
||||||
PostEntities.SinglePost? postInfo = mediaInfo == null
|
PostEntities.SinglePost? postInfo = mediaInfo == null
|
||||||
? null
|
? null
|
||||||
: post.SinglePostObjects.FirstOrDefault(p => p.Media?.Contains(mediaInfo) == true);
|
: post.SinglePostObjects.FirstOrDefault(p => p.Media?.Contains(mediaInfo) == true);
|
||||||
@ -1782,9 +1745,9 @@ public class DownloadService(
|
|||||||
: "/Posts/Free";
|
: "/Posts/Free";
|
||||||
|
|
||||||
bool isNew;
|
bool isNew;
|
||||||
if (postKVP.Value.Contains("cdn3.onlyfans.com/dash/files"))
|
if (postKvp.Value.Contains("cdn3.onlyfans.com/dash/files"))
|
||||||
{
|
{
|
||||||
string[] parsed = postKVP.Value.Split(',');
|
string[] parsed = postKvp.Value.Split(',');
|
||||||
(string decryptionKey, DateTime lastModified)? drmInfo =
|
(string decryptionKey, DateTime lastModified)? drmInfo =
|
||||||
await GetDecryptionInfo(parsed[0], parsed[1], parsed[2], parsed[3],
|
await GetDecryptionInfo(parsed[0], parsed[1], parsed[2], parsed[3],
|
||||||
parsed[4], parsed[5], "post", clientIdBlobMissing, devicePrivateKeyMissing);
|
parsed[4], parsed[5], "post", clientIdBlobMissing, devicePrivateKeyMissing);
|
||||||
@ -1793,8 +1756,8 @@ public class DownloadService(
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
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, postPath + "/Videos", filenameFormat,
|
progressReporter, postPath + "/Videos", filenameFormat,
|
||||||
postInfo, mediaInfo, postInfo?.Author, users);
|
postInfo, mediaInfo, postInfo?.Author, users);
|
||||||
}
|
}
|
||||||
@ -1802,8 +1765,8 @@ public class DownloadService(
|
|||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
isNew = await DownloadMedia(postKVP.Value, path,
|
isNew = await DownloadMedia(postKvp.Value, path,
|
||||||
postKVP.Key, "Posts", progressReporter,
|
postKvp.Key, "Posts", progressReporter,
|
||||||
postPath, filenameFormat, postInfo, mediaInfo, postInfo?.Author, users);
|
postPath, filenameFormat, postInfo, mediaInfo, postInfo?.Author, users);
|
||||||
}
|
}
|
||||||
catch
|
catch
|
||||||
@ -1845,14 +1808,14 @@ public class DownloadService(
|
|||||||
// Download preview messages
|
// Download preview messages
|
||||||
if (singlePaidMessageCollection.PreviewSingleMessages.Count > 0)
|
if (singlePaidMessageCollection.PreviewSingleMessages.Count > 0)
|
||||||
{
|
{
|
||||||
foreach (KeyValuePair<long, string> paidMessageKVP in singlePaidMessageCollection.PreviewSingleMessages)
|
foreach (KeyValuePair<long, string> paidMessageKvp in singlePaidMessageCollection.PreviewSingleMessages)
|
||||||
{
|
{
|
||||||
MessageEntities.Medium? mediaInfo =
|
MessageEntities.Medium? mediaInfo =
|
||||||
singlePaidMessageCollection.PreviewSingleMessageMedia.FirstOrDefault(m =>
|
singlePaidMessageCollection.PreviewSingleMessageMedia.FirstOrDefault(m =>
|
||||||
m.Id == paidMessageKVP.Key);
|
m.Id == paidMessageKvp.Key);
|
||||||
MessageEntities.SingleMessage? messageInfo =
|
MessageEntities.SingleMessage? messageInfo =
|
||||||
singlePaidMessageCollection.SingleMessageObjects.FirstOrDefault(p =>
|
singlePaidMessageCollection.SingleMessageObjects.FirstOrDefault(p =>
|
||||||
p.Media?.Any(m => m.Id == paidMessageKVP.Key) == true);
|
p.Media?.Any(m => m.Id == paidMessageKvp.Key) == true);
|
||||||
string filenameFormat = configService.CurrentConfig.GetCreatorFileNameFormatConfig(username)
|
string filenameFormat = configService.CurrentConfig.GetCreatorFileNameFormatConfig(username)
|
||||||
.PaidMessageFileNameFormat ?? "";
|
.PaidMessageFileNameFormat ?? "";
|
||||||
string previewMsgPath = configService.CurrentConfig.FolderPerMessage && messageInfo != null &&
|
string previewMsgPath = configService.CurrentConfig.FolderPerMessage && messageInfo != null &&
|
||||||
@ -1861,9 +1824,9 @@ public class DownloadService(
|
|||||||
: "/Messages/Free";
|
: "/Messages/Free";
|
||||||
|
|
||||||
bool isNew;
|
bool isNew;
|
||||||
if (paidMessageKVP.Value.Contains("cdn3.onlyfans.com/dash/files"))
|
if (paidMessageKvp.Value.Contains("cdn3.onlyfans.com/dash/files"))
|
||||||
{
|
{
|
||||||
string[] parsed = paidMessageKVP.Value.Split(',');
|
string[] parsed = paidMessageKvp.Value.Split(',');
|
||||||
(string decryptionKey, DateTime lastModified)? drmInfo =
|
(string decryptionKey, DateTime lastModified)? drmInfo =
|
||||||
await GetDecryptionInfo(parsed[0], parsed[1], parsed[2], parsed[3],
|
await GetDecryptionInfo(parsed[0], parsed[1], parsed[2], parsed[3],
|
||||||
parsed[4], parsed[5], "message", clientIdBlobMissing, devicePrivateKeyMissing);
|
parsed[4], parsed[5], "message", clientIdBlobMissing, devicePrivateKeyMissing);
|
||||||
@ -1872,15 +1835,15 @@ public class DownloadService(
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
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, previewMsgPath + "/Videos", filenameFormat,
|
"Messages", progressReporter, previewMsgPath + "/Videos", filenameFormat,
|
||||||
messageInfo, mediaInfo, messageInfo?.FromUser, users);
|
messageInfo, mediaInfo, messageInfo?.FromUser, users);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
isNew = await DownloadMedia(paidMessageKVP.Value, path,
|
isNew = await DownloadMedia(paidMessageKvp.Value, path,
|
||||||
paidMessageKVP.Key, "Messages", progressReporter,
|
paidMessageKvp.Key, "Messages", progressReporter,
|
||||||
previewMsgPath, filenameFormat, messageInfo, mediaInfo, messageInfo?.FromUser, users);
|
previewMsgPath, filenameFormat, messageInfo, mediaInfo, messageInfo?.FromUser, users);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1898,14 +1861,14 @@ public class DownloadService(
|
|||||||
// Download actual paid messages
|
// Download actual paid messages
|
||||||
if (singlePaidMessageCollection.SingleMessages.Count > 0)
|
if (singlePaidMessageCollection.SingleMessages.Count > 0)
|
||||||
{
|
{
|
||||||
foreach (KeyValuePair<long, string> paidMessageKVP in singlePaidMessageCollection.SingleMessages)
|
foreach (KeyValuePair<long, string> paidMessageKvp in singlePaidMessageCollection.SingleMessages)
|
||||||
{
|
{
|
||||||
MessageEntities.Medium? mediaInfo =
|
MessageEntities.Medium? mediaInfo =
|
||||||
singlePaidMessageCollection.SingleMessageMedia.FirstOrDefault(m =>
|
singlePaidMessageCollection.SingleMessageMedia.FirstOrDefault(m =>
|
||||||
m.Id == paidMessageKVP.Key);
|
m.Id == paidMessageKvp.Key);
|
||||||
MessageEntities.SingleMessage? messageInfo =
|
MessageEntities.SingleMessage? messageInfo =
|
||||||
singlePaidMessageCollection.SingleMessageObjects.FirstOrDefault(p =>
|
singlePaidMessageCollection.SingleMessageObjects.FirstOrDefault(p =>
|
||||||
p.Media?.Any(m => m.Id == paidMessageKVP.Key) == true);
|
p.Media?.Any(m => m.Id == paidMessageKvp.Key) == true);
|
||||||
string filenameFormat = configService.CurrentConfig.GetCreatorFileNameFormatConfig(username)
|
string filenameFormat = configService.CurrentConfig.GetCreatorFileNameFormatConfig(username)
|
||||||
.PaidMessageFileNameFormat ?? "";
|
.PaidMessageFileNameFormat ?? "";
|
||||||
string singlePaidMsgPath = configService.CurrentConfig.FolderPerPaidMessage &&
|
string singlePaidMsgPath = configService.CurrentConfig.FolderPerPaidMessage &&
|
||||||
@ -1915,9 +1878,9 @@ public class DownloadService(
|
|||||||
: "/Messages/Paid";
|
: "/Messages/Paid";
|
||||||
|
|
||||||
bool isNew;
|
bool isNew;
|
||||||
if (paidMessageKVP.Value.Contains("cdn3.onlyfans.com/dash/files"))
|
if (paidMessageKvp.Value.Contains("cdn3.onlyfans.com/dash/files"))
|
||||||
{
|
{
|
||||||
string[] parsed = paidMessageKVP.Value.Split(',');
|
string[] parsed = paidMessageKvp.Value.Split(',');
|
||||||
(string decryptionKey, DateTime lastModified)? drmInfo =
|
(string decryptionKey, DateTime lastModified)? drmInfo =
|
||||||
await GetDecryptionInfo(parsed[0], parsed[1], parsed[2], parsed[3],
|
await GetDecryptionInfo(parsed[0], parsed[1], parsed[2], parsed[3],
|
||||||
parsed[4], parsed[5], "message", clientIdBlobMissing, devicePrivateKeyMissing);
|
parsed[4], parsed[5], "message", clientIdBlobMissing, devicePrivateKeyMissing);
|
||||||
@ -1926,15 +1889,15 @@ public class DownloadService(
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
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, singlePaidMsgPath + "/Videos", filenameFormat,
|
"Messages", progressReporter, singlePaidMsgPath + "/Videos", filenameFormat,
|
||||||
messageInfo, mediaInfo, messageInfo?.FromUser, users);
|
messageInfo, mediaInfo, messageInfo?.FromUser, users);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
isNew = await DownloadMedia(paidMessageKVP.Value, path,
|
isNew = await DownloadMedia(paidMessageKvp.Value, path,
|
||||||
paidMessageKVP.Key, "Messages", progressReporter,
|
paidMessageKvp.Key, "Messages", progressReporter,
|
||||||
singlePaidMsgPath, filenameFormat, messageInfo, mediaInfo, messageInfo?.FromUser, users);
|
singlePaidMsgPath, filenameFormat, messageInfo, mediaInfo, messageInfo?.FromUser, users);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -27,7 +27,7 @@ public class FileNameService(IAuthService authService) : IFileNameService
|
|||||||
|
|
||||||
if (fileProperty != null && drmProperty != null && propertyName == "mediaCreatedAt")
|
if (fileProperty != null && drmProperty != null && propertyName == "mediaCreatedAt")
|
||||||
{
|
{
|
||||||
string? mpdurl = GetNestedPropertyValue(media, "Files.Drm.Manifest.Dash") as string;
|
string? mpdUrl = GetNestedPropertyValue(media, "Files.Drm.Manifest.Dash") as string;
|
||||||
string? policy =
|
string? policy =
|
||||||
GetNestedPropertyValue(media, "Files.Drm.Signature.Dash.CloudFrontPolicy") as string;
|
GetNestedPropertyValue(media, "Files.Drm.Signature.Dash.CloudFrontPolicy") as string;
|
||||||
string? signature =
|
string? signature =
|
||||||
@ -35,7 +35,7 @@ public class FileNameService(IAuthService authService) : IFileNameService
|
|||||||
string? kvp =
|
string? kvp =
|
||||||
GetNestedPropertyValue(media, "Files.Drm.Signature.Dash.CloudFrontKeyPairId") as string;
|
GetNestedPropertyValue(media, "Files.Drm.Signature.Dash.CloudFrontKeyPairId") as string;
|
||||||
|
|
||||||
if (string.IsNullOrEmpty(mpdurl) || string.IsNullOrEmpty(policy) ||
|
if (string.IsNullOrEmpty(mpdUrl) || string.IsNullOrEmpty(policy) ||
|
||||||
string.IsNullOrEmpty(signature) || string.IsNullOrEmpty(kvp) ||
|
string.IsNullOrEmpty(signature) || string.IsNullOrEmpty(kvp) ||
|
||||||
authService.CurrentAuth == null)
|
authService.CurrentAuth == null)
|
||||||
{
|
{
|
||||||
@ -43,7 +43,7 @@ public class FileNameService(IAuthService authService) : IFileNameService
|
|||||||
}
|
}
|
||||||
|
|
||||||
DateTime lastModified =
|
DateTime lastModified =
|
||||||
await DownloadService.GetDRMVideoLastModified(string.Join(",", mpdurl, policy, signature, kvp),
|
await DownloadService.GetDrmVideoLastModified(string.Join(",", mpdUrl, policy, signature, kvp),
|
||||||
authService.CurrentAuth);
|
authService.CurrentAuth);
|
||||||
values.Add(propertyName, lastModified.ToString("yyyy-MM-dd"));
|
values.Add(propertyName, lastModified.ToString("yyyy-MM-dd"));
|
||||||
continue;
|
continue;
|
||||||
|
|||||||
@ -9,27 +9,31 @@ using UserEntities = OF_DL.Models.Entities.Users;
|
|||||||
|
|
||||||
namespace OF_DL.Services;
|
namespace OF_DL.Services;
|
||||||
|
|
||||||
public interface IAPIService
|
public interface IApiService
|
||||||
{
|
{
|
||||||
Task<string> GetDecryptionKeyCDM(Dictionary<string, string> drmHeaders, string licenceURL, string pssh);
|
Task<string> GetDecryptionKeyCdm(Dictionary<string, string> drmHeaders, string licenceUrl, string pssh);
|
||||||
Task<DateTime> GetDRMMPDLastModified(string mpdUrl, string policy, string signature, string kvp);
|
|
||||||
Task<string> GetDRMMPDPSSH(string mpdUrl, string policy, string signature, string kvp);
|
Task<DateTime> GetDrmMpdLastModified(string mpdUrl, string policy, string signature, string kvp);
|
||||||
|
|
||||||
|
Task<string> GetDrmMpdPssh(string mpdUrl, string policy, string signature, string kvp);
|
||||||
|
|
||||||
Task<Dictionary<string, long>?> GetLists(string endpoint);
|
Task<Dictionary<string, long>?> GetLists(string endpoint);
|
||||||
|
|
||||||
Task<List<string>?> GetListUsers(string endpoint);
|
Task<List<string>?> GetListUsers(string endpoint);
|
||||||
|
|
||||||
Task<Dictionary<long, string>?> GetMedia(MediaType mediatype, string endpoint, string? username, string folder,
|
Task<Dictionary<long, string>?> GetMedia(MediaType mediaType, string endpoint, string? username, string folder,
|
||||||
List<long> paid_post_ids);
|
List<long> paidPostIds);
|
||||||
|
|
||||||
Task<PurchasedEntities.PaidPostCollection> GetPaidPosts(string endpoint, string folder, string username,
|
Task<PurchasedEntities.PaidPostCollection> GetPaidPosts(string endpoint, string folder, string username,
|
||||||
List<long> paid_post_ids,
|
List<long> paidPostIds,
|
||||||
IStatusReporter statusReporter);
|
IStatusReporter statusReporter);
|
||||||
|
|
||||||
Task<PostEntities.PostCollection> GetPosts(string endpoint, string folder, List<long> paid_post_ids,
|
Task<PostEntities.PostCollection> GetPosts(string endpoint, string folder, List<long> paidPostIds,
|
||||||
IStatusReporter statusReporter);
|
IStatusReporter statusReporter);
|
||||||
|
|
||||||
Task<PostEntities.SinglePostCollection> GetPost(string endpoint, string folder);
|
Task<PostEntities.SinglePostCollection> GetPost(string endpoint, string folder);
|
||||||
|
|
||||||
Task<StreamEntities.StreamsCollection> GetStreams(string endpoint, string folder, List<long> paid_post_ids,
|
Task<StreamEntities.StreamsCollection> GetStreams(string endpoint, string folder, List<long> paidPostIds,
|
||||||
IStatusReporter statusReporter);
|
IStatusReporter statusReporter);
|
||||||
|
|
||||||
Task<ArchivedEntities.ArchivedCollection> GetArchived(string endpoint, string folder,
|
Task<ArchivedEntities.ArchivedCollection> GetArchived(string endpoint, string folder,
|
||||||
@ -41,15 +45,21 @@ public interface IAPIService
|
|||||||
IStatusReporter statusReporter);
|
IStatusReporter statusReporter);
|
||||||
|
|
||||||
Task<PurchasedEntities.SinglePaidMessageCollection> GetPaidMessage(string endpoint, string folder);
|
Task<PurchasedEntities.SinglePaidMessageCollection> GetPaidMessage(string endpoint, string folder);
|
||||||
|
|
||||||
Task<Dictionary<string, long>> GetPurchasedTabUsers(string endpoint, Dictionary<string, long> users);
|
Task<Dictionary<string, long>> GetPurchasedTabUsers(string endpoint, Dictionary<string, long> users);
|
||||||
|
|
||||||
Task<List<PurchasedEntities.PurchasedTabCollection>> GetPurchasedTab(string endpoint, string folder,
|
Task<List<PurchasedEntities.PurchasedTabCollection>> GetPurchasedTab(string endpoint, string folder,
|
||||||
Dictionary<string, long> users);
|
Dictionary<string, long> users);
|
||||||
|
|
||||||
Task<UserEntities.User?> GetUserInfo(string endpoint);
|
Task<UserEntities.User?> GetUserInfo(string endpoint);
|
||||||
|
|
||||||
Task<JObject?> GetUserInfoById(string endpoint);
|
Task<JObject?> GetUserInfoById(string endpoint);
|
||||||
|
|
||||||
Dictionary<string, string> GetDynamicHeaders(string path, string queryParam);
|
Dictionary<string, string> GetDynamicHeaders(string path, string queryParam);
|
||||||
|
|
||||||
Task<Dictionary<string, long>?> GetActiveSubscriptions(string endpoint, bool includeRestrictedSubscriptions);
|
Task<Dictionary<string, long>?> GetActiveSubscriptions(string endpoint, bool includeRestrictedSubscriptions);
|
||||||
|
|
||||||
Task<Dictionary<string, long>?> GetExpiredSubscriptions(string endpoint, bool includeRestrictedSubscriptions);
|
Task<Dictionary<string, long>?> GetExpiredSubscriptions(string endpoint, bool includeRestrictedSubscriptions);
|
||||||
Task<string> GetDecryptionKeyOFDL(Dictionary<string, string> drmHeaders, string licenceURL, string pssh);
|
|
||||||
|
Task<string> GetDecryptionKeyOfdl(Dictionary<string, string> drmHeaders, string licenceUrl, string pssh);
|
||||||
}
|
}
|
||||||
@ -1,27 +0,0 @@
|
|||||||
namespace OF_DL.Services;
|
|
||||||
|
|
||||||
public interface IDBService
|
|
||||||
{
|
|
||||||
Task AddMessage(string folder, long post_id, string message_text, string price, bool is_paid, bool is_archived,
|
|
||||||
DateTime created_at, long user_id);
|
|
||||||
|
|
||||||
Task AddPost(string folder, long post_id, string message_text, string price, bool is_paid, bool is_archived,
|
|
||||||
DateTime created_at);
|
|
||||||
|
|
||||||
Task AddStory(string folder, long post_id, string message_text, string price, bool is_paid, bool is_archived,
|
|
||||||
DateTime created_at);
|
|
||||||
|
|
||||||
Task CreateDB(string folder);
|
|
||||||
Task CreateUsersDB(Dictionary<string, long> users);
|
|
||||||
Task CheckUsername(KeyValuePair<string, long> user, string path);
|
|
||||||
|
|
||||||
Task AddMedia(string folder, long media_id, long post_id, string link, string? directory, string? filename,
|
|
||||||
long? size, string api_type, string media_type, bool preview, bool downloaded, DateTime? created_at);
|
|
||||||
|
|
||||||
Task UpdateMedia(string folder, long media_id, string api_type, string directory, string filename, long size,
|
|
||||||
bool downloaded, DateTime created_at);
|
|
||||||
|
|
||||||
Task<long> GetStoredFileSize(string folder, long media_id, string api_type);
|
|
||||||
Task<bool> CheckDownloaded(string folder, long media_id, string api_type);
|
|
||||||
Task<DateTime?> GetMostRecentPostDate(string folder);
|
|
||||||
}
|
|
||||||
31
OF DL.Core/Services/IDbService.cs
Normal file
31
OF DL.Core/Services/IDbService.cs
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
namespace OF_DL.Services;
|
||||||
|
|
||||||
|
public interface IDbService
|
||||||
|
{
|
||||||
|
Task AddMessage(string folder, long postId, string messageText, string price, bool isPaid, bool isArchived,
|
||||||
|
DateTime createdAt, long userId);
|
||||||
|
|
||||||
|
Task AddPost(string folder, long postId, string messageText, string price, bool isPaid, bool isArchived,
|
||||||
|
DateTime createdAt);
|
||||||
|
|
||||||
|
Task AddStory(string folder, long postId, string messageText, string price, bool isPaid, bool isArchived,
|
||||||
|
DateTime createdAt);
|
||||||
|
|
||||||
|
Task CreateDb(string folder);
|
||||||
|
|
||||||
|
Task CreateUsersDb(Dictionary<string, long> users);
|
||||||
|
|
||||||
|
Task CheckUsername(KeyValuePair<string, long> user, string path);
|
||||||
|
|
||||||
|
Task AddMedia(string folder, long mediaId, long postId, string link, string? directory, string? filename,
|
||||||
|
long? size, string apiType, string mediaType, bool preview, bool downloaded, DateTime? createdAt);
|
||||||
|
|
||||||
|
Task UpdateMedia(string folder, long mediaId, string apiType, string directory, string filename, long size,
|
||||||
|
bool downloaded, DateTime createdAt);
|
||||||
|
|
||||||
|
Task<long> GetStoredFileSize(string folder, long mediaId, string apiType);
|
||||||
|
|
||||||
|
Task<bool> CheckDownloaded(string folder, long mediaId, string apiType);
|
||||||
|
|
||||||
|
Task<DateTime?> GetMostRecentPostDate(string folder);
|
||||||
|
}
|
||||||
@ -11,22 +11,22 @@ public interface IDownloadService
|
|||||||
{
|
{
|
||||||
Task<long> CalculateTotalFileSize(List<string> urls);
|
Task<long> CalculateTotalFileSize(List<string> urls);
|
||||||
|
|
||||||
Task<bool> ProcessMediaDownload(string folder, long media_id, string api_type, string url, string path,
|
Task<bool> ProcessMediaDownload(string folder, long mediaId, string apiType, string url, string path,
|
||||||
string serverFileName, string resolvedFileName, string extension, IProgressReporter progressReporter);
|
string serverFileName, string resolvedFileName, string extension, IProgressReporter progressReporter);
|
||||||
|
|
||||||
Task<bool> DownloadMedia(string url, string folder, long media_id, string api_type,
|
Task<bool> DownloadMedia(string url, string folder, long mediaId, string apiType,
|
||||||
IProgressReporter progressReporter, string path,
|
IProgressReporter progressReporter, string path,
|
||||||
string? filenameFormat, object? postInfo, object? postMedia,
|
string? filenameFormat, object? postInfo, object? postMedia,
|
||||||
object? author, Dictionary<string, long> users);
|
object? author, Dictionary<string, long> users);
|
||||||
|
|
||||||
Task<bool> DownloadDRMVideo(string policy, string signature, string kvp, string url,
|
Task<bool> DownloadDrmVideo(string policy, string signature, string kvp, string url,
|
||||||
string decryptionKey, string folder, DateTime lastModified, long media_id, string api_type,
|
string decryptionKey, string folder, DateTime lastModified, long mediaId, string apiType,
|
||||||
IProgressReporter progressReporter, string path,
|
IProgressReporter progressReporter, string path,
|
||||||
string? filenameFormat, object? postInfo, object? postMedia,
|
string? filenameFormat, object? postInfo, object? postMedia,
|
||||||
object? author, Dictionary<string, long> users);
|
object? author, Dictionary<string, long> users);
|
||||||
|
|
||||||
Task<(string decryptionKey, DateTime lastModified)?> GetDecryptionInfo(
|
Task<(string decryptionKey, DateTime lastModified)?> GetDecryptionInfo(
|
||||||
string mpdURL, string policy, string signature, string kvp,
|
string mpdUrl, string policy, string signature, string kvp,
|
||||||
string mediaId, string contentId, string drmType,
|
string mediaId, string contentId, string drmType,
|
||||||
bool clientIdBlobMissing, bool devicePrivateKeyMissing);
|
bool clientIdBlobMissing, bool devicePrivateKeyMissing);
|
||||||
|
|
||||||
|
|||||||
@ -6,6 +6,8 @@ namespace OF_DL.Services;
|
|||||||
public interface ILoggingService
|
public interface ILoggingService
|
||||||
{
|
{
|
||||||
LoggingLevelSwitch LevelSwitch { get; }
|
LoggingLevelSwitch LevelSwitch { get; }
|
||||||
|
|
||||||
void UpdateLoggingLevel(LoggingLevel newLevel);
|
void UpdateLoggingLevel(LoggingLevel newLevel);
|
||||||
|
|
||||||
LoggingLevel GetCurrentLoggingLevel();
|
LoggingLevel GetCurrentLoggingLevel();
|
||||||
}
|
}
|
||||||
|
|||||||
@ -221,7 +221,7 @@ public class StartupService(IConfigService configService, IAuthService authServi
|
|||||||
return File.Exists(path);
|
return File.Exists(path);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static string? GetFullPath(string filename)
|
private static string? GetFullPath(string filename)
|
||||||
{
|
{
|
||||||
if (File.Exists(filename))
|
if (File.Exists(filename))
|
||||||
{
|
{
|
||||||
@ -229,15 +229,7 @@ public class StartupService(IConfigService configService, IAuthService authServi
|
|||||||
}
|
}
|
||||||
|
|
||||||
string pathEnv = Environment.GetEnvironmentVariable("PATH") ?? "";
|
string pathEnv = Environment.GetEnvironmentVariable("PATH") ?? "";
|
||||||
foreach (string path in pathEnv.Split(Path.PathSeparator))
|
return pathEnv.Split(Path.PathSeparator).Select(path => Path.Combine(path, filename))
|
||||||
{
|
.FirstOrDefault(File.Exists);
|
||||||
string fullPath = Path.Combine(path, filename);
|
|
||||||
if (File.Exists(fullPath))
|
|
||||||
{
|
|
||||||
return fullPath;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return null;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -110,8 +110,8 @@ public class Program(IServiceProvider serviceProvider)
|
|||||||
services.AddSingleton(loggingService);
|
services.AddSingleton(loggingService);
|
||||||
services.AddSingleton(configService);
|
services.AddSingleton(configService);
|
||||||
services.AddSingleton<IAuthService, AuthService>();
|
services.AddSingleton<IAuthService, AuthService>();
|
||||||
services.AddSingleton<IAPIService, ApiService>();
|
services.AddSingleton<IApiService, ApiService>();
|
||||||
services.AddSingleton<IDBService, DBService>();
|
services.AddSingleton<IDbService, DbService>();
|
||||||
services.AddSingleton<IDownloadService, DownloadService>();
|
services.AddSingleton<IDownloadService, DownloadService>();
|
||||||
services.AddSingleton<IFileNameService, FileNameService>();
|
services.AddSingleton<IFileNameService, FileNameService>();
|
||||||
services.AddSingleton<IStartupService, StartupService>();
|
services.AddSingleton<IStartupService, StartupService>();
|
||||||
@ -403,8 +403,8 @@ public class Program(IServiceProvider serviceProvider)
|
|||||||
AnsiConsole.Markup($"[red]Folder for {Markup.Escape(username)} already created\n[/]");
|
AnsiConsole.Markup($"[red]Folder for {Markup.Escape(username)} already created\n[/]");
|
||||||
}
|
}
|
||||||
|
|
||||||
IDBService dbService = serviceProvider.GetRequiredService<IDBService>();
|
IDbService dbService = serviceProvider.GetRequiredService<IDbService>();
|
||||||
await dbService.CreateDB(path);
|
await dbService.CreateDb(path);
|
||||||
|
|
||||||
await orchestrationService.DownloadSinglePostAsync(username, postId, path, users,
|
await orchestrationService.DownloadSinglePostAsync(username, postId, path, users,
|
||||||
startupResult.ClientIdBlobMissing, startupResult.DevicePrivateKeyMissing, eventHandler);
|
startupResult.ClientIdBlobMissing, startupResult.DevicePrivateKeyMissing, eventHandler);
|
||||||
@ -475,8 +475,8 @@ public class Program(IServiceProvider serviceProvider)
|
|||||||
Log.Debug($"Folder for {username} already created");
|
Log.Debug($"Folder for {username} already created");
|
||||||
}
|
}
|
||||||
|
|
||||||
IDBService dbService = serviceProvider.GetRequiredService<IDBService>();
|
IDbService dbService = serviceProvider.GetRequiredService<IDbService>();
|
||||||
await dbService.CreateDB(path);
|
await dbService.CreateDb(path);
|
||||||
|
|
||||||
await orchestrationService.DownloadSinglePaidMessageAsync(username, messageId, path, users,
|
await orchestrationService.DownloadSinglePaidMessageAsync(username, messageId, path, users,
|
||||||
startupResult.ClientIdBlobMissing, startupResult.DevicePrivateKeyMissing, eventHandler);
|
startupResult.ClientIdBlobMissing, startupResult.DevicePrivateKeyMissing, eventHandler);
|
||||||
@ -488,7 +488,7 @@ public class Program(IServiceProvider serviceProvider)
|
|||||||
{
|
{
|
||||||
IConfigService configService = serviceProvider.GetRequiredService<IConfigService>();
|
IConfigService configService = serviceProvider.GetRequiredService<IConfigService>();
|
||||||
IAuthService authService = serviceProvider.GetRequiredService<IAuthService>();
|
IAuthService authService = serviceProvider.GetRequiredService<IAuthService>();
|
||||||
IAPIService apiService = serviceProvider.GetRequiredService<IAPIService>();
|
IApiService apiService = serviceProvider.GetRequiredService<IApiService>();
|
||||||
ILoggingService loggingService = serviceProvider.GetRequiredService<ILoggingService>();
|
ILoggingService loggingService = serviceProvider.GetRequiredService<ILoggingService>();
|
||||||
|
|
||||||
bool hasSelectedUsers = false;
|
bool hasSelectedUsers = false;
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user