about summary refs log tree commit diff
path: root/MiniUtils/Utilities/MscInfoProvider.cs
blob: 74788dc665f24ceff9872b9ba865f5a2e0940645 (plain) (blame)
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";
        }
    }
}