Add Github Plugin
This commit is contained in:
parent
840379bfda
commit
dc116a33ab
@ -5,11 +5,11 @@ namespace ExtensiblePortfolioSite.SDK.Git
|
||||
{
|
||||
internal static class GitManager
|
||||
{
|
||||
private static readonly SortedDictionary<String, GitService> Providers = new ();
|
||||
private static readonly SortedDictionary<String, GitService> Providers = new();
|
||||
|
||||
public static void Register(String Service, IGitProvider Provider)
|
||||
{
|
||||
if(Providers.TryGetValue(Service, out GitService? GitService))
|
||||
if (Providers.TryGetValue(Service, out GitService? GitService))
|
||||
{
|
||||
GitService.addProvider(Provider);
|
||||
return;
|
||||
|
||||
@ -1,8 +1,4 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace ExtensiblePortfolioSite.SDK.Git
|
||||
{
|
||||
@ -30,6 +26,11 @@ namespace ExtensiblePortfolioSite.SDK.Git
|
||||
/// </summary>
|
||||
public readonly struct GitReference
|
||||
{
|
||||
public GitReference(GitReferenceKind Kind, String ReferenceString)
|
||||
{
|
||||
this.Kind = Kind;
|
||||
this.ReferenceString = ReferenceString;
|
||||
}
|
||||
/// <summary>
|
||||
/// Reference Kind
|
||||
/// </summary>
|
||||
|
||||
@ -1,10 +1,4 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace ExtensiblePortfolioSite.SDK.Git
|
||||
namespace ExtensiblePortfolioSite.SDK.Git
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents a Git Object Interface
|
||||
|
||||
@ -1,9 +1,4 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace ExtensiblePortfolioSite.SDK.Git
|
||||
{
|
||||
@ -26,6 +21,29 @@ namespace ExtensiblePortfolioSite.SDK.Git
|
||||
/// </summary>
|
||||
/// <param name="HeadOffset">How far to go back in the commit tree (default 0)</param>
|
||||
/// <returns>A commit</returns>
|
||||
public ICommit GetCommit(uint HeadOffset = 0);
|
||||
public ICommit? GetCommit(uint HeadOffset = 0);
|
||||
|
||||
/// <summary>
|
||||
/// Get a commit from the repository, defaults to latest
|
||||
/// </summary>
|
||||
/// <param name="HeadOffset">How far to go back in the commit tree (default 0)</param>
|
||||
/// <param name="Commit">Reference to the commit</param>
|
||||
/// <returns>If the commit could be found</returns>
|
||||
public bool TryGetCommit(uint HeadOffset, out ICommit? Commit);
|
||||
|
||||
/// <summary>
|
||||
/// Get a commit from the repository by it's hash
|
||||
/// </summary>
|
||||
/// <param name="Reference">Which commit to get from the repo</param>
|
||||
/// <returns>A commit</returns>
|
||||
public ICommit? GetCommitByRef(string Reference);
|
||||
|
||||
/// <summary>
|
||||
/// Get a commit from the repository, defaults to latest
|
||||
/// </summary>
|
||||
/// <param name="Reference">Which commit to get from the repo</param>
|
||||
/// <param name="Commit">Reference to the commit</param>
|
||||
/// <returns>If the commit could be found</returns>
|
||||
public bool TryGetCommitByRef(string Reference, out ICommit? Commit);
|
||||
}
|
||||
}
|
||||
|
||||
@ -28,6 +28,7 @@ namespace ExtensiblePortfolioSite.SDK.Plugins
|
||||
|
||||
List<Byte[]> PublicKeyTokens = new();
|
||||
PublicKeyTokens.Add(typeof(String).Assembly.GetName().GetPublicKeyToken()!); // Framework Libraries
|
||||
PublicKeyTokens.Add(typeof(System.Runtime.GCSettings).Assembly.GetName().GetPublicKeyToken()!);
|
||||
KnownPublicKeyTokens = PublicKeyTokens.ToArray();
|
||||
}
|
||||
|
||||
@ -42,11 +43,13 @@ namespace ExtensiblePortfolioSite.SDK.Plugins
|
||||
public static void LoadPlugins(string RootPath)
|
||||
{
|
||||
RootPath = Path.GetFullPath(RootPath);
|
||||
if(!Directory.Exists(RootPath))
|
||||
if (!Directory.Exists(RootPath))
|
||||
Directory.CreateDirectory(RootPath);
|
||||
LibraryPaths.Add(RootPath);
|
||||
foreach (String Dll in Directory.EnumerateFiles(RootPath, "*.dll", SearchOption.TopDirectoryOnly))
|
||||
{
|
||||
TryLoadPlugin(Path.GetFullPath(Dll, RootPath), out Plugin? _);
|
||||
}
|
||||
}
|
||||
public static Boolean TryLoadPlugin(string AsmPath, out Plugin? plugin)
|
||||
{
|
||||
@ -104,17 +107,17 @@ namespace ExtensiblePortfolioSite.SDK.Plugins
|
||||
TypeReference AttrType = MD.GetTypeReference((TypeReferenceHandle)Ctor.Parent);
|
||||
String AttrTypeName = MD.GetString(AttrType.Name);
|
||||
String AttrTypeNamespace = MD.GetString(AttrType.Namespace);
|
||||
|
||||
if (
|
||||
AttrType.ResolutionScope.Kind == HandleKind.AssemblyReference &&
|
||||
AttrTypeName == EPSPluginAttribute_type.Name &&
|
||||
AttrTypeNamespace == EPSPluginAttribute_type.Namespace
|
||||
)
|
||||
{
|
||||
|
||||
AssemblyReference AsmRef = MD.GetAssemblyReference((AssemblyReferenceHandle)AttrType.ResolutionScope);
|
||||
|
||||
String AsmName = MD.GetString(AsmRef.Name);
|
||||
if (AsmName == EPSPluginAttribute_type.Assembly.FullName)
|
||||
if (AsmName == EPSPluginAttribute_type.Assembly.GetName().Name)
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@ -185,7 +188,7 @@ namespace ExtensiblePortfolioSite.SDK.Plugins
|
||||
}
|
||||
}
|
||||
}
|
||||
throw new FileNotFoundException($"Unable to load Assembly '{AsmName}'");
|
||||
return null;
|
||||
}
|
||||
internal static IPluginUnmanagedLibrary? LoadUnmanagedLibrary(String Name)
|
||||
{
|
||||
|
||||
33
GithubPlugin/GithubCommit.cs
Normal file
33
GithubPlugin/GithubCommit.cs
Normal file
@ -0,0 +1,33 @@
|
||||
using ExtensiblePortfolioSite.SDK.Git;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Text.Json.Serialization;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace GithubPlugin
|
||||
{
|
||||
public class GithubCommit : ICommit
|
||||
{
|
||||
[JsonIgnore]
|
||||
public IReadOnlyCollection<string> ModifiedFiles { get; internal set; }
|
||||
|
||||
[JsonIgnore]
|
||||
public IRepository? Repository { get; internal set; }
|
||||
|
||||
[JsonIgnore]
|
||||
public IGitProvider? Provider { get; internal set; }
|
||||
|
||||
[JsonPropertyName("sha")]
|
||||
public string? Hash { get; private set; }
|
||||
|
||||
[JsonPropertyName("message")]
|
||||
public string? Description { get; private set; }
|
||||
|
||||
public GitReference GetReference()
|
||||
{
|
||||
return new GitReference(GitReferenceKind.Commit, $"{Repository.Owner}/{Repository.Name}/{Hash}");
|
||||
}
|
||||
}
|
||||
}
|
||||
13
GithubPlugin/GithubPlugin.csproj
Normal file
13
GithubPlugin/GithubPlugin.csproj
Normal file
@ -0,0 +1,13 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net6.0</TargetFramework>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\EPS.SDK\EPS.SDK.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
147
GithubPlugin/GithubProvider.cs
Normal file
147
GithubPlugin/GithubProvider.cs
Normal file
@ -0,0 +1,147 @@
|
||||
using ExtensiblePortfolioSite.SDK.Git;
|
||||
using System.Text.Json;
|
||||
using System.Text.RegularExpressions;
|
||||
|
||||
namespace GithubPlugin
|
||||
{
|
||||
[GitProvider("github.com")]
|
||||
public class GithubProvider : IGitProvider
|
||||
{
|
||||
private HttpClient httpClient = new HttpClient();
|
||||
|
||||
private Regex userPattern = new Regex("^(http(s)*:\\/\\/)(www\\.)*(github\\.com\\/[A-z]+)$", RegexOptions.Compiled | RegexOptions.IgnoreCase);
|
||||
private Regex repoPattern = new Regex("^(http(s)*:\\/\\/)(www\\.)*(github\\.com\\/[A-z]+\\/[A-z]+)$", RegexOptions.Compiled | RegexOptions.IgnoreCase);
|
||||
|
||||
public Dictionary<string, GithubUser> Users = new();
|
||||
public Dictionary<string, GithubRepo> Repositories = new();
|
||||
|
||||
public GithubProvider()
|
||||
{
|
||||
this.httpClient.BaseAddress = new("https://api.github.com/");
|
||||
this.httpClient.DefaultRequestHeaders.Add("User-Agent", "KoromaruKoruko");
|
||||
this.httpClient.DefaultRequestHeaders.Add("Authorization", "Bearer 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");
|
||||
}
|
||||
|
||||
public IGitObject GetByReference(GitReference Reference)
|
||||
{
|
||||
switch(Reference.Kind)
|
||||
{
|
||||
case GitReferenceKind.User:
|
||||
if(TryGetUserByName(Reference.ReferenceString, out IUser? user))
|
||||
return user!;
|
||||
else
|
||||
return null;
|
||||
case GitReferenceKind.Repository:
|
||||
{
|
||||
if (TryGetRepositoryByName(
|
||||
Reference.ReferenceString.Split('/')[0], Reference.ReferenceString.Split('/')[1], out IRepository? repo))
|
||||
return repo!;
|
||||
else
|
||||
return null;
|
||||
}
|
||||
case GitReferenceKind.Commit:
|
||||
{
|
||||
if (TryGetRepositoryByName(
|
||||
Reference.ReferenceString.Split('/')[0], Reference.ReferenceString.Split('/')[1], out IRepository? repo))
|
||||
{
|
||||
if (repo!.TryGetCommitByRef(Reference.ReferenceString.Split('/')[2], out ICommit? commit))
|
||||
return commit!;
|
||||
else
|
||||
return null;
|
||||
}
|
||||
else
|
||||
return null;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public bool TryGetRepositoryByName(string Username, string RepositoryName, out IRepository? Repository)
|
||||
{
|
||||
if (TryGetUserByName(Username, out IUser? User))
|
||||
return TryGetRepositoryByName(User!, RepositoryName, out Repository);
|
||||
Repository = null;
|
||||
return false;
|
||||
}
|
||||
|
||||
public bool TryGetRepositoryByName(IUser User, string RepositoryName, out IRepository? Repository)
|
||||
{
|
||||
if(User.GetType() == typeof(GithubUser))
|
||||
{
|
||||
if (Repositories.TryGetValue(RepositoryName, out GithubRepo? _repo))
|
||||
{
|
||||
Repository = _repo;
|
||||
return true;
|
||||
} else
|
||||
{
|
||||
var response = httpClient.GetAsync($"repos/{User.Name}/{RepositoryName}").Result;
|
||||
if (!response.IsSuccessStatusCode)
|
||||
{
|
||||
Repository = null;
|
||||
return false;
|
||||
}
|
||||
GithubRepo tempRepo = JsonSerializer.Deserialize<GithubRepo>(response.Content.ReadAsStream())!;
|
||||
tempRepo.Provider = this;
|
||||
tempRepo.Owner = User;
|
||||
Repository = tempRepo;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
Repository = null;
|
||||
return false;
|
||||
}
|
||||
|
||||
public bool TryGetUserByName(string Username, out IUser? User)
|
||||
{
|
||||
if(Users.TryGetValue(Username, out GithubUser? _user))
|
||||
{
|
||||
User = _user;
|
||||
return true;
|
||||
} else
|
||||
{
|
||||
var response = httpClient.GetAsync($"users/{Username}").Result;
|
||||
if(!response.IsSuccessStatusCode)
|
||||
{
|
||||
User = null;
|
||||
return false;
|
||||
}
|
||||
GithubUser tempUser = JsonSerializer.Deserialize<GithubUser>(response.Content.ReadAsStream())!;
|
||||
tempUser.Provider = this;
|
||||
User = tempUser;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
public bool TryGetRepositoryByURL(Uri RepoUrl, out IRepository? Repository)
|
||||
{
|
||||
if (repoPattern.IsMatch(RepoUrl.OriginalString))
|
||||
{
|
||||
var split = RepoUrl.OriginalString.Split("://")[1].Split('/');
|
||||
return TryGetRepositoryByName(split[1], split[2], out Repository);
|
||||
} else
|
||||
{
|
||||
Repository = null;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public bool TryGetUserByURL(Uri UserProfile, out IUser? User)
|
||||
{
|
||||
if (userPattern.IsMatch(UserProfile.OriginalString))
|
||||
{
|
||||
var split = UserProfile.OriginalString.Split("://")[1].Split('/');
|
||||
return TryGetUserByName(split[1], out User);
|
||||
}
|
||||
else
|
||||
{
|
||||
User = null;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public HttpResponseMessage GetAPIResource(string resourceLocation)
|
||||
{
|
||||
return httpClient.GetAsync(resourceLocation).Result;
|
||||
}
|
||||
}
|
||||
}
|
||||
106
GithubPlugin/GithubRepo.cs
Normal file
106
GithubPlugin/GithubRepo.cs
Normal file
@ -0,0 +1,106 @@
|
||||
using ExtensiblePortfolioSite.SDK.Git;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Text.Json;
|
||||
using System.Text.Json.Serialization;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace GithubPlugin
|
||||
{
|
||||
public class GithubRepo : IRepository
|
||||
{
|
||||
[JsonPropertyName("name")]
|
||||
public string Name { get; private set; }
|
||||
|
||||
[JsonPropertyName("description")]
|
||||
public string Description { get; private set; }
|
||||
|
||||
[JsonIgnore]
|
||||
public IUser Owner { get; internal set; }
|
||||
|
||||
[JsonIgnore]
|
||||
public IGitProvider Provider { get; internal set; }
|
||||
|
||||
public ICommit? GetCommit(uint HeadOffset = 0)
|
||||
{
|
||||
var response = Provider.GetAPIResource($"repos/{Owner.Name}/{Name}/commits");
|
||||
if(response.IsSuccessStatusCode)
|
||||
{
|
||||
JsonDocument json = JsonDocument.Parse(response.Content.ReadAsStream());
|
||||
JsonElement commitObject = json.RootElement.EnumerateArray().Skip((int)HeadOffset).First();
|
||||
GithubCommit commit = JsonSerializer.Deserialize<GithubCommit>(commitObject.GetProperty("commit"))!;
|
||||
commit.Provider = Provider;
|
||||
commit.Repository = this;
|
||||
List<string> tempFiles = new List<string>();
|
||||
JsonElement files = commitObject.GetProperty("files");
|
||||
foreach(JsonElement file in files.EnumerateArray())
|
||||
{
|
||||
tempFiles.Add(file.GetProperty("filename").GetString()!);
|
||||
}
|
||||
commit.ModifiedFiles = tempFiles;
|
||||
return commit;
|
||||
} else
|
||||
{
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public ICommit? GetCommitByRef(string reference)
|
||||
{
|
||||
var response = Provider.GetAPIResource($"repos/{Owner.Name}/{Name}/commits/{reference}");
|
||||
if (response.IsSuccessStatusCode)
|
||||
{
|
||||
JsonDocument json = JsonDocument.Parse(response.Content.ReadAsStream());
|
||||
JsonElement commitObject = json.RootElement;
|
||||
GithubCommit commit = JsonSerializer.Deserialize<GithubCommit>(commitObject.GetProperty("commit"))!;
|
||||
commit.Provider = Provider;
|
||||
commit.Repository = this;
|
||||
List<string> tempFiles = new List<string>();
|
||||
JsonElement files = commitObject.GetProperty("files");
|
||||
foreach (JsonElement file in files.EnumerateArray())
|
||||
{
|
||||
tempFiles.Add(file.GetProperty("filename").GetString()!);
|
||||
}
|
||||
commit.ModifiedFiles = tempFiles;
|
||||
return commit;
|
||||
}
|
||||
else
|
||||
{
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public GitReference GetReference()
|
||||
{
|
||||
return new GitReference(GitReferenceKind.Repository, $"{Owner}/{Name}");
|
||||
}
|
||||
|
||||
public bool TryGetCommit(uint HeadOffset, out ICommit? Commit)
|
||||
{
|
||||
var commit = GetCommit(HeadOffset);
|
||||
if (commit != null)
|
||||
{
|
||||
Commit = commit;
|
||||
return true;
|
||||
}
|
||||
|
||||
Commit = null;
|
||||
return false;
|
||||
}
|
||||
|
||||
public bool TryGetCommitByRef(string Reference, out ICommit? Commit)
|
||||
{
|
||||
var commit = GetCommitByRef(Reference);
|
||||
if (commit != null)
|
||||
{
|
||||
Commit = commit;
|
||||
return true;
|
||||
}
|
||||
|
||||
Commit = null;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
47
GithubPlugin/GithubUser.cs
Normal file
47
GithubPlugin/GithubUser.cs
Normal file
@ -0,0 +1,47 @@
|
||||
using ExtensiblePortfolioSite.SDK.Git;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Text.Json;
|
||||
using System.Text.Json.Serialization;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace GithubPlugin
|
||||
{
|
||||
public class GithubUser : IUser
|
||||
{
|
||||
[JsonPropertyName("login")]
|
||||
public string Name { get; private set; }
|
||||
|
||||
[JsonPropertyName("id")]
|
||||
public int Identifier { get; private set; }
|
||||
|
||||
[JsonPropertyName("avatar_url")]
|
||||
public string AvatarURL { get; private set; }
|
||||
|
||||
[JsonIgnore]
|
||||
public IGitProvider Provider { get; internal set; }
|
||||
|
||||
public GitReference GetReference()
|
||||
{
|
||||
return new GitReference(GitReferenceKind.User, $"{Name}");
|
||||
}
|
||||
|
||||
public IEnumerable<IRepository> GetUserRepositories()
|
||||
{
|
||||
var response = Provider.GetAPIResource($"users/{Name}/repos");
|
||||
if(response.IsSuccessStatusCode)
|
||||
{
|
||||
JsonDocument json = JsonDocument.Parse(response.Content.ReadAsStream());
|
||||
List<IRepository> ret = new List<IRepository>(json.RootElement.GetArrayLength());
|
||||
foreach(JsonElement repo in json.RootElement.EnumerateArray())
|
||||
{
|
||||
ret.Add(JsonSerializer.Deserialize<GithubRepo>(repo)!);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
return new List<IRepository>();
|
||||
}
|
||||
}
|
||||
}
|
||||
3
GithubPlugin/Properties/AssemblyInfo.cs
Normal file
3
GithubPlugin/Properties/AssemblyInfo.cs
Normal file
@ -0,0 +1,3 @@
|
||||
using ExtensiblePortfolioSite.SDK.Plugins;
|
||||
|
||||
[assembly: EPSPlugin("Github", false, 1, 0)]
|
||||
Loading…
Reference in New Issue
Block a user