-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathProgram.cs
134 lines (116 loc) · 4.87 KB
/
Program.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
122
123
124
125
126
127
128
129
130
131
132
133
134
using System.Text.RegularExpressions;
using System.Web;
using Microsoft.Extensions.Configuration;
namespace Open_Rails_Triage_Bot
{
class Program
{
static void Main(string[] args)
{
var config = new CommandLineParser.Arguments.FileArgument('c', "config")
{
ForcedDefaultValue = new FileInfo("config.json")
};
var commandLineParser = new CommandLineParser.CommandLineParser()
{
Arguments = {
config,
}
};
try
{
commandLineParser.ParseCommandLine(args);
AsyncMain(new ConfigurationBuilder()
.AddJsonFile(config.Value.FullName, true)
.Build()).Wait();
}
catch (CommandLineParser.Exceptions.CommandLineException e)
{
Console.WriteLine(e.Message);
}
}
static async Task AsyncMain(IConfigurationRoot config)
{
var launchpadConfig = config.GetSection("launchpad");
var loggedIn = await LogInToLaunchpad(launchpadConfig);
if (!loggedIn)
{
return;
}
var launchpad = new Launchpad.Cache(launchpadConfig["oauth_token"], launchpadConfig["oauth_token_secret"]);
var project = await launchpad.GetProject($"https://api.launchpad.net/devel/{launchpadConfig["project"]}");
foreach (var bugTask in await project.GetRecentBugTasks())
{
var bug = await bugTask.GetBug();
var attachments = await bug.GetAttachments();
Console.WriteLine($"{bugTask.Json.web_link} - {bug.Name}");
if (IsBugCrashMissingLog(bug, bugTask, attachments))
{
await bug.AddUniqueMessage(
"Automated response (ORTB-C1)",
"Hello human, I am the Open Rails Triage Bot (https://github.com/openrails/openrails-triage-bot).\n" +
"\n" +
"It looks to me like you are reporting a crash in Open Rails, but I don't see a log file attached to this bug. To help my human friends diagnose what has gone wrong, it would be greatly appreciated if you could attach the complete 'OpenRailsLog.txt' file from your desktop to this bug.\n" +
"\n" +
"If you have provided the log file and I've missed it, or you're not actually reporting a crash, don't worry - I won't ask about this again and the humans will know what to do.\n"
);
}
}
}
static bool IsBugCrashMissingLog(Launchpad.Bug bug, Launchpad.BugTask bugTask, List<Launchpad.Attachment> attachments)
{
var now = DateTimeOffset.UtcNow;
var crash = new Regex(@"\b(?:crash|crashes|crashed)\b", RegexOptions.IgnoreCase | RegexOptions.CultureInvariant);
var logContents = "This is a log file for Open Rails. Please include this file in bug reports.";
var log = new Regex(@"\b(?:OpenRailsLog\.txt)\b", RegexOptions.IgnoreCase | RegexOptions.CultureInvariant);
return (now - bug.Created).TotalDays < 7 &&
bugTask.Status == Launchpad.Status.New &&
(crash.IsMatch(bug.Name) || crash.IsMatch(bug.Description)) &&
!bug.Description.Contains(logContents) &&
!attachments.Any(attachment => log.IsMatch(attachment.Name));
}
static readonly HttpClient Client = new();
static async Task<bool> LogInToLaunchpad(IConfigurationSection config)
{
if ((config["oauth_token"] ?? "").Length > 0 && (config["oauth_token_secret"] ?? "").Length > 0)
{
return true;
}
var requestToken = await Client.PostAsync(
"https://launchpad.net/+request-token",
new FormUrlEncodedContent(new Dictionary<string, string> {
{ "oauth_consumer_key", "Open Rails Triage Bot" },
{ "oauth_signature_method", "PLAINTEXT" },
{ "oauth_signature", "&" }
})
);
var decodedRequest = HttpUtility.ParseQueryString(await requestToken.Content.ReadAsStringAsync());
Console.WriteLine("Please open the following URL in a web browser logged in to the Launchpad account this bot should use:");
Console.WriteLine();
Console.WriteLine($" https://launchpad.net/+authorize-token?oauth_token={decodedRequest["oauth_token"]}");
Console.WriteLine();
Console.WriteLine("Press enter once the authorization has been made inside Launchpad");
Console.ReadLine();
var accessToken = await Client.PostAsync(
"https://launchpad.net/+access-token",
new FormUrlEncodedContent(new Dictionary<string, string> {
{ "oauth_token", decodedRequest["oauth_token"] ?? "" },
{ "oauth_consumer_key", "Open Rails Triage Bot" },
{ "oauth_signature_method", "PLAINTEXT" },
{ "oauth_signature", "&" + decodedRequest["oauth_token_secret"] }
})
);
var decodedAccess = HttpUtility.ParseQueryString(await accessToken.Content.ReadAsStringAsync());
Console.WriteLine();
Console.WriteLine("Please record the following values in the configuration file:");
Console.WriteLine();
Console.WriteLine("{");
Console.WriteLine(" \"launchpad\": {");
Console.WriteLine($" \"oauth_token\": \"{decodedAccess["oauth_token"]}\",");
Console.WriteLine($" \"oauth_token_secret\": \"{decodedAccess["oauth_token_secret"]}\"");
Console.WriteLine(" }");
Console.WriteLine("}");
return false;
}
}
}