Skip to content

Commit 99ec69b

Browse files
author
Meyn
committed
Cleanup for .net8.0
1 parent de97cdf commit 99ec69b

114 files changed

Lines changed: 894 additions & 987 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

Tubifarry/Blocklisting/BaseBlocklist.cs

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,11 +6,9 @@
66

77
namespace Tubifarry.Blocklisting
88
{
9-
public abstract class BaseBlocklist<TProtocol> : IBlocklistForProtocol where TProtocol : IDownloadProtocol
9+
public abstract class BaseBlocklist<TProtocol>(IBlocklistRepository blocklistRepository) : IBlocklistForProtocol where TProtocol : IDownloadProtocol
1010
{
11-
private readonly IBlocklistRepository _blocklistRepository;
12-
13-
public BaseBlocklist(IBlocklistRepository blocklistRepository) => _blocklistRepository = blocklistRepository;
11+
private readonly IBlocklistRepository _blocklistRepository = blocklistRepository;
1412

1513
public string Protocol => typeof(TProtocol).Name;
1614

Tubifarry/Blocklisting/Blocklists.cs

Lines changed: 4 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -3,14 +3,9 @@
33

44
namespace Tubifarry.Blocklisting
55
{
6-
public class YoutubeBlocklist : BaseBlocklist<YoutubeDownloadProtocol>
7-
{
8-
public YoutubeBlocklist(IBlocklistRepository blocklistRepository) : base(blocklistRepository) { }
6+
public class YoutubeBlocklist(IBlocklistRepository blocklistRepository) : BaseBlocklist<YoutubeDownloadProtocol>(blocklistRepository)
7+
{ }
98

10-
}
11-
12-
public class SoulseekBlocklist : BaseBlocklist<SoulseekDownloadProtocol>
13-
{
14-
public SoulseekBlocklist(IBlocklistRepository blocklistRepository) : base(blocklistRepository) { }
15-
}
9+
public class SoulseekBlocklist(IBlocklistRepository blocklistRepository) : BaseBlocklist<SoulseekDownloadProtocol>(blocklistRepository)
10+
{ }
1611
}

Tubifarry/Core/Model/AlbumData.cs

Lines changed: 11 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -7,11 +7,11 @@ namespace Tubifarry.Core.Model
77
/// <summary>
88
/// Contains combined information about an album, search parameters, and search results.
99
/// </summary>
10-
public class AlbumData
10+
public partial class AlbumData(string name, string downloadProtocol)
1111
{
1212
public string? Guid { get; set; }
13+
public string IndexerName { get; } = name;
1314

14-
public string IndexerName { get; }
1515
// Mixed
1616
public string AlbumId { get; set; } = string.Empty;
1717

@@ -37,17 +37,11 @@ public class AlbumData
3737
public int Priotity { get; set; }
3838
public List<string>? ExtraInfo { get; set; }
3939

40-
public string DownloadProtocol { get; set; }
40+
public string DownloadProtocol { get; set; } = downloadProtocol;
4141

4242
// Not used
4343
public AudioFormat Codec { get; set; } = AudioFormat.AAC;
4444

45-
public AlbumData(string name, string downloadProtocol)
46-
{
47-
IndexerName = name;
48-
DownloadProtocol = downloadProtocol;
49-
}
50-
5145
/// <summary>
5246
/// Converts AlbumData into a ReleaseInfo object.
5347
/// </summary>
@@ -120,15 +114,19 @@ private string ConstructTitle()
120114
/// <returns>The normalized album name.</returns>
121115
private static string NormalizeAlbumName(string albumName)
122116
{
123-
Regex featRegex = new(@"(?i)\b(feat\.|ft\.|featuring)\b", RegexOptions.IgnoreCase);
124-
if (featRegex.IsMatch(albumName))
117+
if (FeatRegex().IsMatch(albumName)) // TODO ISMatch vs Match
125118
{
126-
Match match = featRegex.Match(albumName);
119+
Match match = FeatRegex().Match(albumName);
127120
string featuringArtist = albumName[(match.Index + match.Length)..].Trim();
128121

129122
albumName = $"{albumName[..match.Index].Trim()} (feat. {featuringArtist})";
130123
}
131-
return Regex.Replace(albumName, @"\((?!feat\.)[^)]*\)", match => $"{{{match.Value.Trim('(', ')')}}}");
124+
return FeatReplaceRegex().Replace(albumName, match => $"{{{match.Value.Trim('(', ')')}}}");
132125
}
126+
127+
[GeneratedRegex(@"(?i)\b(feat\.|ft\.|featuring)\b", RegexOptions.IgnoreCase, "de-DE")]
128+
private static partial Regex FeatRegex();
129+
[GeneratedRegex(@"\((?!feat\.)[^)]*\)")]
130+
private static partial Regex FeatReplaceRegex();
133131
}
134132
}

Tubifarry/Core/Model/ApiCircuitBreaker.cs

Lines changed: 4 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -11,20 +11,14 @@ public interface ICircuitBreaker
1111
void Reset();
1212
}
1313

