com.alicizax.unity.packagem.../Editor/PackageManager/RepositoryDataFetcher.cs

204 lines
6.3 KiB
C#
Raw Normal View History

2025-02-20 10:48:57 +08:00
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Networking;
using Newtonsoft.Json;
using Unity.EditorCoroutines.Editor;
using UnityEditor;
namespace AlicizaX.PackageManager.Editor
{
public enum PackageState
{
UnInstall,
InstallLocal,
Install,
Update
}
[Serializable]
public class RepositoryPackageData
{
// Repository info
public string name;
public string description;
public string cloneUrl;
public string htmlUrl;
public string updatedAt;
// Package info
public string displayName;
public string version;
public string unityVersion;
public string category;
public string packageDescription;
public string authorName;
public PackageState PackageState;
}
[Serializable]
public class RepoApiResponse
{
public bool ok;
public List<RepoItem> data;
}
[Serializable]
public class RepoItem
{
public string name;
public string description;
public string clone_url;
public string html_url;
public string updated_at;
public Owner owner;
[Serializable]
public class Owner
{
public string login;
}
}
[Serializable]
public class PackageJsonResponse
{
public string name;
public string displayName;
public string category;
public string description;
public string version;
public string unity;
public Author author;
[Serializable]
public class Author
{
public string name;
}
}
public static class RepositoryDataFetcher
{
private const string BaseApiUrl = "http://101.34.252.46:3000/api/v1/repos/search?q=unity&topic=false";
private const string PackageJsonPath = "/raw/branch/main/package.json";
public static void FetchRepositoryData(Action<List<RepositoryPackageData>> callback)
{
2025-02-20 11:44:00 +08:00
EditorPrefs.SetString("PackageUpdateDate", DateTime.Now.ToString());
2025-02-20 10:48:57 +08:00
EditorCoroutineUtility.StartCoroutineOwnerless(FetchDataRoutine(callback));
}
private static IEnumerator FetchDataRoutine(Action<List<RepositoryPackageData>> callback)
{
// 第一阶段:获取仓库列表
using (var request = CreateWebRequest(BaseApiUrl))
{
yield return request.SendWebRequest();
if (!HandleRequestError(request, "Repository request failed"))
{
callback?.Invoke(null);
yield break;
}
var repoResponse = JsonConvert.DeserializeObject<RepoApiResponse>(request.downloadHandler.text);
if (!repoResponse.ok || repoResponse.data == null)
{
Debug.LogError("Invalid repository response data");
callback?.Invoke(null);
yield break;
}
var results = new List<RepositoryPackageData>();
var pendingRequests = new Queue<RepoItem>(repoResponse.data);
// 第二阶段逐个获取package.json信息
while (pendingRequests.Count > 0)
{
var repo = pendingRequests.Dequeue();
var packageData = CreateBaseRepositoryData(repo);
var packageUrl = repo.html_url + PackageJsonPath;
using (var packageRequest = CreateWebRequest(packageUrl))
{
yield return packageRequest.SendWebRequest();
if (HandleRequestError(packageRequest, $"Package request failed for {repo.name}"))
{
try
{
var packageInfo = JsonConvert.DeserializeObject<PackageJsonResponse>(
packageRequest.downloadHandler.text);
UpdateWithPackageInfo(ref packageData, packageInfo);
}
catch (Exception e)
{
Debug.LogError($"JSON parse error for {repo.name}: {e.Message}");
}
}
results.Add(packageData);
}
// 防止同时发起太多请求,每帧处理一个
yield return null;
}
callback?.Invoke(results);
}
}
private static UnityWebRequest CreateWebRequest(string url)
{
var request = new UnityWebRequest(url, "GET");
request.downloadHandler = new DownloadHandlerBuffer();
request.SetRequestHeader("accept", "application/json");
return request;
}
private static bool HandleRequestError(UnityWebRequest request, string errorMessage)
{
if (request.result != UnityWebRequest.Result.Success)
{
Debug.LogError($"{errorMessage}: {request.error}");
return false;
}
return true;
}
private static RepositoryPackageData CreateBaseRepositoryData(RepoItem repo)
{
return new RepositoryPackageData
{
name = repo.name,
description = repo.description,
cloneUrl = repo.clone_url,
htmlUrl = repo.html_url,
updatedAt = repo.updated_at
};
}
private static void UpdateWithPackageInfo(ref RepositoryPackageData data, PackageJsonResponse package)
{
if (package == null) return;
2025-02-20 11:44:00 +08:00
data.name = package.name;
2025-02-20 10:48:57 +08:00
data.displayName = package.displayName;
data.version = package.version;
data.unityVersion = package.unity;
data.category = package.category;
data.packageDescription = package.description;
if (package.author != null)
{
data.authorName = package.author.name;
}
}
}
}