Skip to content

Commit afe17a6

Browse files
committed
Refactor online image handling and update README
- Now uses https://github.com/MrKev312/JustDanceCovers instead of https://justdance.fandom.com/wiki/User_blog:Sweet_King_Candy/Extended_Covers_for_Just_Dance_%2B, this allows us to also get the songTitleLogo as well as easily add new covers as the blog post hasn't been updated in years. - Refactored `TryCoverWeb` to `TryImageWeb` and now uses the cover repository.
1 parent df9d60a commit afe17a6

File tree

4 files changed

+62
-98
lines changed

4 files changed

+62
-98
lines changed

JustDanceEditor.Converter/Converters/Bundles/CoverBundleGenerator.cs

+1-1
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,7 @@ static void GenerateCoverInternal(ConvertUbiArtToUnity convert)
6464
// If a cover.png exists in the map folder, use that
6565
Image<Rgba32>? coverImage = null;
6666
if (convert.ConversionRequest.OnlineCover)
67-
coverImage ??= CoverArtGenerator.TryCoverWeb(convert);
67+
coverImage ??= CoverArtGenerator.TryImageWeb(convert, "Cover");
6868
coverImage ??= CoverArtGenerator.ExistingCover(convert);
6969
coverImage ??= CoverArtGenerator.GenerateOwnCover(convert);
7070

JustDanceEditor.Converter/Converters/Bundles/SongTitleLogoBundleGenerator.cs

+12-5
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
using SixLabors.ImageSharp.Processing;
1212
using TextureConverter;
1313
using JustDanceEditor.Converter.Files;
14+
using JustDanceEditor.Converter.Converters.Images;
1415

1516
namespace JustDanceEditor.Converter.Converters.Bundles;
1617