14-
public class ApiCircuitBreaker : ICircuitBreaker
14+
public class ApiCircuitBreaker(int failureThreshold = 5, int resetTimeoutMinutes = 5) : ICircuitBreaker
1515
{
1616
private int _failureCount;
1717
private DateTime _lastFailure = DateTime.MinValue;
18-
private readonly int _failureThreshold;
19-
private readonly TimeSpan _resetTimeout;
18+
private readonly int _failureThreshold = failureThreshold;
19+
private readonly TimeSpan _resetTimeout = TimeSpan.FromMinutes(resetTimeoutMinutes);
2020
private readonly object _lock = new();
2121

22-
public ApiCircuitBreaker(int failureThreshold = 5, int resetTimeoutMinutes = 5)
23-
{
24-
_failureThreshold = failureThreshold;
25-
_resetTimeout = TimeSpan.FromMinutes(resetTimeoutMinutes);
26-
}
27-
2822
public bool IsOpen
2923
{
3024
get
@@ -67,7 +61,7 @@ public void Reset()
6761

6862
public static class CircuitBreakerFactory
6963
{
70-
private static readonly ConditionalWeakTable<Type, ICircuitBreaker> _typeBreakers = new();
64+
private static readonly ConditionalWeakTable<Type, ICircuitBreaker> _typeBreakers = [];
7165
private static readonly ConcurrentDictionary<string, WeakReference<ICircuitBreaker>> _namedBreakers = new();
7266

7367
private static readonly object _cleanupLock = new();

Tubifarry/Core/Model/AudioMetadataHandler.cs

Lines changed: 20 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -51,8 +51,8 @@ public AudioMetadataHandler(string originalPath)
5151
{
5252
AudioFormat.AAC,
5353
bitrate => bitrate < 256
54-
? new[] { $"-b:a {bitrate}k" }
55-
: new[] { "-q:a 2" } // 2 is highest quality for AAC
54+
? [$"-b:a {bitrate}k"]
55+
: ["-q:a 2"] // 2 is highest quality for AAC
5656
},
5757

5858
{
@@ -70,42 +70,39 @@ public AudioMetadataHandler(string originalPath)
7070
>= 65 => 8, // V8 (~65-105kbps)
7171
_ => 9 // V9 (~45-85kbps)
7272
};
73-
return new[] { $"-q:a {qualityLevel}" };
73+
return [$"-q:a {qualityLevel}"];
7474
}
7575
},
7676

7777
{
7878
AudioFormat.Opus,
79-
bitrate => new[] {
80-
$"-b:a {bitrate}k",
81-
"-compression_level 10"
82-
}
79+
bitrate => [$"-b:a {bitrate}k", "-compression_level 10"]
8380
},
8481

8582
{
8683
AudioFormat.Vorbis,
87-
bitrate => new[] { $"-q:a {AudioFormatHelper.MapBitrateToVorbisQuality(bitrate)}" }
84+
bitrate => [$"-q:a {AudioFormatHelper.MapBitrateToVorbisQuality(bitrate)}"]
8885
},
8986

90-
{ AudioFormat.MP4, bitrate => new[] { $"-b:a {bitrate}k" } },
87+
{ AudioFormat.MP4, bitrate => [$"-b:a {bitrate}k"] },
9188
{
9289
AudioFormat.OGG,
93-
bitrate => new[] { $"-q:a {AudioFormatHelper.MapBitrateToVorbisQuality(bitrate)}" }
90+
bitrate => [$"-q:a {AudioFormatHelper.MapBitrateToVorbisQuality(bitrate)}"]
9491
},
95-
{ AudioFormat.AMR, bitrate => new[] { $"-ab {bitrate}k" } },
96-
{ AudioFormat.WMA, bitrate => new[] { $"-b:a {bitrate}k" } }
92+
{ AudioFormat.AMR, bitrate => [$"-ab {bitrate}k"]},
93+
{ AudioFormat.WMA, bitrate => [$"-b:a {bitrate}k"]}
9794
};
9895

