Skip to content
This repository was archived by the owner on Nov 24, 2022. It is now read-only.

Commit 424d3a7

Browse files
committed
Improve GitHub issue responses
1 parent e6e7c92 commit 424d3a7

10 files changed

Lines changed: 60 additions & 53 deletions

File tree

TabletBot.Common/Attributes/Bot/CommandAttribute.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
namespace TabletBot.Common.Attributes.Bot
55
{
66
[AttributeUsage(AttributeTargets.Method)]
7-
[MeansImplicitUse(ImplicitUseTargetFlags.Members)]
7+
[MeansImplicitUse(ImplicitUseTargetFlags.Itself)]
88
public class CommandAttribute : Attribute
99
{
1010
public CommandAttribute(params string[] arguments)

TabletBot.Common/Log.cs

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,6 @@ public static void Write(string group, string text, LogLevel level = LogLevel.In
1212
Output?.Invoke(new LogMessage(group, text, level));
1313
}
1414

15-
public static async Task WriteAsync(string group, string text, LogLevel level = LogLevel.Info) => await Task.Run(() => Write(group, text, level));
16-
1715
public static void Debug(string group, string text)
1816
{
1917
Write(group, text, LogLevel.Debug);

TabletBot.Common/Settings.cs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -39,10 +39,10 @@ public sealed class Settings
3939

4040
public async Task Write(FileInfo file)
4141
{
42-
if (!file.Directory.Exists)
42+
if (file.Directory is { Exists: false })
4343
file.Directory.Create();
4444
await using (var fs = file.Create())
45-
await JsonSerializer.SerializeAsync<Settings>(fs, this, SerializerOptions);
45+
await JsonSerializer.SerializeAsync(fs, this, SerializerOptions);
4646
}
4747

4848
public static async Task<Settings> Read(FileInfo file)
@@ -55,7 +55,7 @@ public async Task<string> ExportAsync()
5555
{
5656
await using (var ms = new MemoryStream())
5757
{
58-
await JsonSerializer.SerializeAsync<Settings>(ms, this, SerializerOptions);
58+
await JsonSerializer.SerializeAsync(ms, this, SerializerOptions);
5959
ms.Position = 0;
6060
using (var sr = new StreamReader(ms))
6161
return await sr.ReadToEndAsync();

TabletBot.Discord/Commands/ModerationCommands.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ public async Task ForceSaveSettings()
3535
{
3636
await _settings.Write(Platform.SettingsFile);
3737
await ReplyAsync("Settings force saved.", allowedMentions: AllowedMentions.None);
38-
await Log.WriteAsync("Settings", $"{Context.Message.Author.Username} force-saved the configuration to {Platform.SettingsFile.FullName}");
38+
Log.Write("Settings", $"{Context.Message.Author.Username} force-saved the configuration to {Platform.SettingsFile.FullName}");
3939
}
4040

4141
[Command("kill-bot", RunMode = RunMode.Async), Name("Kill Bot"), RequireOwner]

TabletBot.Discord/LogExtensions.cs

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,25 +7,29 @@ namespace TabletBot.Discord
77
{
88
public static class LogExtensions
99
{
10-
public static async Task WriteAsync(IMessage message)
10+
public static Task WriteAsync(IMessage message)
1111
{
12-
await Log.WriteAsync("Message", string.Format(
12+
Log.Write("Message", string.Format(
1313
"#{1}/{2}#{3}: {0}",
1414
message.CleanContent,
1515
message.Channel.Name,
1616
message.Author.Username,
1717
message.Author.Discriminator
1818
));
19+
20+
return Task.CompletedTask;
1921
}
2022

21-
public static async Task WriteAsync(LogMessage message)
23+
public static Task WriteAsync(LogMessage message)
2224
{
23-
await Log.WriteAsync("Client", string.Format(
25+
Log.Write("Client", string.Format(
2426
"{1} [{2}]: {0}",
2527
message.Message,
2628
message.Source,
2729
message.Severity
2830
));
31+
32+
return Task.CompletedTask;
2933
}
3034
}
3135
}

TabletBot.Discord/Watchers/Commands/CommandMessageWatcher.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,7 @@ public async Task InitializeAsync()
7070
foreach (var module in _commands)
7171
{
7272
await _commandService.AddModuleAsync(module, _serviceProvider);
73-
await Log.WriteAsync("CommandSvc", $"Registered command module '{module.Name}'.", LogLevel.Debug);
73+
Log.Write("CommandSvc", $"Registered command module '{module.Name}'.", LogLevel.Debug);
7474
}
7575

7676
_commandService.CommandExecuted += CommandExecuted;

TabletBot.Discord/Watchers/Commands/SlashCommandInteractionWatcher.cs

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -64,25 +64,24 @@ public async Task InitializeAsync()
6464
if (_registered)
6565
return;
6666

67-
await Task.WhenAll(_commands.Select(RegisterCommand));
67+
await Task.WhenAll(_commands.Select(RegisterCommandModule));
6868
_registered = true;
6969
}
7070

71-
private async Task RegisterCommand(SlashCommandModule module)
71+
private async Task RegisterCommandModule(SlashCommandModule module)
7272
{
73-
module.BuildCommandHandlers();
74-
7573
var moderatorCommands = new List<RestGuildCommand>();
76-
foreach (var command in module.CommandHandlers)
74+
foreach (var command in module.BuildCommandHandlers())
7775
{
7876
var guildCommand = await _client.Rest.CreateGuildCommand(command.Build(), _settings.GuildID);
7977
if (guildCommand.IsDefaultPermission == false)
8078
moderatorCommands.Add(guildCommand);
8179
}
8280

8381
await ApplyCommandPermissions(_client, moderatorCommands);
84-
8582
module.Update += UpdateModule;
83+
84+
Log.Write("Setup", $"Registered slash command module '{module.GetType().Name}'.");
8685
}
8786

8887
private async Task ApplyCommandPermissions(DiscordSocketClient client, IEnumerable<RestGuildCommand> moderatorCommands)
Lines changed: 33 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
using System;
21
using System.Collections.Generic;
32
using System.Linq;
43
using System.Text.RegularExpressions;
@@ -7,6 +6,7 @@
76
using Octokit;
87
using TabletBot.Common;
98
using TabletBot.Discord.Embeds;
9+
using TabletBot.Discord.Commands;
1010

1111
#nullable enable
1212

@@ -26,49 +26,55 @@ public IssueMessageWatcher(Settings settings, GitHubClient gitHubClient)
2626
private const string OWNER = "OpenTabletDriver";
2727
private const string NAME = "OpenTabletDriver";
2828

29+
private static readonly Regex IssueRefRegex = new Regex(@" ?#([0-9]+[0-9]) ?");
30+
2931
public async Task Receive(IMessage message)
3032
{
31-
if (message.Author.IsBot)
33+
if (message.Author.IsBot || message is not IUserMessage userMessage)
3234
return;
3335

34-
if (TryGetIssueRefNumbers(message.Content, out var refs))
36+
var rateLimits = await _gitHubClient.Miscellaneous.GetRateLimits();
37+
if (rateLimits.Rate.Remaining < 2)
38+
return;
39+
40+
if (GetIssueRefNumbers(userMessage.Content) is IList<uint> refs)
3541
{
36-
uint refNum = 0;
37-
foreach (int issueRef in refs)
42+
using (userMessage.Channel.EnterTypingState())
3843
{
39-
if (refNum == _settings.GitHubIssueRefLimit)
40-
break;
41-
42-
var issues = await _gitHubClient.Issue.GetAllForRepository(OWNER, NAME);
43-
var prs = await _gitHubClient.PullRequest.GetAllForRepository(OWNER, NAME);
44-
if (issues.FirstOrDefault(i => i.Number == issueRef) is Issue issue)
45-
{
46-
var pr = prs.FirstOrDefault(pr => pr.Number == issue.Number);
47-
var embed = pr == null ? GitHubEmbeds.GetIssueEmbed(issue) : GitHubEmbeds.GetPullRequestEmbed(pr);
48-
await message.Channel.SendMessageAsync(embed: embed);
49-
}
50-
refNum++;
44+
await ReplyWithEmbeds(userMessage, refs);
5145
}
5246
}
5347
}
5448

5549
public Task Deleted(Cacheable<IMessage, ulong> message, Cacheable<IMessageChannel, ulong> channel) => Task.CompletedTask;
5650

57-
public static bool TryGetIssueRefNumbers(string message, out IEnumerable<int> refNums)
51+
private async Task ReplyWithEmbeds(IUserMessage message, IList<uint> refs)
5852
{
59-
refNums = Array.Empty<int>();
53+
var issues = await _gitHubClient.Issue.GetAllForRepository(OWNER, NAME);
54+
var prs = await _gitHubClient.PullRequest.GetAllForRepository(OWNER, NAME);
55+
var embeds = GetEmbedsForRefs(issues, prs, refs).ToArray();
6056

61-
var matches = IssueRefRegex.Matches(message);
62-
if (matches.Count > 0)
57+
await message.Channel.SendMessageAsync(embeds: embeds, messageReference: message.ToReference());
58+
}
59+
60+
private IEnumerable<Embed> GetEmbedsForRefs(IReadOnlyList<Issue> issues, IReadOnlyList<PullRequest> prs, IList<uint> refs)
61+
{
62+
for (var i = 0; i < refs.Count && i < _settings.GitHubIssueRefLimit; i++)
6363
{
64-
refNums = from match in matches
65-
select int.Parse(match.Groups[1].Value);
66-
return true;
67-
}
64+
var issueRef = refs[i];
6865

69-
return false;
66+
if (issues.FirstOrDefault(s => s.Number == issueRef) is Issue issue)
67+
{
68+
var pr = prs.FirstOrDefault(pr => pr.Number == issue.Number);
69+
yield return pr == null ? GitHubEmbeds.GetIssueEmbed(issue) : GitHubEmbeds.GetPullRequestEmbed(pr);
70+
}
71+
}
7072
}
7173

72-
private static readonly Regex IssueRefRegex = new Regex(@" ?#([0-9]+[0-9]) ?");
74+
private static IEnumerable<uint>? GetIssueRefNumbers(string message)
75+
{
76+
var matches = IssueRefRegex.Matches(message);
77+
return matches.Any() ? matches.Select(m => uint.Parse(m.Groups[1].Value)).ToList() : null;
78+
}
7379
}
7480
}

TabletBot/Program.Commands.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -81,7 +81,7 @@ public static void ModifySetting(params string[] args)
8181
public static async void SaveSettings(params string[] args)
8282
{
8383
await Settings!.Write(Platform.SettingsFile);
84-
await Log.WriteAsync("Settings", $"Saved to '{Platform.SettingsFile.FullName}'.");
84+
Log.Write("Settings", $"Saved to '{Platform.SettingsFile.FullName}'.");
8585
}
8686
}
8787
}

TabletBot/Program.cs

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,7 @@ private static async Task Main(string[] args)
5656

5757
var config = new DiscordSocketConfig();
5858
DiscordClient = new DiscordSocketClient(config);
59-
var gitHubClient = await AuthenticateGitHub(githubToken);
59+
var gitHubClient = AuthenticateGitHub(githubToken);
6060

6161
var serviceCollection = BotServiceCollection.Build(Settings, DiscordClient, gitHubClient!);
6262
var serviceProvider = serviceCollection.BuildServiceProvider();
@@ -73,27 +73,27 @@ private static async Task Main(string[] args)
7373
else
7474
{
7575
var commandArgs = IO.ReadLine().Split(' ');
76-
await InvokeCommand(commandArgs);
76+
InvokeCommand(commandArgs);
7777
}
7878
}
7979
await Bot.Logout();
8080
Console.WriteLine();
8181
}
8282

83-
private static async Task InvokeCommand(string[] args)
83+
private static void InvokeCommand(string[] args)
8484
{
8585
try
8686
{
8787
if (!CommandCollection.Current.Invoke(args))
88-
await Log.WriteAsync("Terminal", $"Invalid command: '{args[0]}'. Execute help for a list of commands.");
88+
Log.Write("Terminal", $"Invalid command: '{args[0]}'. Execute help for a list of commands.");
8989
}
9090
catch (Exception ex)
9191
{
9292
Log.Exception(ex);
9393
}
9494
}
9595

96-
private static async Task<GitHubClient?> AuthenticateGitHub(string token)
96+
private static GitHubClient? AuthenticateGitHub(string token)
9797
{
9898
if (!string.IsNullOrWhiteSpace(token))
9999
{
@@ -105,7 +105,7 @@ private static async Task InvokeCommand(string[] args)
105105
Credentials = new Credentials(token)
106106
};
107107

108-
await Log.WriteAsync("GitHub", "Authenticated client.");
108+
Log.Write("GitHub", "Authenticated client.");
109109
return githubClient;
110110
}
111111
catch (Exception ex)
@@ -115,7 +115,7 @@ private static async Task InvokeCommand(string[] args)
115115
}
116116
else
117117
{
118-
await Log.WriteAsync("GitHub", "API was not authenticated.", LogLevel.Warning);
118+
Log.Write("GitHub", "API was not authenticated.", LogLevel.Warning);
119119
}
120120

121121
return null;

0 commit comments

Comments
 (0)