138 lines
5.3 KiB
C#
138 lines
5.3 KiB
C#
using PowerArgs;
|
|
using Newtonsoft.Json.Linq;
|
|
using System.Net;
|
|
|
|
namespace SBT_Downloader
|
|
{
|
|
internal class Program
|
|
{
|
|
static void Main(string[] args)
|
|
{
|
|
Console.WriteLine("Welcome to the Sound Booth Theater Personal Archiving Tool!");
|
|
try
|
|
{
|
|
MyArgs parsed = Args.Parse<MyArgs>(args);
|
|
Console.WriteLine("Downloading book now...");
|
|
(List<string> mp3Urls, List<string> chapters) = ParseHar(parsed.Har);
|
|
DownloadMp3s(mp3Urls, chapters, parsed);
|
|
}
|
|
catch (ArgException ex)
|
|
{
|
|
Console.WriteLine(ex.Message);
|
|
Console.WriteLine(ArgUsage.GenerateUsageFromTemplate<MyArgs>());
|
|
}
|
|
}
|
|
|
|
static (List<string> mp3Urls, List<string> chapters) ParseHar(string har)
|
|
{
|
|
try
|
|
{
|
|
string harContents = LoadHar(har);
|
|
JObject harObject = JObject.Parse(harContents);
|
|
List<JToken> requestObjects = ParseRequests(harObject);
|
|
List<string> mp3Urls = ParseUrls(requestObjects);
|
|
List<string> chapters = ParseChapters(mp3Urls);
|
|
return (mp3Urls, chapters);
|
|
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
Console.WriteLine(ex.Message);
|
|
Environment.Exit(0);
|
|
return (new List<string>(), new List<string>());
|
|
}
|
|
}
|
|
|
|
private static List<JToken?> ParseRequests(JObject harObject)
|
|
{
|
|
List<JToken?> requests = harObject["log"]["entries"]
|
|
.Where(x => x.SelectToken("_resourceType").ToString() == "media")
|
|
.Select(y => y.SelectToken("request"))
|
|
.DistinctBy(z => z.SelectToken("url")).ToList();
|
|
|
|
return requests;
|
|
}
|
|
|
|
private static List<string> ParseChapters(List<string> mp3Urls)
|
|
{
|
|
List<string> chapters = new();
|
|
foreach (string url in mp3Urls)
|
|
{
|
|
Uri uri = new(url);
|
|
string fixedUri = uri.AbsoluteUri.Replace(uri.Query, string.Empty);
|
|
List<string> urlTokens = fixedUri.Split("/").ToList();
|
|
//string series = urlTokens[5];
|
|
//string title = urlTokens[6];
|
|
//string episode = urlTokens[7];
|
|
var chapterTokens = urlTokens.Last().Split("_").ToList();
|
|
chapterTokens.RemoveRange(0,5);
|
|
string chapterLastToken = chapterTokens.Last().Split(".").First();
|
|
chapterTokens[^1] = chapterLastToken;
|
|
chapters.Add(string.Join(" ", chapterTokens));
|
|
}
|
|
|
|
return chapters;
|
|
}
|
|
|
|
static List<string> ParseUrls(List<JToken> requestList)
|
|
{
|
|
List<string> urls = requestList.Select(x => x.SelectToken("url").ToString()).ToList();
|
|
|
|
Console.WriteLine(urls.Count + " total requests");
|
|
|
|
return urls;
|
|
}
|
|
|
|
private static void DownloadMp3s(List<string> mp3Urls, List<string> chapters, MyArgs arguments)
|
|
{
|
|
Parallel.ForEach(
|
|
mp3Urls,
|
|
new ParallelOptions { MaxDegreeOfParallelism = 10 },
|
|
(url, state, index) =>
|
|
{
|
|
int chapterNumber = (int)index + 1;
|
|
string chapterName = chapters[(int)index];
|
|
string fileName = $"{chapterNumber} {chapterName}.mp3";
|
|
using var client = new WebClient();
|
|
Console.WriteLine("Downloading file #" + index);
|
|
client.DownloadFile(url, fileName);
|
|
TagFile(chapterName, chapterNumber, chapters.Count, arguments);
|
|
});
|
|
}
|
|
|
|
private static void TagFile(string chapterName, int chapterNumber, int chapterCount, MyArgs arguments)
|
|
{
|
|
Console.WriteLine($"Tagging chapter {chapterNumber} ({chapterCount})");
|
|
var file = TagLib.File.Create($"{chapterNumber} {chapterName}.mp3");
|
|
|
|
file.Tag.Album = arguments.Title.IsNullOrEmpty() ? string.Empty : arguments.Title;
|
|
List<string> artistsList = new();
|
|
if (!arguments.Author.IsNullOrEmpty()) artistsList.Add(arguments.Author);
|
|
if (!arguments.Narrator.IsNullOrEmpty()) artistsList.Add(arguments.Narrator);
|
|
file.Tag.AlbumArtists = artistsList.ToArray();
|
|
file.Tag.Title = chapterName;
|
|
file.Tag.Track = (uint)chapterNumber;
|
|
file.Tag.TrackCount = (uint)chapterCount;
|
|
|
|
file.Save();
|
|
}
|
|
|
|
static string LoadHar(string harFileName)
|
|
{
|
|
string harContents;
|
|
try
|
|
{
|
|
using StreamReader streamReader = new(harFileName);
|
|
harContents = streamReader.ReadToEnd();
|
|
return harContents;
|
|
}
|
|
catch (Exception e)
|
|
{
|
|
Console.WriteLine("The file could not be read:");
|
|
Console.WriteLine(e.Message);
|
|
Environment.Exit(0);
|
|
return string.Empty;
|
|
}
|
|
}
|
|
}
|
|
} |