99-
private static readonly string[] ExtractionParameters = new[]
100-
{
96+
private static readonly string[] ExtractionParameters =
97+
[
10198
"-codec:a copy",
10299
"-vn",
103100
"-movflags +faststart"
104-
};
101+
];
105102

106103

107-
private static readonly string[] VideoFormats = new[]
108-
{
104+
private static readonly string[] VideoFormats =
105+
[
109106
"matroska", "webm", // Matroska/WebM containers
110107
"mov", "mp4", "m4a", // QuickTime/MP4 containers
111108
"avi", // AVI containers
@@ -114,7 +111,7 @@ public AudioMetadataHandler(string originalPath)
114111
"3gp", "3g2", // 3GPP containers
115112
"mxf", // Material Exchange Format
116113
"ts", "m2ts" // Transport streams
117-
};
114+
];
118115

119116
/// <summary>
120117
/// Converts audio to the specified format with optional bitrate control.
@@ -372,7 +369,7 @@ public bool TryEmbedMetadata(Album albumInfo, Track trackInfo)
372369
file.GetTag(TagLib.TagTypes.Id3v2) is TagLib.Id3v2.Tag id3v2Tag)
373370
{
374371
TagLib.Id3v2.UserTextInformationFrame mbFrame = TagLib.Id3v2.UserTextInformationFrame.Get(id3v2Tag, "MusicBrainz Recording Id", true);
375-
mbFrame.Text = new[] { trackInfo.ForeignRecordingId };
372+
mbFrame.Text = [trackInfo.ForeignRecordingId];
376373
}
377374

378375
try
@@ -384,7 +381,7 @@ public bool TryEmbedMetadata(Album albumInfo, Track trackInfo)
384381
Type = TagLib.PictureType.FrontCover,
385382
Description = "Album Cover"
386383
};
387-
file.Tag.Pictures = new TagLib.IPicture[] { picture };
384+
file.Tag.Pictures = [picture];
388385
}
389386
}
390387
catch (Exception ex)
@@ -450,7 +447,7 @@ public static bool CheckFFmpegInstalled()
450447