@@ -37,9 +38,16 @@ static void GenerateSongTitleLogoInternal(ConvertUbiArtToUnity convert)
3738
{
3839
FileSystem fs = convert.FileSystem;
3940

40-
// Does the following exist?
41-
string songTitleLogoPath = Path.Combine(fs.TempFolders.MenuArtFolder, "songTitleLogo.png");
42-
if (!File.Exists(songTitleLogoPath))
41+
Image<Rgba32>? image = null;
42+
// Should we look up the cover online?
43+
if (convert.ConversionRequest.OnlineCover)
44+
image = CoverArtGenerator.TryImageWeb(convert, "Title");
45+
46+
// If we couldn't find the cover online, try to load it from the input folder
47+
image ??= CoverArtGenerator.ExistingSongTitleLogo(convert);
48+
49+
// If we still don't have a cover, we throw an info message
50+
if (image == null)
4351
{
4452
Logger.Log("No songTitleLogo.png found, skipping...", LogLevel.Important);
4553
return;
@@ -72,8 +80,7 @@ static void GenerateSongTitleLogoInternal(ConvertUbiArtToUnity convert)
7280
// Set the name to {mapName}_Cover_2x
7381
coverBase["m_Name"].AsString = $"{convert.SongData.Name}_Title";
7482

75-
// Load the image and make it fit in 1024x512
76-
Image<Rgba32> image = Image.Load<Rgba32>(songTitleLogoPath);
83+
// Make it fit in 1024x512
7784
if (image.Width / (float)image.Height != 2f)
7885
{
7986
// Pad the image to 2:1

JustDanceEditor.Converter/Converters/Images/CoverArtGenerator.cs

+45-92
Original file line numberDiff line numberDiff line change
@@ -7,11 +7,14 @@
77
using SixLabors.ImageSharp.Processing;
88
using SixLabors.ImageSharp.Drawing.Processing;
99
using SixLabors.Fonts;
10+
using System.Text.Json;
1011

1112
namespace JustDanceEditor.Converter.Converters.Images;
1213

1314
public static class CoverArtGenerator
1415
{
16+
private static HttpClient httpClient = new();
17+
1518
public static Image<Rgba32>? ExistingCover(ConvertUbiArtToUnity convert)
1619
{
1720
string[] paths =
@@ -51,6 +54,12 @@ public static class CoverArtGenerator
5154
return null;
5255
}
5356

57+
public static Image<Rgba32>? ExistingSongTitleLogo(ConvertUbiArtToUnity convert)
58+
{
59+
// Load the image
60+
return TryLoadImage(Path.Combine(convert.FileSystem.TempFolders.MenuArtFolder, "songTitleLogo.png"));
61+
}
62+
5463
static Image<Rgba32>? TryLoadImage(string path)
5564
{
5665
if (!File.Exists(path))
@@ -62,110 +71,54 @@ public static class CoverArtGenerator
6271
return coverImage;
6372
}
6473

65-
public static Image<Rgba32>? TryCoverWeb(ConvertUbiArtToUnity convert)
74+
public static Image<Rgba32>? TryImageWeb(ConvertUbiArtToUnity convert, string imageType)
6675
{
67-
try
68-
{
69-
string baseURL = "https://justdance.fandom.com";
70-
71-
// Download one from https://justdance.fandom.com/wiki/User_blog:Sweet_King_Candy/Extended_Covers_for_Just_Dance_%2B
72-
// Load the webpage
73-
HttpClient client = new();
74-
string html = client.GetStringAsync($"{baseURL}/wiki/User_blog:Sweet_King_Candy/Extended_Covers_for_Just_Dance_%2B").Result;
75-
76-
// Convert the html to a document
77-
HtmlDocument doc = new();
78-
doc.LoadHtml(html);
79-
80-
// Get the class called "fandom-table"[0]/tbody
81-
HtmlNode table = doc.DocumentNode.SelectNodes("//table[@class='fandom-table']")[0];
82-
HtmlNode htmlNode = table.SelectSingleNode("tbody");
83-
84-
// Get all the tr nodes
85-
List<HtmlNode> allNodes = htmlNode.SelectNodes("tr").Skip(1).ToList();
86-
87-
// Find the node where the first td's inner text is the map name
88-
List<HtmlNode> nodes = [];
89-
90-
foreach (HtmlNode node in allNodes)
91-
{
92-
// Get the first <i> tag's title, it might not be a direct child
93-
string title = node.SelectSingleNode(".//i").FirstChild.InnerText;
94-
95-
if (title.Trim() == convert.SongData.SongDesc.COMPONENTS[0].Title.Trim())
96-
{
97-
nodes.Add(node);
98-
}
99-
}
100-
101-
// If the cover doesn't exist, return false
102-
if (nodes.Count == 0)
103-
return null;
104-
105-
HtmlNode? row = null;
106-
107-
foreach (HtmlNode node in nodes)
108-
{
109-
// Get the url at .//i//a
110-
string url = baseURL + node.SelectSingleNode(".//a").Attributes["href"].Value;
111-
112-
// Load in the page
113-
string pageHtml = client.GetStringAsync(url).Result;
114-
HtmlDocument wikiPage = new();
115-
wikiPage.LoadHtml(pageHtml);
116-
117-
// Query for the infobox element
118-
HtmlNode? codeName = wikiPage.DocumentNode.SelectSingleNode("//b[contains(text(), 'Code Name')]");
119-
120-
if (codeName == null)
121-
continue;
122-
123-
// Get the parent.parent/div
124-
HtmlNode codeNameElement = codeName.ParentNode.ParentNode;
76+
string baseUrl = "https://raw.githubusercontent.com/MrKev312/JustDanceCovers/refs/heads/main/";
12577

126-
string? codeNameText = codeNameElement.Elements("div").FirstOrDefault()?.FirstChild.InnerText;
78+
Image<Rgba32>? FetchCoverFromWeb(string name)
79+
=> LoadFromUrl($"{baseUrl}/Covers/{name}/{imageType}.webp");
12780

128-
if (codeNameText == null)
129-
continue;
81+
Image<Rgba32>? coverImage = FetchCoverFromWeb(convert.SongData.Name);
13082

131-
// Skip everything after the first space
132-
codeNameText = codeNameText.Split(' ')[0];
83+
if (coverImage is not null)
84+
{
85+
Logger.Log($"Found {imageType} on the web", LogLevel.Important);
86+
return coverImage;
87+
}
13388

134-
if (codeNameText.Trim() == convert.SongData.Name.Trim())
135-
{
136-
row = node;
137-
break;
138-
}
139-
}
89+
// Else, maybe we can look in the Covers.json
90+
string coversJsonUrl = $"{baseUrl}/Covers.json";
91+
string json = httpClient.GetStringAsync(coversJsonUrl).Result;
92+
Dictionary<string, string[]> covers = JsonSerializer.Deserialize<Dictionary<string, string[]>>(json)!;
14093

141-
if (row == null)
142-
return null;
94+
string? codename = covers.Where(x => x.Value.Contains(convert.SongData.Name)).Select(x => x.Key).FirstOrDefault();
95+
if (codename is null)
96+
return null;
14397

144-
// If both the last or second to last td's are empty or "N/A", then the cover doesn't exist
145-
HtmlNodeCollection tds = row.SelectNodes("td");
98+
// Now we can try to fetch the cover from the web
99+
return FetchCoverFromWeb(codename);
100+
}
146101

147-
// Get the cover url with text on it
148-
string coverUrl = tds[^1].SelectSingleNode("(.//a )[1]").Attributes["href"].Value;
149-
// If this is a placeholder cover, get the second to last, the version without text
150-
if (coverUrl.Contains("PlaceHolderCover", StringComparison.OrdinalIgnoreCase))
151-
coverUrl = tds[^2].SelectSingleNode("(.//a )[1]").Attributes["href"].Value;
152-
if (coverUrl.Contains("PlaceHolderCover", StringComparison.OrdinalIgnoreCase))
153-
// Couldn't find the cover, return false
154-
return null;
102+
private static Image<Rgba32>? LoadFromUrl(string url)
103+
{
104+
// Return null if the URL is invalid or the request fails
105+
if (string.IsNullOrEmpty(url))
106+
return null;
155107

156-
// Load the image
157-
Stream coverStream = client.GetStreamAsync(coverUrl).Result;
158-
Image<Rgba32>? coverImage = Image.Load<Rgba32>(coverStream);
159-
coverImage.Mutate(x => x.Resize(640, 360));
108+
// Send a GET request to the URL
109+
using HttpResponseMessage response = httpClient.GetAsync(url).Result;
160110

161-
// Success!
162-
return coverImage;
163-
}
164-
catch (Exception e)
111+
// Check if the request was successful
112+
if (response.IsSuccessStatusCode)
165113
{
166-
Logger.Log($"Failed to get cover from the web: {e.Message}", LogLevel.Warning);
167-
return null;
114+
// Read the image data from the response
115+
byte[] imageData = response.Content.ReadAsByteArrayAsync().Result;
116+
// Load the image from the byte array
117+
using MemoryStream stream = new(imageData);
118+
return Image.Load<Rgba32>(stream);
168119
}
120+
121+
return null;
169122
}
170123

171124
public static Image<Rgba32> GenerateOwnCover(ConvertUbiArtToUnity convert)

README.md

+4
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,10 @@ Be sure to include the following information:
6464
- The error message you are getting.
6565
- Any other relevant information.
6666

67+
## Online Covers
68+
This tool can automatically download covers from the internet from this repository: [Just Dance Covers](https://github.com/MrKev312/JustDanceCovers).
69+
Feel free to add your own covers to the repository!
70+
6771
## Contributing
6872
Contributions are welcome! Please follow these guidelines:
6973
- Fork the repository.

0 commit comments

Comments
 (0)