Skip to content

Commit

Permalink
Merge pull request #143 from Corona-Studio/hotfix
Browse files Browse the repository at this point in the history
Minor bug fix, new Modrinth API
  • Loading branch information
laolarou726 authored Apr 27, 2024
2 parents 0111e35 + 495e163 commit 70302e8
Show file tree
Hide file tree
Showing 12 changed files with 153 additions and 58 deletions.
6 changes: 4 additions & 2 deletions ProjBobcat/ProjBobcat/Class/Helper/CurseForgeAPIHelper.cs
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,8 @@ public static void SetApiKey(string apiKey)
using var req = Req(HttpMethod.Get, reqUrl);
using var res = await Client.SendAsync(req);

res.EnsureSuccessStatusCode();

return (await res.Content.ReadFromJsonAsync(CurseForgeModelContext.Default
.DataModelCurseForgeLatestFileModelArray))?.Data;
}
Expand Down Expand Up @@ -174,11 +176,11 @@ public static void SetApiKey(string apiKey)
return (await res.Content.ReadFromJsonAsync(CurseForgeModelContext.Default.DataModelString))?.Data;
}

public static async Task<CurseForgeFuzzySearchResponseModel?> TryFuzzySearchFile(long fingerprint, int gameId = 432)
public static async Task<CurseForgeFuzzySearchResponseModel?> TryFuzzySearchFile(long[] fingerprint, int gameId = 432)
{
var reqUrl = $"{BaseUrl}/fingerprints/{gameId}";

var data = JsonSerializer.Serialize(new FuzzyFingerPrintReqModel([fingerprint]),
var data = JsonSerializer.Serialize(new FuzzyFingerPrintReqModel(fingerprint),
CurseForgeModelContext.Default.FuzzyFingerPrintReqModel);

using var req = Req(HttpMethod.Post, reqUrl);
Expand Down
58 changes: 45 additions & 13 deletions ProjBobcat/ProjBobcat/Class/Helper/GameResourcesResolveHelper.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
using System.Threading;
using System.Threading.Tasks;
using ProjBobcat.Class.Helper.TOMLParser;
using ProjBobcat.Class.Model;
using ProjBobcat.Class.Model.Fabric;
using ProjBobcat.Class.Model.GameResource;
using ProjBobcat.Class.Model.GameResource.ResolvedInfo;
Expand Down Expand Up @@ -143,6 +144,28 @@ static async Task<GameModResolvedInfo> GetFabricModInfo(
}
}

public static ModLoaderType GetModLoaderType(IArchive archive)
{
var fabricEntry = archive.Entries.Any(e =>
e.Key.EndsWith("fabric.mod.json", StringComparison.OrdinalIgnoreCase));

if (fabricEntry) return ModLoaderType.Fabric;

var neoforgeEntry = archive.Entries.Any(e =>
e.Key.EndsWith("_neoforge.mixins.json", StringComparison.OrdinalIgnoreCase));

if (neoforgeEntry) return ModLoaderType.NeoForge;

var forgeEntry = archive.Entries.Any(e =>
e.Key.EndsWith("META-INF/mods.toml", StringComparison.OrdinalIgnoreCase));
var forgeNewEntry = archive.Entries.Any(e =>
e.Key.EndsWith("mcmod.info", StringComparison.OrdinalIgnoreCase));

if (forgeEntry || forgeNewEntry) return ModLoaderType.Forge;

return ModLoaderType.Unknown;
}

public static async IAsyncEnumerable<GameModResolvedInfo> ResolveModListAsync(
IEnumerable<string> files,
[EnumeratorCancellation] CancellationToken ct)
Expand Down Expand Up @@ -174,23 +197,31 @@ public static async IAsyncEnumerable<GameModResolvedInfo> ResolveModListAsync(

GameModResolvedInfo? result = null;

if (modInfoEntry != null)
try
{
result = await GetNewModInfo(modInfoEntry, file, isEnabled, ct);

if (result != null) goto ReturnResult;
}
if (modInfoEntry != null)
{
result = await GetNewModInfo(modInfoEntry, file, isEnabled, ct);

if (tomlInfoEntry != null)
{
result = await GetLegacyModInfo(tomlInfoEntry, file, isEnabled);
if (result != null) goto ReturnResult;
}

if (result != null) goto ReturnResult;
}
if (tomlInfoEntry != null)
{
result = await GetLegacyModInfo(tomlInfoEntry, file, isEnabled);

if (result != null) goto ReturnResult;
}

if (fabricModInfoEntry != null)
if (fabricModInfoEntry != null)
{
result = await GetFabricModInfo(fabricModInfoEntry, file, isEnabled, ct);
goto ReturnResult;
}
}
catch (Exception e)
{
result = await GetFabricModInfo(fabricModInfoEntry, file, isEnabled, ct);
Console.WriteLine(e);
goto ReturnResult;
}

Expand All @@ -202,8 +233,9 @@ public static async IAsyncEnumerable<GameModResolvedInfo> ResolveModListAsync(
null,
"Unknown",
isEnabled);

ReturnResult:
result = result! with { LoaderType = GetModLoaderType(archive) };
yield return result;
}
}
Expand Down
43 changes: 43 additions & 0 deletions ProjBobcat/ProjBobcat/Class/Helper/ModrinthAPIHelper.cs
Original file line number Diff line number Diff line change
@@ -1,13 +1,26 @@
using System;
using System.Collections.Generic;
using System.Net.Http;
using System.Net.Http.Json;
using System.Text;
using System.Text.Json;
using System.Text.Json.Serialization;
using System.Threading;
using System.Threading.Tasks;
using ProjBobcat.Class.Model;
using ProjBobcat.Class.Model.Modrinth;