451448
if (!string.IsNullOrEmpty(FFmpeg.ExecutablesPath) && Directory.Exists(FFmpeg.ExecutablesPath))
452449
{
453-
string[] ffmpegPatterns = new[] { "ffmpeg", "ffmpeg.exe", "ffmpeg.bin" };
450+
string[] ffmpegPatterns = ["ffmpeg", "ffmpeg.exe", "ffmpeg.bin"];
454451
string[] files = Directory.GetFiles(FFmpeg.ExecutablesPath);
455452
if (files.Any(file => ffmpegPatterns.Contains(Path.GetFileName(file), StringComparer.OrdinalIgnoreCase) && IsExecutable(file)))
456453
{
@@ -460,11 +457,11 @@ public static bool CheckFFmpegInstalled()
460457

461458
if (!isInstalled)
462459
{
463-
foreach (string path in Environment.GetEnvironmentVariable("PATH")?.Split(Path.PathSeparator) ?? Array.Empty<string>())
460+
foreach (string path in Environment.GetEnvironmentVariable("PATH")?.Split(Path.PathSeparator) ?? [])
464461
{
465462
if (Directory.Exists(path))
466463
{
467-
string[] ffmpegPatterns = new[] { "ffmpeg", "ffmpeg.exe", "ffmpeg.bin" };
464+
string[] ffmpegPatterns = ["ffmpeg", "ffmpeg.exe", "ffmpeg.bin"];
468465
string[] files = Directory.GetFiles(path);
469466

470467
if (files.Any(file => ffmpegPatterns.Contains(Path.GetFileName(file), StringComparer.OrdinalIgnoreCase) && IsExecutable(file)))

Tubifarry/Core/Model/FileCache.cs

Lines changed: 3 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -31,9 +31,7 @@ private void CleanupOldCacheFiles()
3131
File.Delete(file);
3232
}
3333
catch
34-
{
35-
36-
}
34+
{ }
3735
}
3836

3937
/// <summary>
@@ -105,11 +103,10 @@ public bool IsCacheValid(string cacheKey, TimeSpan expirationDuration)
105103
/// </summary>
106104
private string GetCacheFilePath(string cacheKey)
107105
{
108-
using MD5 md5 = MD5.Create();
109-
byte[] hashBytes = md5.ComputeHash(Encoding.UTF8.GetBytes(cacheKey));
106+
byte[] hashBytes = MD5.HashData(Encoding.UTF8.GetBytes(cacheKey));
110107
string hashString = BitConverter.ToString(hashBytes).Replace("-", "").ToLowerInvariant();
111108

112-
string subdirectory = hashString.Substring(0, 2);
109+
string subdirectory = hashString[..2];
113110
string fileName = $"{hashString}.json";
114111

115112
return Path.Combine(_cacheDirectory, subdirectory, fileName);
@@ -122,7 +119,6 @@ public void CheckDirectory()
122119
{
123120
try
124121
{
125-
126122
if (!Directory.Exists(_cacheDirectory))
127123
Directory.CreateDirectory(_cacheDirectory);
128124

@@ -134,7 +130,6 @@ public void CheckDirectory()
134130
int maxCachePathLength = _cacheDirectory.Length + 40;
135131
if (maxCachePathLength >= maxPath)
136132
throw new PathTooLongException($"Cache path exceeds OS limits ({maxCachePathLength} characters). Use a shorter base directory.");
137-
138133
}
139134
catch (Exception ex)
140135
{

Tubifarry/Core/Records/Lyric.cs

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,7 @@
66

77
namespace Tubifarry.Core.Records
88
{
9-
10-
public record Lyric(string? PlainLyrics, SyncLyric? SyncedLyrics)
9+
public record Lyric(string? PlainLyrics, List<SyncLine>? SyncedLyrics)
1110
{
1211
public static async Task<Lyric?> FetchLyricsFromLRCLIBAsync(string instance, ReleaseInfo releaseInfo, string trackName, int duration = 0, CancellationToken token = default)
1312
{
@@ -19,9 +18,7 @@ public record Lyric(string? PlainLyrics, SyncLyric? SyncedLyrics)
1918
}
2019
}
2120

22-
public class SyncLyric : List<SyncLine> { }
23-
24-
public record class SyncLine
21+
public partial record class SyncLine
2522
{
2623
[JsonProperty("lrc_timestamp")]
2724
public string? LrcTimestamp { get; init; }
@@ -35,13 +32,13 @@ public record class SyncLine
3532
[JsonProperty("line")]
3633
public string? Line { get; init; }
3734

38-
public static SyncLyric ParseSyncedLyrics(string syncedLyrics)
35+
public static List<SyncLine> ParseSyncedLyrics(string syncedLyrics)
3936
{
40-
SyncLyric lyric = new();
37+
List<SyncLine> lyric = [];
4138
string[] array = syncedLyrics.Split(new char[1] { '\n' }, StringSplitOptions.RemoveEmptyEntries);
4239
for (int i = 0; i < array.Length; i++)
4340
{
44-
Match match = Regex.Match(array[i], "\\[(\\d{2}:\\d{2}\\.\\d{2})\\](.*)");
41+
Match match = TagRegex().Match(array[i]);
4542
if (match.Success)
4643
{
4744
string value = match.Groups[1].Value;
@@ -57,5 +54,8 @@ public static SyncLyric ParseSyncedLyrics(string syncedLyrics)
5754
}
5855
return lyric;
5956
}
57+
58+
[GeneratedRegex("\\[(\\d{2}:\\d{2}\\.\\d{2})\\](.*)")]
59+
private static partial Regex TagRegex();
6060
}
6161
}

Tubifarry/Core/Records/MappingAgent.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
{
33
public record MappingAgent
44
{
5-
public string UserAgent { get; set; } = "Tubifarry/" + PluginInfo.Version;
5+
public string UserAgent { get; set; } = Tubifarry.UserAgent;
66

77
public static T? MapAgent<T>(T? mappingAgent, string userAgent) where T : MappingAgent
88
{

Tubifarry/Core/Records/YouTubeSession.cs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@
22

33
namespace Tubifarry.Core.Records
44
{
5-
65
/// <summary>
76
/// Represents session token data for transportation and caching
87
/// </summary>

0 commit comments

Comments
 (0)