refactor: Remove redundant code and consolidate JsonSerializerOptions
- Remove unused GetRepoLanguagesAsync method from GitHubClient - Remove unused IsFakeAccreditor and FakeAccreditors from DiplomaMills - Remove unused CompanyVerificationFlagPenalty constant from ProcessCVCheckJob - Remove unused SkillVerification properties (TotalLinesOfCode, FirstUsed, LastUsed) - Remove unused CompanyMatchRequest record from SemanticMatchResult - Add JsonDefaults.ApiClient and consolidate duplicate JsonSerializerOptions across API clients - Remove ApiTester tool containing hardcoded API credentials (security fix) 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
@@ -135,24 +135,6 @@ public static class DiplomaMills
|
|||||||
"distance learning university", // be careful - some are legit
|
"distance learning university", // be careful - some are legit
|
||||||
];
|
];
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Fake accreditation bodies used by diploma mills.
|
|
||||||
/// </summary>
|
|
||||||
public static readonly HashSet<string> FakeAccreditors = new(StringComparer.OrdinalIgnoreCase)
|
|
||||||
{
|
|
||||||
"World Association of Universities and Colleges",
|
|
||||||
"WAUC",
|
|
||||||
"International Accreditation Agency",
|
|
||||||
"Universal Accreditation Council",
|
|
||||||
"Board of Online Universities Accreditation",
|
|
||||||
"International Council for Open and Distance Education",
|
|
||||||
"World Online Education Accrediting Commission",
|
|
||||||
"Central States Consortium of Colleges and Schools",
|
|
||||||
"American Council of Private Colleges and Universities",
|
|
||||||
"Association of Distance Learning Programs",
|
|
||||||
"International Distance Education Certification Agency",
|
|
||||||
};
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Check if an institution is a known diploma mill.
|
/// Check if an institution is a known diploma mill.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -196,15 +178,4 @@ public static class DiplomaMills
|
|||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Check if an accreditor is known to be fake.
|
|
||||||
/// </summary>
|
|
||||||
public static bool IsFakeAccreditor(string accreditorName)
|
|
||||||
{
|
|
||||||
if (string.IsNullOrWhiteSpace(accreditorName))
|
|
||||||
return false;
|
|
||||||
|
|
||||||
return FakeAccreditors.Contains(accreditorName.Trim());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
using System.Text.Json;
|
using System.Text.Json;
|
||||||
|
using System.Text.Json.Serialization;
|
||||||
|
|
||||||
namespace RealCV.Application.Helpers;
|
namespace RealCV.Application.Helpers;
|
||||||
|
|
||||||
@@ -16,4 +17,13 @@ public static class JsonDefaults
|
|||||||
PropertyNameCaseInsensitive = true,
|
PropertyNameCaseInsensitive = true,
|
||||||
WriteIndented = true
|
WriteIndented = true
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Options for consuming external APIs - case insensitive with null handling.
|
||||||
|
/// </summary>
|
||||||
|
public static readonly JsonSerializerOptions ApiClient = new()
|
||||||
|
{
|
||||||
|
PropertyNameCaseInsensitive = true,
|
||||||
|
DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -37,9 +37,6 @@ public sealed record SkillVerification
|
|||||||
public required string ClaimedSkill { get; init; }
|
public required string ClaimedSkill { get; init; }
|
||||||
public required bool IsVerified { get; init; }
|
public required bool IsVerified { get; init; }
|
||||||
public int RepoCount { get; init; }
|
public int RepoCount { get; init; }
|
||||||
public int TotalLinesOfCode { get; init; }
|
|
||||||
public DateOnly? FirstUsed { get; init; }
|
|
||||||
public DateOnly? LastUsed { get; init; }
|
|
||||||
public string? Notes { get; init; }
|
public string? Notes { get; init; }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -10,12 +10,6 @@ public record SemanticMatchResult
|
|||||||
public bool IsMatch => ConfidenceScore >= 70;
|
public bool IsMatch => ConfidenceScore >= 70;
|
||||||
}
|
}
|
||||||
|
|
||||||
public record CompanyMatchRequest
|
|
||||||
{
|
|
||||||
public required string CVCompanyName { get; init; }
|
|
||||||
public required List<CompanyCandidate> Candidates { get; init; }
|
|
||||||
}
|
|
||||||
|
|
||||||
public record CompanyCandidate
|
public record CompanyCandidate
|
||||||
{
|
{
|
||||||
public required string CompanyName { get; init; }
|
public required string CompanyName { get; init; }
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
using System.Net.Http.Json;
|
using System.Net.Http.Json;
|
||||||
using System.Text.Json;
|
|
||||||
using System.Text.Json.Serialization;
|
using System.Text.Json.Serialization;
|
||||||
using Microsoft.Extensions.Logging;
|
using Microsoft.Extensions.Logging;
|
||||||
using Microsoft.Extensions.Options;
|
using Microsoft.Extensions.Options;
|
||||||
|
using RealCV.Application.Helpers;
|
||||||
|
|
||||||
namespace RealCV.Infrastructure.Clients;
|
namespace RealCV.Infrastructure.Clients;
|
||||||
|
|
||||||
@@ -44,7 +44,7 @@ public sealed class FcaRegisterClient
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
return await response.Content.ReadFromJsonAsync<FcaIndividualResponse>(JsonOptions);
|
return await response.Content.ReadFromJsonAsync<FcaIndividualResponse>(JsonDefaults.ApiClient);
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
@@ -70,7 +70,7 @@ public sealed class FcaRegisterClient
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
var wrapper = await response.Content.ReadFromJsonAsync<FcaIndividualDetailsWrapper>(JsonOptions);
|
var wrapper = await response.Content.ReadFromJsonAsync<FcaIndividualDetailsWrapper>(JsonDefaults.ApiClient);
|
||||||
return wrapper?.Data?.FirstOrDefault();
|
return wrapper?.Data?.FirstOrDefault();
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
@@ -94,7 +94,7 @@ public sealed class FcaRegisterClient
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
return await response.Content.ReadFromJsonAsync<FcaFirmResponse>(JsonOptions);
|
return await response.Content.ReadFromJsonAsync<FcaFirmResponse>(JsonDefaults.ApiClient);
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
@@ -102,12 +102,6 @@ public sealed class FcaRegisterClient
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static readonly JsonSerializerOptions JsonOptions = new()
|
|
||||||
{
|
|
||||||
PropertyNameCaseInsensitive = true,
|
|
||||||
DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public class FcaOptions
|
public class FcaOptions
|
||||||
|
|||||||
@@ -1,9 +1,9 @@
|
|||||||
using System.Net.Http.Headers;
|
using System.Net.Http.Headers;
|
||||||
using System.Net.Http.Json;
|
using System.Net.Http.Json;
|
||||||
using System.Text.Json;
|
|
||||||
using System.Text.Json.Serialization;
|
using System.Text.Json.Serialization;
|
||||||
using Microsoft.Extensions.Logging;
|
using Microsoft.Extensions.Logging;
|
||||||
using Microsoft.Extensions.Options;
|
using Microsoft.Extensions.Options;
|
||||||
|
using RealCV.Application.Helpers;
|
||||||
|
|
||||||
namespace RealCV.Infrastructure.Clients;
|
namespace RealCV.Infrastructure.Clients;
|
||||||
|
|
||||||
@@ -49,7 +49,7 @@ public sealed class GitHubApiClient
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
return await response.Content.ReadFromJsonAsync<GitHubUser>(JsonOptions);
|
return await response.Content.ReadFromJsonAsync<GitHubUser>(JsonDefaults.ApiClient);
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
@@ -76,7 +76,7 @@ public sealed class GitHubApiClient
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
var pageRepos = await response.Content.ReadFromJsonAsync<List<GitHubRepo>>(JsonOptions);
|
var pageRepos = await response.Content.ReadFromJsonAsync<List<GitHubRepo>>(JsonDefaults.ApiClient);
|
||||||
|
|
||||||
if (pageRepos == null || pageRepos.Count == 0)
|
if (pageRepos == null || pageRepos.Count == 0)
|
||||||
{
|
{
|
||||||
@@ -107,28 +107,6 @@ public sealed class GitHubApiClient
|
|||||||
return repos;
|
return repos;
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<Dictionary<string, int>?> GetRepoLanguagesAsync(string owner, string repo)
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
var url = $"repos/{Uri.EscapeDataString(owner)}/{Uri.EscapeDataString(repo)}/languages";
|
|
||||||
|
|
||||||
var response = await _httpClient.GetAsync(url);
|
|
||||||
|
|
||||||
if (!response.IsSuccessStatusCode)
|
|
||||||
{
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
return await response.Content.ReadFromJsonAsync<Dictionary<string, int>>(JsonOptions);
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
_logger.LogError(ex, "Error getting languages for repo: {Owner}/{Repo}", owner, repo);
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public async Task<GitHubUserSearchResponse?> SearchUsersAsync(string query, int perPage = 30)
|
public async Task<GitHubUserSearchResponse?> SearchUsersAsync(string query, int perPage = 30)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
@@ -143,7 +121,7 @@ public sealed class GitHubApiClient
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
return await response.Content.ReadFromJsonAsync<GitHubUserSearchResponse>(JsonOptions);
|
return await response.Content.ReadFromJsonAsync<GitHubUserSearchResponse>(JsonDefaults.ApiClient);
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
@@ -151,12 +129,6 @@ public sealed class GitHubApiClient
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static readonly JsonSerializerOptions JsonOptions = new()
|
|
||||||
{
|
|
||||||
PropertyNameCaseInsensitive = true,
|
|
||||||
DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public class GitHubOptions
|
public class GitHubOptions
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
using System.Net.Http.Headers;
|
using System.Net.Http.Headers;
|
||||||
using System.Net.Http.Json;
|
using System.Net.Http.Json;
|
||||||
using System.Text.Json;
|
|
||||||
using System.Text.Json.Serialization;
|
using System.Text.Json.Serialization;
|
||||||
using Microsoft.Extensions.Logging;
|
using Microsoft.Extensions.Logging;
|
||||||
|
using RealCV.Application.Helpers;
|
||||||
|
|
||||||
namespace RealCV.Infrastructure.Clients;
|
namespace RealCV.Infrastructure.Clients;
|
||||||
|
|
||||||
@@ -40,7 +40,7 @@ public sealed class OrcidClient
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
return await response.Content.ReadFromJsonAsync<OrcidSearchResponse>(JsonOptions);
|
return await response.Content.ReadFromJsonAsync<OrcidSearchResponse>(JsonDefaults.ApiClient);
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
@@ -69,7 +69,7 @@ public sealed class OrcidClient
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
return await response.Content.ReadFromJsonAsync<OrcidRecord>(JsonOptions);
|
return await response.Content.ReadFromJsonAsync<OrcidRecord>(JsonDefaults.ApiClient);
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
@@ -92,7 +92,7 @@ public sealed class OrcidClient
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
return await response.Content.ReadFromJsonAsync<OrcidWorks>(JsonOptions);
|
return await response.Content.ReadFromJsonAsync<OrcidWorks>(JsonDefaults.ApiClient);
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
@@ -115,7 +115,7 @@ public sealed class OrcidClient
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
return await response.Content.ReadFromJsonAsync<OrcidEmployments>(JsonOptions);
|
return await response.Content.ReadFromJsonAsync<OrcidEmployments>(JsonDefaults.ApiClient);
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
@@ -138,7 +138,7 @@ public sealed class OrcidClient
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
return await response.Content.ReadFromJsonAsync<OrcidEducations>(JsonOptions);
|
return await response.Content.ReadFromJsonAsync<OrcidEducations>(JsonDefaults.ApiClient);
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
@@ -155,12 +155,6 @@ public sealed class OrcidClient
|
|||||||
.Trim();
|
.Trim();
|
||||||
return orcidId;
|
return orcidId;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static readonly JsonSerializerOptions JsonOptions = new()
|
|
||||||
{
|
|
||||||
PropertyNameCaseInsensitive = true,
|
|
||||||
DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Response models
|
// Response models
|
||||||
|
|||||||
@@ -24,7 +24,6 @@ public sealed class ProcessCVCheckJob
|
|||||||
private const int BaseScore = 100;
|
private const int BaseScore = 100;
|
||||||
private const int UnverifiedCompanyPenalty = 10;
|
private const int UnverifiedCompanyPenalty = 10;
|
||||||
private const int ImplausibleJobTitlePenalty = 15;
|
private const int ImplausibleJobTitlePenalty = 15;
|
||||||
private const int CompanyVerificationFlagPenalty = 5; // Base penalty for company flags, actual from flag.ScoreImpact
|
|
||||||
private const int RapidProgressionPenalty = 10;
|
private const int RapidProgressionPenalty = 10;
|
||||||
private const int EarlyCareerSeniorRolePenalty = 10;
|
private const int EarlyCareerSeniorRolePenalty = 10;
|
||||||
private const int GapMonthPenalty = 1;
|
private const int GapMonthPenalty = 1;
|
||||||
|
|||||||
@@ -1,10 +0,0 @@
|
|||||||
<Project Sdk="Microsoft.NET.Sdk">
|
|
||||||
|
|
||||||
<PropertyGroup>
|
|
||||||
<OutputType>Exe</OutputType>
|
|
||||||
<TargetFramework>net8.0</TargetFramework>
|
|
||||||
<ImplicitUsings>enable</ImplicitUsings>
|
|
||||||
<Nullable>enable</Nullable>
|
|
||||||
</PropertyGroup>
|
|
||||||
|
|
||||||
</Project>
|
|
||||||
@@ -1,123 +0,0 @@
|
|||||||
using System.Net.Http.Headers;
|
|
||||||
using System.Text.Json;
|
|
||||||
|
|
||||||
Console.WriteLine("=== RealCV API Integration Tester ===\n");
|
|
||||||
|
|
||||||
// Test 1: FCA Register API
|
|
||||||
Console.WriteLine("1. Testing FCA Register API...");
|
|
||||||
try
|
|
||||||
{
|
|
||||||
var fcaClient = new HttpClient();
|
|
||||||
fcaClient.BaseAddress = new Uri("https://register.fca.org.uk/services/V0.1/");
|
|
||||||
fcaClient.DefaultRequestHeaders.Add("X-Auth-Email", "peter.foster@ukdataservices.co.uk");
|
|
||||||
fcaClient.DefaultRequestHeaders.Add("X-Auth-Key", "9ae1aee51e5c717a1135775501c89075");
|
|
||||||
|
|
||||||
var fcaResponse = await fcaClient.GetAsync("Individuals?q=John%20Smith&page=1");
|
|
||||||
Console.WriteLine($" Status: {fcaResponse.StatusCode}");
|
|
||||||
|
|
||||||
if (fcaResponse.IsSuccessStatusCode)
|
|
||||||
{
|
|
||||||
var content = await fcaResponse.Content.ReadAsStringAsync();
|
|
||||||
Console.WriteLine($" ✓ FCA API working");
|
|
||||||
using var doc = JsonDocument.Parse(content);
|
|
||||||
if (doc.RootElement.TryGetProperty("Data", out var data) && data.ValueKind == JsonValueKind.Array)
|
|
||||||
{
|
|
||||||
Console.WriteLine($" Found {data.GetArrayLength()} individuals matching 'John Smith'");
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
Console.WriteLine($" Response: {content.Substring(0, Math.Min(200, content.Length))}");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
Console.WriteLine($" ✗ Error: {fcaResponse.StatusCode}");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
Console.WriteLine($" ✗ Error: {ex.Message}");
|
|
||||||
}
|
|
||||||
|
|
||||||
Console.WriteLine();
|
|
||||||
|
|
||||||
// Test 2: ORCID API
|
|
||||||
Console.WriteLine("2. Testing ORCID API...");
|
|
||||||
try
|
|
||||||
{
|
|
||||||
var orcidClient = new HttpClient();
|
|
||||||
orcidClient.BaseAddress = new Uri("https://pub.orcid.org/v3.0/");
|
|
||||||
orcidClient.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
|
|
||||||
|
|
||||||
// Get a known ORCID record directly
|
|
||||||
var orcidResponse = await orcidClient.GetAsync("0000-0001-5109-3700/record");
|
|
||||||
Console.WriteLine($" Status: {orcidResponse.StatusCode}");
|
|
||||||
|
|
||||||
if (orcidResponse.IsSuccessStatusCode)
|
|
||||||
{
|
|
||||||
var content = await orcidResponse.Content.ReadAsStringAsync();
|
|
||||||
Console.WriteLine($" ✓ ORCID API working");
|
|
||||||
using var doc = JsonDocument.Parse(content);
|
|
||||||
if (doc.RootElement.TryGetProperty("person", out var person) &&
|
|
||||||
person.TryGetProperty("name", out var name))
|
|
||||||
{
|
|
||||||
var givenName = "";
|
|
||||||
var familyName = "";
|
|
||||||
if (name.TryGetProperty("given-names", out var gn) && gn.TryGetProperty("value", out var gnv))
|
|
||||||
givenName = gnv.GetString() ?? "";
|
|
||||||
if (name.TryGetProperty("family-name", out var fn) && fn.TryGetProperty("value", out var fnv))
|
|
||||||
familyName = fnv.GetString() ?? "";
|
|
||||||
Console.WriteLine($" Retrieved record for: {givenName} {familyName}");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
Console.WriteLine($" ✗ Error: {orcidResponse.StatusCode}");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
Console.WriteLine($" ✗ Error: {ex.Message}");
|
|
||||||
}
|
|
||||||
|
|
||||||
Console.WriteLine();
|
|
||||||
|
|
||||||
// Test 3: GitHub API
|
|
||||||
Console.WriteLine("3. Testing GitHub API...");
|
|
||||||
try
|
|
||||||
{
|
|
||||||
var githubClient = new HttpClient();
|
|
||||||
githubClient.BaseAddress = new Uri("https://api.github.com/");
|
|
||||||
githubClient.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/vnd.github+json"));
|
|
||||||
githubClient.DefaultRequestHeaders.Add("X-GitHub-Api-Version", "2022-11-28");
|
|
||||||
githubClient.DefaultRequestHeaders.UserAgent.ParseAdd("RealCV/1.0");
|
|
||||||
|
|
||||||
var githubResponse = await githubClient.GetAsync("users/torvalds");
|
|
||||||
Console.WriteLine($" Status: {githubResponse.StatusCode}");
|
|
||||||
|
|
||||||
if (githubResponse.IsSuccessStatusCode)
|
|
||||||
{
|
|
||||||
var content = await githubResponse.Content.ReadAsStringAsync();
|
|
||||||
Console.WriteLine($" ✓ GitHub API working");
|
|
||||||
using var doc = JsonDocument.Parse(content);
|
|
||||||
var name = doc.RootElement.GetProperty("name").GetString();
|
|
||||||
var repos = doc.RootElement.GetProperty("public_repos").GetInt32();
|
|
||||||
var followers = doc.RootElement.GetProperty("followers").GetInt32();
|
|
||||||
Console.WriteLine($" User: {name}, Repos: {repos}, Followers: {followers}");
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
Console.WriteLine($" ✗ Error: {githubResponse.StatusCode}");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (githubResponse.Headers.TryGetValues("X-RateLimit-Remaining", out var remaining))
|
|
||||||
{
|
|
||||||
Console.WriteLine($" Rate limit remaining: {remaining.First()}");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
Console.WriteLine($" ✗ Error: {ex.Message}");
|
|
||||||
}
|
|
||||||
|
|
||||||
Console.WriteLine("\n=== Tests complete ===");
|
|
||||||
Reference in New Issue
Block a user