-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Update to .Net 8, fix bug with new api change with graphql, more details
- Loading branch information
Showing
5 changed files
with
181 additions
and
102 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,20 +1,16 @@ | ||
<Project Sdk="Microsoft.NET.Sdk"> | ||
|
||
<PropertyGroup> | ||
<TargetFramework>net6.0</TargetFramework> | ||
<TargetFramework>net8.0</TargetFramework> | ||
<RootNamespace>audiothek_client</RootNamespace> | ||
<ImplicitUsings>enable</ImplicitUsings> | ||
<Nullable>enable</Nullable> | ||
</PropertyGroup> | ||
|
||
<ItemGroup> | ||
<PackageReference Include="GraphQL.Client" Version="5.1.0" /> | ||
<PackageReference Include="GraphQL.Client.Serializer.SystemTextJson" Version="5.1.0" /> | ||
<PackageReference Include="GraphQL.SystemTextJson" Version="7.2.2" /> | ||
</ItemGroup> | ||
|
||
<ItemGroup> | ||
<Folder Include="Api.Catalog" /> | ||
<PackageReference Include="GraphQL.Client" Version="6.1.0" /> | ||
<PackageReference Include="GraphQL.Client.Serializer.SystemTextJson" Version="6.1.0" /> | ||
<PackageReference Include="GraphQL.SystemTextJson" Version="7.8.0" /> | ||
</ItemGroup> | ||
|
||
</Project> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,57 +1,133 @@ | ||
using audiothek_client; | ||
using Spectre.Console; | ||
|
||
AnsiConsole.Clear(); | ||
AnsiConsole.Write(new FigletText("Audiothekar").Color(Color.Blue)); | ||
ApiRequester apiRequester = new ApiRequester(); | ||
IEnumerable<Node> nodesOfAllCategories = (await apiRequester.GetAllProgramSets()).ToList(); | ||
IEnumerable<IGrouping<string, Node>> categories = nodesOfAllCategories.Select(x => | ||
{ | ||
if (x.editorialCategory == null) | ||
x.editorialCategory = new EditorialCategory() { id = "", title = "Andere" }; | ||
return x; | ||
}).GroupBy(x => x.editorialCategory.title); | ||
bool downloadSelected = false; | ||
Node selectedNode = null; | ||
string selectedCategory = null; | ||
while (!downloadSelected) | ||
namespace audiothekar_cli; | ||
|
||
public static class Program | ||
{ | ||
selectedCategory = AnsiConsole.Prompt( | ||
new SelectionPrompt<string>() | ||
.Title("Rubrik:") | ||
.PageSize(15) | ||
.AddChoices(categories.Select(x => x.Key))); | ||
|
||
selectedNode = AnsiConsole.Prompt( | ||
new SelectionPrompt<Node>() | ||
.Title("Reihe:") | ||
.PageSize(15) | ||
.AddChoices(categories.Single(x => x.Key == selectedCategory).OrderBy(x => x.title))); | ||
|
||
var nodesByNodeId = await apiRequester.GetFilesByNodeId(selectedNode.nodeId); | ||
var nodesWithDownloadUrl = nodesByNodeId.Where(x => x.audios.FirstOrDefault()?.downloadUrl != null).ToList(); | ||
if (!nodesWithDownloadUrl.Any()) | ||
public static async Task Main(string[] args) | ||
{ | ||
AnsiConsole.Write("No downloads available"); | ||
Console.ReadKey(); | ||
AnsiConsole.Clear(); | ||
AnsiConsole.Write(new FigletText("Audiothekar").Color(Color.Blue)); | ||
ApiRequester apiRequester = new ApiRequester(); | ||
IEnumerable<Node> nodesOfAllCategories = (await apiRequester.GetAllProgramSets()).ToList(); | ||
IEnumerable<IGrouping<string, Node>> categories = nodesOfAllCategories.Select(x => | ||
{ | ||
x.editorialCategory ??= new EditorialCategory() { id = "", title = "Andere" }; | ||
return x; | ||
}).GroupBy(x => x.editorialCategory!.title).ToList(); | ||
bool downloadSelected = false; | ||
Node? selectedNode = null; | ||
List<Node> children = new List<Node>(); | ||
while (!downloadSelected) | ||
{ | ||
string selectedCategory = SelectCategory(categories); | ||
|
||
selectedNode = SelectSeries(categories.Single(x => x.Key == selectedCategory)); | ||
|
||
var items = await apiRequester.GetFilesByNodeId(selectedNode.nodeId); | ||
children = FilterDownloadableNodes(items); | ||
if (!children.Any()) | ||
{ | ||
AnsiConsole.Write("No downloads available"); | ||
Console.ReadKey(); | ||
} | ||
else | ||
{ | ||
AnsiConsole.Write(CreateTreeFromNodes(selectedNode, children)); | ||
downloadSelected = AnsiConsole.Confirm("Download starten?"); | ||
} | ||
|
||
if (!downloadSelected) | ||
AnsiConsole.Clear(); | ||
} | ||
|
||
await DownloadAllFilesFromNodes(apiRequester, children, selectedNode!.title); | ||
} | ||
else | ||
|
||
private static string SelectCategory(IEnumerable<IGrouping<string, Node>> categories) | ||
{ | ||
AnsiConsole.Write(new Rows(nodesWithDownloadUrl.Select(x => new Text(x.title)))); | ||
downloadSelected = AnsiConsole.Confirm("Download starten?"); | ||
string selectedCategory = AnsiConsole.Prompt( | ||
new SelectionPrompt<string>() | ||
.Title("Rubrik:") | ||
.PageSize(15) | ||
.AddChoices(categories.Select(x => x.Key).Order())); | ||
return selectedCategory; | ||
} | ||
|
||
if (!downloadSelected) | ||
AnsiConsole.Clear(); | ||
} | ||
private static Node SelectSeries(IEnumerable<Node> nodes) | ||
{ | ||
Node selectedNode = AnsiConsole.Prompt( | ||
new SelectionPrompt<Node>() | ||
.Title("Reihe:") | ||
.PageSize(15) | ||
.AddChoices(nodes.OrderByDescending(x => x.lastItemAdded))); | ||
return selectedNode; | ||
} | ||
|
||
string path = Environment.GetFolderPath(Environment.SpecialFolder.MyMusic); | ||
Task downloadTask = apiRequester.DownloadAllFilesFromNode(selectedNode, path); | ||
Console.WriteLine($"Download {selectedNode.title} nach {path}"); | ||
await AnsiConsole.Status().StartAsync("Downloading...", async ctx => | ||
{ | ||
ctx.Spinner(Spinner.Known.Star); | ||
ctx.SpinnerStyle(Style.Parse("green")); | ||
await downloadTask; | ||
}); | ||
Console.WriteLine("-------------"); | ||
private static List<Node> FilterDownloadableNodes(IEnumerable<Node> nodes) | ||
{ | ||
return nodes | ||
.Where(x => x.audios.Any(audio => audio.downloadUrl != null)) | ||
.GroupBy(x => x.assetId) | ||
.Select(y => y.OrderByDescending(a => a.publishDate).First()) | ||
.OrderBy(x => x.episodeNumber).ToList(); | ||
} | ||
|
||
private static Tree CreateTreeFromNodes(Node root, IReadOnlyCollection<Node> children) | ||
{ | ||
var tree = new Tree(root.editorialCategory!.title); | ||
|
||
var item = tree.AddNode(root.title); | ||
item.AddNode(new Text($"{children.Count} Items")); | ||
var table = new Table() | ||
.RoundedBorder() | ||
.AddColumn("Name") | ||
.AddColumn("Dauer"); | ||
item.AddNode(table); | ||
foreach (var child in children) | ||
{ | ||
table.AddRow(child.title, TimeSpan.FromSeconds(child.duration).ToString()); | ||
} | ||
|
||
return tree; | ||
} | ||
|
||
public static async Task DownloadAllFilesFromNodes(ApiRequester apiRequester, IEnumerable<Node> nodes, | ||
string parentTitle) | ||
{ | ||
string outputRootDir = Environment.GetFolderPath(Environment.SpecialFolder.MyMusic); | ||
string outputDir = Path.Combine(outputRootDir, MakeValidFileName(parentTitle)); | ||
Console.WriteLine($"Download {parentTitle} nach {outputDir}"); | ||
await AnsiConsole.Status().StartAsync("Downloading...", async ctx => | ||
{ | ||
ctx.Spinner(Spinner.Known.Star); | ||
ctx.SpinnerStyle(Style.Parse("green")); | ||
foreach (var node in nodes) | ||
{ | ||
try | ||
{ | ||
ctx.Status = $"Downloading '{node.title}'"; | ||
await apiRequester.Download(node, outputDir); | ||
} | ||
catch (Exception e) | ||
{ | ||
AnsiConsole.Markup($"Download von '{node.title}' schlug fehl: {e.Message}"); | ||
if (!node.isPublished) | ||
AnsiConsole.Markup($"Mögliche Ursache: Diese Resource ist (noch) nicht veröffentlicht."); | ||
AnsiConsole.Markup($"Setze restliche Downloads fort..."); | ||
} | ||
} | ||
}); | ||
AnsiConsole.Markup(":check_mark_button: Completed."); | ||
} | ||
|
||
private static string MakeValidFileName(string name) | ||
{ | ||
string invalidChars = | ||
System.Text.RegularExpressions.Regex.Escape(new string(Path.GetInvalidFileNameChars())); | ||
string invalidRegStr = string.Format(@"([{0}]*\.+$)|([{0}]+)", invalidChars); | ||
|
||
return System.Text.RegularExpressions.Regex.Replace(name, invalidRegStr, "-"); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters