First commit

This commit is contained in:
2026-03-15 22:15:34 -05:00
commit 0858a8a751
79 changed files with 6010 additions and 0 deletions
+14
View File
@@ -0,0 +1,14 @@
using System.Text.Json.Serialization;
namespace Tesses.YouTubeDownloader2025Companion;
public class Album {
public long Id {get;set;} = 0;
public string AlbumId {get;set;}="";
public string AlbumName {get;set;}="";
public string AlbumReleaseDate {get;set;}="";
}
+19
View File
@@ -0,0 +1,19 @@
using System.Text.Json.Serialization;
namespace Tesses.YouTubeDownloader2025Companion;
public class AlbumQuery {
[JsonPropertyName("releases")]
public List<AlbumQueryItem> Albums {get;set;}=new List<AlbumQueryItem>();
public class AlbumQueryItem
{
[JsonPropertyName("id")]
public Guid Id {get;set;}
[JsonPropertyName("title")]
public string Name {get;set;}="";
}
}
+67
View File
@@ -0,0 +1,67 @@
using System.Text.Json.Serialization;
namespace Tesses.YouTubeDownloader2025Companion;
public class AlbumSongQuery {
[JsonPropertyName("artist-credit")]
public List<AlbumSongQueryMedia.AlbumSongQueryMediaTrack.AlbumSongQueryMediaTrackRecording.AlbumSongQueryMediaTrackRecordingArtists> Artists {get;set;}=new List<AlbumSongQueryMedia.AlbumSongQueryMediaTrack.AlbumSongQueryMediaTrackRecording.AlbumSongQueryMediaTrackRecordingArtists>();
[JsonPropertyName("title")]
public string Title {get;set;}="";
[JsonPropertyName("date")]
public string Date {get;set;}="";
[JsonPropertyName("media")]
public List<AlbumSongQueryMedia> Media {get;set;}=new List<AlbumSongQueryMedia>();
public class AlbumSongQueryMedia {
[JsonPropertyName("tracks")]
public List<AlbumSongQueryMediaTrack> Tracks {get;set;}=new List<AlbumSongQueryMediaTrack>();
public class AlbumSongQueryMediaTrack
{
[JsonPropertyName("position")]
public int Track {get;set;} = 1;
[JsonPropertyName("recording")]
public AlbumSongQueryMediaTrackRecording Recording {get;set;}=new AlbumSongQueryMediaTrackRecording();
[JsonPropertyName("length")]
public long Length {get;set;} = 0;
public class AlbumSongQueryMediaTrackRecording
{
[JsonPropertyName("title")]
public string Name {get;set;}="";
[JsonPropertyName("id")]
public Guid Id {get;set;}
[JsonPropertyName("artist-credit")]
public List<AlbumSongQueryMediaTrackRecordingArtists> ContributingArtists {get;set;}=new List<AlbumSongQueryMediaTrackRecordingArtists>();
public class AlbumSongQueryMediaTrackRecordingArtists
{
[JsonPropertyName("joinphrase")]
public string JoinPhrase {get;set;}="";
[JsonPropertyName("artist")]
public AlbumSongQueryMediaTrackRecordingArtistsArtist Artist {get;set;}=new AlbumSongQueryMediaTrackRecordingArtistsArtist();
public class AlbumSongQueryMediaTrackRecordingArtistsArtist
{
[JsonPropertyName("name")]
public string Name {get;set;}="";
[JsonPropertyName("id")]
public Guid Id {get;set;}
[JsonPropertyName("disambiguation")]
public string Disambiguation {get;set;}="";
}
}
}
}
}
}
+27
View File
@@ -0,0 +1,27 @@
using System.Text.Json.Serialization;
namespace Tesses.YouTubeDownloader2025Companion;
public class AlbumTrack {
public long Id {get;set;} = 0;
public string AlbumId {get;set;}="";
public string SongId {get;set;}="";
public int Track {get;set;}=0;
public long Length {get;set;}=0;
}
public class AlbumSongTrack {
public string AlbumId {get;set;}="";
public string SongId {get;set;} = "";
public int Track {get;set;}
public string SongName {get;set;}="";
public long Length {get;set;}=0;
}
+14
View File
@@ -0,0 +1,14 @@
using System.Text.Json.Serialization;
namespace Tesses.YouTubeDownloader2025Companion;
public class Artist {
public long Id {get;set;}=0;
public string ArtistId {get;set;}="";
public string ArtistDisambiguation {get;set;}="";
public string ArtistName {get;set;}="";
}
+19
View File
@@ -0,0 +1,19 @@
using System.Text.Json.Serialization;
namespace Tesses.YouTubeDownloader2025Companion;
public class ArtistQuery {
[JsonPropertyName("artists")]
public List<ArtistQueryItem> Artists {get;set;}=new List<ArtistQueryItem>();
public class ArtistQueryItem
{
[JsonPropertyName("id")]
public Guid Id {get;set;}
[JsonPropertyName("name")]
public string Name {get;set;}="";
}
}
+15
View File
@@ -0,0 +1,15 @@
using System.Text.Json.Serialization;
namespace Tesses.YouTubeDownloader2025Companion;
public class AudioDBArtistJsonResponse {
[JsonPropertyName("artists")]
public List<AudioDBArtistJsonResponseArtist> Artists {get;set;}=new List<AudioDBArtistJsonResponseArtist>();
public class AudioDBArtistJsonResponseArtist
{
[JsonPropertyName("strArtistThumb")]
public string Thumbnail {get;set;}="";
}
}
+83
View File
@@ -0,0 +1,83 @@
using System.Diagnostics;
using System.Text.Json.Serialization;
using Tesses.WebServer;
using YoutubeExplode.Videos;
namespace Tesses.YouTubeDownloader2025Companion;
public class MediaEntry {
public string AlbumArtist {get;set;}="";
public string AlbumName {get;set;}="";
public string SongName {get;set;} = "";
public string AlbumId {get;set;}="";
public List<string> ContributingArtists {get;set;}=new List<string>();
public string ContributingArtistsString => string.Join("; ", ContributingArtists.Select(e=>e.Replace(";","")));
public int TrackIndex {get;set;}
public override string ToString()
{
var trackIndex = TrackIndex.ToString("D2");
return Path.Combine("data","Music",ServerContext.FixFileName(AlbumArtist),ServerContext.FixFileName(AlbumName),$"{trackIndex} {ServerContext.FixFileName(SongName)}.mp3");
}
public async Task<bool> ImportAsync(string srcPath)
{
string dest = ToString();
if(File.Exists(dest)) return true;
using Process p = new Process();
p.StartInfo.FileName = "ffmpeg";
p.StartInfo.UseShellExecute = false;
p.StartInfo.CreateNoWindow=true;
p.StartInfo.WindowStyle = ProcessWindowStyle.Hidden;
p.StartInfo.ArgumentList.Add("-y");
p.StartInfo.ArgumentList.Add("-i");
p.StartInfo.ArgumentList.Add(srcPath);
p.StartInfo.ArgumentList.Add("-i");
p.StartInfo.ArgumentList.Add($"data/Thumbnails/Albums/{AlbumId}.jpg");
p.StartInfo.ArgumentList.Add("-metadata");
p.StartInfo.ArgumentList.Add($"artist={ContributingArtistsString}");
p.StartInfo.ArgumentList.Add("-metadata");
p.StartInfo.ArgumentList.Add($"album={AlbumName}");
p.StartInfo.ArgumentList.Add("-metadata");
p.StartInfo.ArgumentList.Add($"album_artist={AlbumArtist}");
p.StartInfo.ArgumentList.Add("-metadata");
p.StartInfo.ArgumentList.Add($"title={SongName}");
p.StartInfo.ArgumentList.Add("-metadata");
p.StartInfo.ArgumentList.Add($"track={TrackIndex}");
p.StartInfo.ArgumentList.Add("-c:v");
p.StartInfo.ArgumentList.Add("copy");
p.StartInfo.ArgumentList.Add("-map");
p.StartInfo.ArgumentList.Add("0:a");
p.StartInfo.ArgumentList.Add("-map");
p.StartInfo.ArgumentList.Add("1:v");
p.StartInfo.ArgumentList.Add("-id3v2_version");
p.StartInfo.ArgumentList.Add("3");
p.StartInfo.ArgumentList.Add("-metadata:s:v");
p.StartInfo.ArgumentList.Add("title=Album cover");
p.StartInfo.ArgumentList.Add("-metadata:s:v");
p.StartInfo.ArgumentList.Add("comment=Cover (Front)");
p.StartInfo.ArgumentList.Add("data/Temp/conv.mp3");
if(p.Start())
{
await p.WaitForExitAsync();
if(p.ExitCode == 0)
{
string? dir=Path.GetDirectoryName(dest);
if(!string.IsNullOrWhiteSpace(dir))
Directory.CreateDirectory(dir);
File.Move("data/Temp/conv.mp3",dest);
return true;
}
}
return false;
}
}
+13
View File
@@ -0,0 +1,13 @@
using System.Text.Json.Serialization;
namespace Tesses.YouTubeDownloader2025Companion;
public class Song {
public long Id {get;set;}=0;
public string SongId {get;set;}="";
public string SongName {get;set;}="";
}
+14
View File
@@ -0,0 +1,14 @@
using System.Text.Json.Serialization;
namespace Tesses.YouTubeDownloader2025Companion;
public class SongVideo {
public long Id {get;set;}=0;
public string SongId {get;set;}="";
public string VideoId {get;set;}="";
public string VideoTitle {get;set;}="";
}
+45
View File
@@ -0,0 +1,45 @@
using System.Diagnostics.CodeAnalysis;
using Newtonsoft.Json;
public enum LogEntryType {
VideoStarted,
VideoFinished,
Bell,
Started,
Unknown
}
public class LogEntry {
public long Time {get;set;}
[JsonIgnore]
public DateTimeOffset DateTime => DateTimeOffset.FromUnixTimeSeconds(Time);
public string Type {get;set;}="";
[JsonIgnore]
public LogEntryType EventType {
get {
if(Enum.TryParse<LogEntryType>(Type,out var type))
{
return type;
}
return LogEntryType.Unknown;
}
set => Type = value.ToString();
}
public string? VideoTitle {get;set;}
public string? VideoId {get;set;}
public string? ChannelTitle {get;set;}
public string? ChannelId {get;set;}
[JsonIgnore]
[MemberNotNullWhen(true,nameof(VideoTitle),nameof(VideoId),nameof(ChannelTitle),nameof(ChannelId))]
public bool HasStrings => !string.IsNullOrEmpty(VideoTitle) && !string.IsNullOrEmpty(VideoId) && !string.IsNullOrEmpty(ChannelTitle) && !string.IsNullOrEmpty(ChannelId);
}
+21
View File
@@ -0,0 +1,21 @@
using System.Text.Json.Serialization;
namespace Tesses.YouTubeDownloader2025Companion;
public class Webhook {
public string Type {get;set;}="";
public WebhookVideo Video {get;set;}=new WebhookVideo();
public class WebhookVideo
{
public string Channel {get;set;}="";
public string ChannelId {get;set;}="";
public string Title {get;set;}="";
public string VideoId {get;set;}="";
}
}