/
Publisher.cs
121 lines (101 loc) · 4.83 KB
/
Publisher.cs
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
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net.Http;
using System.Reflection.Metadata;
using System.Threading;
using System.Threading.Tasks;
using Mastonet;
using Mastonet.Entities;
using Octokit;
namespace MastodonGitHubBot;
internal class Publisher
{
private readonly Log _log;
private readonly Server _server;
private readonly MastodonClient _mastodon;
private readonly GitHubClient _github;
private readonly ApiOptions _firstPageApiOptions;
private readonly RepositoryIssueRequest _latestIssuesConfiguration;
private readonly bool _debug;
public static async Task<Publisher> CreateAsync(Log log, HttpClient sharedHttpClient, Settings settings, Server server)
{
var mastodon = await Mastodon.GetClientAsync(log, server, sharedHttpClient);
var github = await GitHub.GetClientAsync(log, server);
return new Publisher(log, settings, server, mastodon, github);
}
internal Publisher(Log log, Settings settings, Server server, MastodonClient mastodon, GitHubClient github)
{
_log = log ?? throw new ArgumentNullException(nameof(log));
_server = server;
_mastodon = mastodon ?? throw new ArgumentNullException(nameof(mastodon));
_github = github ?? throw new ArgumentNullException(nameof(github));
_firstPageApiOptions = new() { PageCount = 1, PageSize = 250, StartPage = 1 };
_latestIssuesConfiguration = new() { SortDirection = SortDirection.Descending, State = ItemStateFilter.Open, SortProperty = IssueSort.Created };
_debug = settings.Debug;
}
private void PrintStatus()
{
// Prior to first API call, this will be null, because it only deals with the last call.
ApiInfo? apiInfo = _github.GetLastApiInfo();
RateLimit? rateLimit = apiInfo?.RateLimit;
_log.WriteInfo($"How many requests per hour?: {rateLimit?.Limit}{Environment.NewLine}" +
$"How many requests left?: {rateLimit?.Remaining}{Environment.NewLine}" +
$"When does the limit reset?: {rateLimit?.Reset}{Environment.NewLine}");
Console.WriteLine("----------");
}
public async Task PublishAsync()
{
IOrderedEnumerable<Issue> issues = await GetUnpublishedIssuesAsync();
_log.WriteInfo($"Found {issues.Count()} unpublished issues.");
foreach (Issue issue in issues)
{
string text = $"{issue.Title} ({issue.Number}) {issue.HtmlUrl}";
_log.WriteSuccess($"{issue.CreatedAt:yy/MM/dd HH:mm:ss} - {text}");
if (!_debug)
{
Status status = await _mastodon.PublishStatus(text, _server.Visibility);
_log.WriteSuccess($"Toot published to Mastodon. ID: {status.Url}");
Thread.Sleep(1000);
}
_server.GitHubLatestIssueNumber = issue.Number;
}
PrintStatus();
}
// Includes PRs
private Issue GetLastPublishedIssue(IEnumerable<Issue> latestIssues)
{
Issue? lastPublishedIssue = null;
if (_server.GitHubLatestIssueNumber != 0)
{
for (int number = _server.GitHubLatestIssueNumber; number < (_server.GitHubLatestIssueNumber + 10); number++)
{
lastPublishedIssue = latestIssues.SingleOrDefault(i => i.Number == number);
if (lastPublishedIssue != null)
{
_log.WriteInfo($"Found the specified latest issue: {number}");
break;
}
// Can be null if it's too old and latestIssues does not contain it
_log.WriteError($"Unable to find the specified latest issue: {number}. Trying with {number + 1} now...");
}
}
if (lastPublishedIssue == null)
{
_log.WriteError($"Unable to find the the specified latest issue or the next 10 after that: {_server.GitHubLatestIssueNumber}");
lastPublishedIssue = latestIssues.Any() ? latestIssues.First() : throw new NullReferenceException("No issues found.");
_log.WriteWarning($"Assigning the latest found issue as the latest one: {lastPublishedIssue.Number}");
_server.GitHubLatestIssueNumber = lastPublishedIssue.Number;
}
return lastPublishedIssue;
}
// Includes PRs
private async Task<IOrderedEnumerable<Issue>> GetUnpublishedIssuesAsync()
{
IReadOnlyList<Issue> latestIssues = await _github.Issue.GetAllForRepository(_server.GitHubRepoOrg, _server.GitHubRepoName, _latestIssuesConfiguration, _firstPageApiOptions);
Issue? lastPublishedIssue = GetLastPublishedIssue(latestIssues);
return latestIssues
.Where(i => i.Number > lastPublishedIssue.Number)
.OrderBy(i => i.Number); // Re-sorted ascending so they get published in order of creation
}
}