204 lines
6.3 KiB
C#
204 lines
6.3 KiB
C#
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;
|
||
}
|
||
}
|
||
}
|
||
}
|