1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
|
using System.Globalization;
using System.Net.Http.Json;
using System.Text;
using System.Text.Json.Nodes;
using LibMatrix.Extensions;
namespace MiniUtils.Utilities;
public class MscInfoProvider(MiniUtilsConfiguration config) {
private static Dictionary<int, MscInfo> _mscCache = new();
private static Dictionary<int, DateTime> _mscCacheExpiry = new();
private static long RatelimitRemaining = 60;
private static DateTime RatelimitReset = DateTime.UtcNow;
public async Task<MscInfo?> GetMscInfo(int id) {
var hc = new MatrixHttpClient() {
DefaultRequestHeaders = {
{ "User-Agent", "SynapseDataMiner" }
}
};
if(!string.IsNullOrWhiteSpace(config.GithubToken))
hc.DefaultRequestHeaders.Add("Authorization", $"Bearer {config.GithubToken}");
var response = await hc.GetAsync($"https://api.github.com/repos/matrix-org/matrix-spec-proposals/pulls/{id}");
if(response.Headers.Contains("X-RateLimit-Remaining")) {
RatelimitRemaining = long.Parse(response.Headers.GetValues("X-RateLimit-Remaining").First());
}
if (response.Headers.Contains("X-RateLimit-Reset")) {
var reset = long.Parse(response.Headers.GetValues("X-RateLimit-Reset").First());
RatelimitReset = DateTimeOffset.FromUnixTimeSeconds(reset).UtcDateTime;
}
if (!response.IsSuccessStatusCode) {
return _mscCache.GetValueOrDefault(id);
}
var data = await response.Content.ReadFromJsonAsync<JsonObject>();
var info = new MscInfo() {
Id = id,
Author = data?["user"]?["login"]?.ToString(),
Title = data?["title"]?.ToString(),
Url = data?["html_url"]?.ToString(),
State = data?["state"]?.ToString(),
Labels = data?["labels"]?.AsArray().Select(x => new MscInfo.LabelInfo() {
Name = x["name"]?.ToString(),
Color = x["color"]?.ToString()
}).ToList() ?? []
};
_mscCache[id] = info;
_mscCacheExpiry[id] = DateTime.UtcNow.AddMinutes(60);
return info;
}
public class MscInfo {
public int Id { get; set; }
public string Title { get; set; }
public string State { get; set; }
public string Author { get; set; }
public string Url { get; set; }
public List<LabelInfo> Labels { get; set; }
public class LabelInfo {
public string Name { get; set; }
public string Color { get; set; }
}
public string ToHtml() {
var sb = new StringBuilder();
sb.Append($"<a href=\"{Url}\">{Title}</a> by {Author} ({State})<br/>");
foreach (var label in Labels) {
sb.Append($"<font color=\"#{label.Color}\">" +
$"<span data-mx-bg-color=\"#{label.Color}\" data-mx-color=\"{GetContrastingForegroundColor(label.Color)}\">{label.Name}</span>" +
$"</font> \n");
}
return sb + "\n";
}
private static string GetContrastingForegroundColor(string backgroundColor) {
var color = backgroundColor.Replace("#", "");
var r = int.Parse(color.Substring(0, 2), NumberStyles.HexNumber);
var g = int.Parse(color.Substring(2, 2), NumberStyles.HexNumber);
var b = int.Parse(color.Substring(4, 2), NumberStyles.HexNumber);
// var brightness = Math.Sqrt(0.299 * r * r + 0.587 * g * g + 0.114 * b * b);
var brightness = Math.Sqrt(0.299 * r * r + 0.587 * g * g + 0.114 * b * b);
return brightness < 130 ? "#ffffff" : "#000000";
}
}
}
|