com.alicizax.unity.packagem.../Editor/PackageManager/RepositoryDataFetcher.cs
2025-02-20 11:44:00 +08:00

204 lines
6.3 KiB
C#
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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)
{
EditorPrefs.SetString("PackageUpdateDate", DateTime.Now.ToString());
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;
data.name = package.name;
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;
}
}
}
}