namespace ProjBobcat.Class.Helper;

#region Temp Models

record FileMatchRequestModel(string[] hashes, string algorithm, string[] loaders, string[] game_versions);

[JsonSerializable(typeof(FileMatchRequestModel))]
partial class ModrinthModelContext : JsonSerializerContext;

#endregion

public static class ModrinthAPIHelper
{
const string BaseUrl = "https://api.modrinth.com/v2";
Expand Down Expand Up @@ -110,4 +123,34 @@ await res.Content.ReadFromJsonAsync(ModrinthProjectDependencyInfoContext.Default

return resModel;
}

public static async Task<ModrinthVersionInfo?> GetVersionInfo(string versionId)
{
var reqUrl = $"{BaseUrl}/version/{versionId}";

using var res = await Get(reqUrl);
var resModel = await res.Content.ReadFromJsonAsync(ModrinthVersionInfoContext.Default.ModrinthVersionInfo);

return resModel;
}

public static async Task<IReadOnlyDictionary<string, ModrinthVersionInfo>?> TryMatchFile(
string[] hashes,
string algorithm,
string[] loaders,
string[] game_versions)
{
const string reqUrl = $"{BaseUrl}/version_files/update";

var data = JsonSerializer.Serialize(new FileMatchRequestModel(hashes, algorithm, loaders, game_versions),
ModrinthModelContext.Default.FileMatchRequestModel);

using var res = await HttpHelper.Post(reqUrl, data);


if (!res.IsSuccessStatusCode) return null;

return await res.Content.ReadFromJsonAsync(ModrinthVersionInfoContext.Default
.IReadOnlyDictionaryStringModrinthVersionInfo);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,15 @@

namespace ProjBobcat.Class.Model.CurseForge;

public class CurseForgeFileHashModel
{
[JsonPropertyName("algo")] public int Algorithm { get; init; }
[JsonPropertyName("value")] public string? Value { get; init; }
}

public class CurseForgeLatestFileModel
{
[JsonPropertyName("id")] public int Id { get; set; }
[JsonPropertyName("id")] public long Id { get; set; }

[JsonPropertyName("displayName")] public required string DisplayName { get; init; }

Expand All @@ -28,13 +34,18 @@ public class CurseForgeLatestFileModel

[JsonPropertyName("dependencies")] public CurseForgeDependencyModel[]? Dependencies { get; set; }

[JsonPropertyName("hashes")] public CurseForgeFileHashModel[]? Hashes { get; set; }

[JsonPropertyName("isAvailable")] public bool IsAvailable { get; set; }

[JsonPropertyName("modules")] public CurseForgeModuleModel[]? Modules { get; set; }

[JsonPropertyName("packageFingerprint")]
public long PackageFingerprint { get; set; }

[JsonPropertyName("fileFingerprint")]
public long FileFingerprint { get; set; }

[JsonPropertyName("gameVersions")] public required string[] GameVersions { get; init; }

[JsonPropertyName("sortableGameVersion")]
Expand Down
2 changes: 1 addition & 1 deletion ProjBobcat/ProjBobcat/Class/Model/DownloadSettings.cs
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ public class DownloadSettings
/// </summary>
public string? Host { get; init; }

public async ValueTask<byte[]> HashDataAsync(Stream stream, CancellationToken? token)
public async Task<byte[]> HashDataAsync(Stream stream, CancellationToken? token)
{
token ??= CancellationToken.None;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,4 +9,7 @@ public record GameModResolvedInfo(
string? Title,
string? Version,
string? ModType,
bool IsEnabled);
bool IsEnabled)
{
public ModLoaderType LoaderType { get; init; }
}
10 changes: 10 additions & 0 deletions ProjBobcat/ProjBobcat/Class/Model/ModLoaderType.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
namespace ProjBobcat.Class.Model;

public enum ModLoaderType
{
Forge,
NeoForge,
Fabric,
Quilt,
Unknown
}
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,4 @@ public class ModrinthCategoryInfo

[JsonSerializable(typeof(ModrinthCategoryInfo))]
[JsonSerializable(typeof(ModrinthCategoryInfo[]))]
partial class ModrinthCategoryInfoContext : JsonSerializerContext
{
}
partial class ModrinthCategoryInfoContext : JsonSerializerContext;
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using System.Text;
using System.Collections.Generic;
using System.Text;

namespace ProjBobcat.Class.Model.Modrinth;

Expand All @@ -7,19 +8,25 @@ public class ModrinthSearchOptions
public string? Name { get; init; }
public string? Category { get; init; }
public string Index { get; init; } = "relevance";
public string? ProjectType { get; init; } = "mod";
public string? ProjectType { get; init; }
public int? Offset { get; init; }
public int? Limit { get; set; }

public override string ToString()
{
var sb = new StringBuilder($"?query={Name ?? "any"}&index={Index}&facets=[");
var projType = $"[\"project_type:{ProjectType}\"]";
var sb = new StringBuilder($"?query={Name ?? "any"}&index={Index}");

if (!string.IsNullOrEmpty(Category)) sb.Append($"[\"categories:{Category}\"],");
var facets = new List<string>();

sb.Append(projType);
sb.Append(']');
if (!string.IsNullOrEmpty(Category))
facets.Add($"[\"categories:{Category}\"]");
if (!string.IsNullOrEmpty(ProjectType))
facets.Add($"[\"project_type:{ProjectType}\"]");

if (facets.Count > 0)
sb.Append("&facets=[")
.AppendJoin(',', facets)
.Append(']');

if (Offset != null) sb.Append($"&offset={Offset}");
if (Limit != null) sb.Append($"&limit={Limit}");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -77,4 +77,5 @@ public class ModrinthVersionInfo

[JsonSerializable(typeof(ModrinthVersionInfo))]
[JsonSerializable(typeof(ModrinthVersionInfo[]))]
[JsonSerializable(typeof(IReadOnlyDictionary<string, ModrinthVersionInfo>))]
partial class ModrinthVersionInfoContext : JsonSerializerContext;
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ public void Install()
InstallTaskAsync().Wait();
}

public static async ValueTask<(string? FileName, string? Url)> TryGuessModDownloadLink(long fileId)
public static async Task<(string? FileName, string? Url)> TryGuessModDownloadLink(long fileId)
{
try
{
Expand Down Expand Up @@ -69,7 +69,7 @@ public void Install()
}
}

async ValueTask<(bool, DownloadFile?)> TryGuessModDownloadLink(long fileId, string downloadPath)
async Task<(bool, DownloadFile?)> TryGuessModDownloadLink(long fileId, string downloadPath)
{
var pair = await TryGuessModDownloadLink(fileId);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -391,7 +391,7 @@ public override (List<NativeFileInfo>, List<FileInfo>) GetNatives(Library[] libr
Logging = rawVersion.Logging,
Id = rawVersion.Id,
InheritsFrom = rawVersion.InheritsFrom,
GameBaseVersion = GameVersionHelper.TryGetMcVersion([.. (inherits ?? []), rawVersion]) ?? id,
GameBaseVersion = GameVersionHelper.TryGetMcVersion([.. inherits ?? [], rawVersion]) ?? id,
DirName = id,
Name = id,
JavaVersion = rawVersion.JavaVersion,
Expand Down Expand Up @@ -559,7 +559,7 @@ public override (List<NativeFileInfo>, List<FileInfo>) GetNatives(Library[] libr
}
}

rawLibs = NativeReplaceHelper.Replace([rawVersion, ..inherits ?? []], rawLibs, NativeReplacementPolicy);
rawLibs = NativeReplaceHelper.Replace([rawVersion, .. inherits ?? []], rawLibs, NativeReplacementPolicy);

var libs = GetNatives([.. rawLibs]);

Expand All @@ -583,40 +583,28 @@ void ProcessProfile(VersionInfo result, string id)
if (LauncherProfileParser == null) return;

var gameId = id.ToGuidHash().ToString("N");
var (oldProfileKey, oldProfileModel) =
LauncherProfileParser.LauncherProfile.Profiles!
.FirstOrDefault(p => p.Key.Equals(gameId, StringComparison.OrdinalIgnoreCase));

var gamePath = Path.Combine(RootPath, GamePathHelper.GetGamePath(id));

if (string.IsNullOrEmpty(oldProfileKey) || oldProfileModel == null)
if (LauncherProfileParser.LauncherProfile.Profiles!.TryGetValue(gameId, out var oldProfileModel))
{
var gameProfile = new GameProfileModel
{
GameDir = gamePath,
LastVersionId = id,
Name = id,
Created = DateTime.Now
};

if (!string.IsNullOrEmpty(oldProfileKey) &&
LauncherProfileParser.LauncherProfile.Profiles!.ContainsKey(oldProfileKey))
{
LauncherProfileParser.LauncherProfile.Profiles![oldProfileKey] = gameProfile;
LauncherProfileParser.SaveProfile();
return;
}

LauncherProfileParser.LauncherProfile.Profiles!.Add(gameId, gameProfile);
result.Name = oldProfileModel.Name!;
oldProfileModel.GameDir = gamePath;
oldProfileModel.LastVersionId = id;
LauncherProfileParser.LauncherProfile.Profiles![gameId] = oldProfileModel;
LauncherProfileParser.SaveProfile();

return;
}

result.Name = oldProfileModel.Name!;
oldProfileModel.GameDir = gamePath;
oldProfileModel.LastVersionId = id;
LauncherProfileParser.LauncherProfile.Profiles![oldProfileKey] = oldProfileModel;
var gameProfile = new GameProfileModel
{
GameDir = gamePath,
LastVersionId = id,
Name = id,
Created = DateTime.Now
};

LauncherProfileParser.LauncherProfile.Profiles!.Add(gameId, gameProfile);
LauncherProfileParser.SaveProfile();
}
}

0 comments on commit 70302e8

Please sign in to comment.