Refactor code structure for improved readability and maintainability
This commit is contained in:
parent
b47641feaa
commit
4f488bae45
78 changed files with 3309 additions and 1570 deletions
22
dotnet/src/TwitchArchive.Core/Config/AppSettings.cs
Normal file
22
dotnet/src/TwitchArchive.Core/Config/AppSettings.cs
Normal file
|
|
@ -0,0 +1,22 @@
|
|||
using System.Text.Json.Serialization;
|
||||
|
||||
namespace TwitchArchive.Core.Config
|
||||
{
|
||||
public class AppSettings
|
||||
{
|
||||
[JsonPropertyName("streamlink_path")]
|
||||
public string? StreamlinkPath { get; set; }
|
||||
|
||||
[JsonPropertyName("ffmpeg_path")]
|
||||
public string? FfmpegPath { get; set; }
|
||||
|
||||
[JsonPropertyName("twitchdownloader_path")]
|
||||
public string? TwitchDownloaderPath { get; set; }
|
||||
|
||||
[JsonPropertyName("rclone_path")]
|
||||
public string? RclonePath { get; set; }
|
||||
|
||||
[JsonPropertyName("password_hash")]
|
||||
public string? PasswordHash { get; set; }
|
||||
}
|
||||
}
|
||||
88
dotnet/src/TwitchArchive.Core/Config/ConfigurationService.cs
Normal file
88
dotnet/src/TwitchArchive.Core/Config/ConfigurationService.cs
Normal file
|
|
@ -0,0 +1,88 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Text.Json;
|
||||
|
||||
namespace TwitchArchive.Core.Config
|
||||
{
|
||||
public class ConfigurationService : IConfigurationService
|
||||
{
|
||||
private readonly string _basePath;
|
||||
private readonly string _streamersPath;
|
||||
private readonly JsonSerializerOptions _jsonOptions = new JsonSerializerOptions { WriteIndented = true };
|
||||
|
||||
public ConfigurationService(string? basePath = null)
|
||||
{
|
||||
_basePath = basePath ?? Path.Combine(AppContext.BaseDirectory, "config");
|
||||
_streamersPath = Path.Combine(_basePath, "streamers");
|
||||
Directory.CreateDirectory(_basePath);
|
||||
Directory.CreateDirectory(_streamersPath);
|
||||
}
|
||||
|
||||
public GlobalConfig LoadGlobal()
|
||||
{
|
||||
var file = Path.Combine(_basePath, "global.json");
|
||||
if (!File.Exists(file)) return new GlobalConfig();
|
||||
var txt = File.ReadAllText(file);
|
||||
return JsonSerializer.Deserialize<GlobalConfig>(txt, _jsonOptions) ?? new GlobalConfig();
|
||||
}
|
||||
|
||||
public void SaveGlobal(GlobalConfig cfg)
|
||||
{
|
||||
var file = Path.Combine(_basePath, "global.json");
|
||||
var txt = JsonSerializer.Serialize(cfg, _jsonOptions);
|
||||
File.WriteAllText(file, txt);
|
||||
}
|
||||
|
||||
public StreamerConfig? LoadStreamer(string username)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(username)) return null;
|
||||
var file = Path.Combine(_streamersPath, username + ".json");
|
||||
if (!File.Exists(file)) return null;
|
||||
var txt = File.ReadAllText(file);
|
||||
return JsonSerializer.Deserialize<StreamerConfig>(txt, _jsonOptions);
|
||||
}
|
||||
|
||||
public void SaveStreamer(StreamerConfig cfg)
|
||||
{
|
||||
if (cfg == null) throw new ArgumentNullException(nameof(cfg));
|
||||
if (string.IsNullOrWhiteSpace(cfg.Username)) throw new ArgumentException("Username required");
|
||||
var file = Path.Combine(_streamersPath, cfg.Username + ".json");
|
||||
var txt = JsonSerializer.Serialize(cfg, _jsonOptions);
|
||||
File.WriteAllText(file, txt);
|
||||
}
|
||||
|
||||
public IEnumerable<StreamerConfig> GetAllStreamers()
|
||||
{
|
||||
if (!Directory.Exists(_streamersPath)) return Enumerable.Empty<StreamerConfig>();
|
||||
var files = Directory.EnumerateFiles(_streamersPath, "*.json");
|
||||
var list = new List<StreamerConfig>();
|
||||
foreach (var f in files)
|
||||
{
|
||||
try
|
||||
{
|
||||
var txt = File.ReadAllText(f);
|
||||
var s = JsonSerializer.Deserialize<StreamerConfig>(txt, _jsonOptions);
|
||||
if (s != null) list.Add(s);
|
||||
}
|
||||
catch { }
|
||||
}
|
||||
return list;
|
||||
}
|
||||
|
||||
public EffectiveConfig GetEffectiveConfig(string username)
|
||||
{
|
||||
var global = LoadGlobal();
|
||||
var streamer = LoadStreamer(username);
|
||||
return EffectiveConfig.Merge(global, streamer);
|
||||
}
|
||||
|
||||
public void DeleteStreamer(string username)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(username)) return;
|
||||
var file = Path.Combine(_streamersPath, username + ".json");
|
||||
try { if (File.Exists(file)) File.Delete(file); } catch { }
|
||||
}
|
||||
}
|
||||
}
|
||||
36
dotnet/src/TwitchArchive.Core/Config/EffectiveConfig.cs
Normal file
36
dotnet/src/TwitchArchive.Core/Config/EffectiveConfig.cs
Normal file
|
|
@ -0,0 +1,36 @@
|
|||
using System;
|
||||
|
||||
namespace TwitchArchive.Core.Config
|
||||
{
|
||||
public class EffectiveConfig
|
||||
{
|
||||
public string? ArchiveRoot { get; init; }
|
||||
public string? StreamlinkPath { get; init; }
|
||||
public string? FfmpegPath { get; init; }
|
||||
public string? TwitchDownloaderPath { get; init; }
|
||||
public string? RclonePath { get; init; }
|
||||
public bool UploadToCloud { get; init; }
|
||||
public string? UploadDestination { get; init; }
|
||||
public int RefreshIntervalSeconds { get; init; }
|
||||
public int StreamSegmentThreads { get; init; }
|
||||
public string? DefaultQuality { get; init; }
|
||||
|
||||
public static EffectiveConfig Merge(GlobalConfig global, StreamerConfig? streamer)
|
||||
{
|
||||
streamer ??= new StreamerConfig();
|
||||
return new EffectiveConfig
|
||||
{
|
||||
ArchiveRoot = streamer.Username != null ? (global.ArchiveRoot ?? string.Empty) : (global.ArchiveRoot ?? string.Empty),
|
||||
StreamlinkPath = streamer.StreamlinkPath ?? global.StreamlinkPath,
|
||||
FfmpegPath = global.FfmpegPath,
|
||||
TwitchDownloaderPath = global.TwitchDownloaderPath,
|
||||
RclonePath = global.RclonePath,
|
||||
UploadToCloud = streamer.UploadToCloud ?? global.UploadToCloud,
|
||||
UploadDestination = streamer.UploadDestination ?? global.UploadDestination,
|
||||
RefreshIntervalSeconds = global.RefreshIntervalSeconds,
|
||||
StreamSegmentThreads = global.StreamSegmentThreads,
|
||||
DefaultQuality = streamer.Quality ?? global.DefaultQuality
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
37
dotnet/src/TwitchArchive.Core/Config/GlobalConfig.cs
Normal file
37
dotnet/src/TwitchArchive.Core/Config/GlobalConfig.cs
Normal file
|
|
@ -0,0 +1,37 @@
|
|||
using System.Text.Json.Serialization;
|
||||
|
||||
namespace TwitchArchive.Core.Config
|
||||
{
|
||||
public class GlobalConfig
|
||||
{
|
||||
[JsonPropertyName("archive_root")]
|
||||
public string? ArchiveRoot { get; set; }
|
||||
|
||||
[JsonPropertyName("streamlink_path")]
|
||||
public string? StreamlinkPath { get; set; }
|
||||
|
||||
[JsonPropertyName("ffmpeg_path")]
|
||||
public string? FfmpegPath { get; set; }
|
||||
|
||||
[JsonPropertyName("twitchdownloader_path")]
|
||||
public string? TwitchDownloaderPath { get; set; }
|
||||
|
||||
[JsonPropertyName("rclone_path")]
|
||||
public string? RclonePath { get; set; }
|
||||
|
||||
[JsonPropertyName("upload_to_cloud")]
|
||||
public bool UploadToCloud { get; set; } = false;
|
||||
|
||||
[JsonPropertyName("upload_destination")]
|
||||
public string? UploadDestination { get; set; }
|
||||
|
||||
[JsonPropertyName("refresh_interval_seconds")]
|
||||
public int RefreshIntervalSeconds { get; set; } = 60;
|
||||
|
||||
[JsonPropertyName("stream_segment_threads")]
|
||||
public int StreamSegmentThreads { get; set; } = 4;
|
||||
|
||||
[JsonPropertyName("default_quality")]
|
||||
public string? DefaultQuality { get; set; } = "best";
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,18 @@
|
|||
using System.Collections.Generic;
|
||||
|
||||
namespace TwitchArchive.Core.Config
|
||||
{
|
||||
public interface IConfigurationService
|
||||
{
|
||||
GlobalConfig LoadGlobal();
|
||||
void SaveGlobal(GlobalConfig cfg);
|
||||
|
||||
StreamerConfig? LoadStreamer(string username);
|
||||
void SaveStreamer(StreamerConfig cfg);
|
||||
void DeleteStreamer(string username);
|
||||
|
||||
IEnumerable<StreamerConfig> GetAllStreamers();
|
||||
|
||||
EffectiveConfig GetEffectiveConfig(string username);
|
||||
}
|
||||
}
|
||||
25
dotnet/src/TwitchArchive.Core/Config/StreamerConfig.cs
Normal file
25
dotnet/src/TwitchArchive.Core/Config/StreamerConfig.cs
Normal file
|
|
@ -0,0 +1,25 @@
|
|||
using System.Text.Json.Serialization;
|
||||
|
||||
namespace TwitchArchive.Core.Config
|
||||
{
|
||||
public class StreamerConfig
|
||||
{
|
||||
[JsonPropertyName("username")]
|
||||
public string Username { get; set; } = string.Empty;
|
||||
|
||||
[JsonPropertyName("enabled")]
|
||||
public bool Enabled { get; set; } = true;
|
||||
|
||||
[JsonPropertyName("quality")]
|
||||
public string? Quality { get; set; }
|
||||
|
||||
[JsonPropertyName("upload_to_cloud")]
|
||||
public bool? UploadToCloud { get; set; }
|
||||
|
||||
[JsonPropertyName("upload_destination")]
|
||||
public string? UploadDestination { get; set; }
|
||||
|
||||
[JsonPropertyName("streamlink_path")]
|
||||
public string? StreamlinkPath { get; set; }
|
||||
}
|
||||
}
|
||||
35
dotnet/src/TwitchArchive.Core/Config/ToolPathResolver.cs
Normal file
35
dotnet/src/TwitchArchive.Core/Config/ToolPathResolver.cs
Normal file
|
|
@ -0,0 +1,35 @@
|
|||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace TwitchArchive.Core.Config
|
||||
{
|
||||
public static class ToolPathResolver
|
||||
{
|
||||
public static string DefaultStreamlinkPath()
|
||||
{
|
||||
if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
|
||||
return "streamlink.exe";
|
||||
return "/usr/local/bin/streamlink";
|
||||
}
|
||||
|
||||
public static string DefaultFfmpegPath()
|
||||
{
|
||||
if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
|
||||
return "ffmpeg.exe";
|
||||
return "/usr/bin/ffmpeg";
|
||||
}
|
||||
|
||||
public static string DefaultTwitchDownloaderPath()
|
||||
{
|
||||
if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
|
||||
return "TwitchDownloaderCLI.exe";
|
||||
return "/app/bin/TwitchDownloaderCLI";
|
||||
}
|
||||
|
||||
public static string DefaultRclonePath()
|
||||
{
|
||||
if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
|
||||
return "rclone.exe";
|
||||
return "/usr/bin/rclone";
|
||||
}
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue