3e668a3660
Previous commits had quite a bit of personal information in them. More than I would have liked to share. Unfortunately, making this public means losing all that prior commit history.
267 lines
9 KiB
C#
267 lines
9 KiB
C#
using Discord;
|
||
using Discord.WebSocket;
|
||
using Noikoio.RegexBot.ConfigItem;
|
||
using System;
|
||
using System.Collections.ObjectModel;
|
||
using System.Diagnostics;
|
||
using System.Text;
|
||
using System.Threading.Tasks;
|
||
|
||
namespace Noikoio.RegexBot
|
||
{
|
||
// Contains code for handling each response in a rule.
|
||
partial class RuleResponder
|
||
{
|
||
private delegate Task ResponseProcessor(AsyncLogger l, string cmd, Rule r, SocketMessage m);
|
||
private readonly ReadOnlyDictionary<string, ResponseProcessor> _commands;
|
||
|
||
#if DEBUG
|
||
/// <summary>
|
||
/// Throws an exception. Meant to be a quick error handling test.
|
||
/// No parameters.
|
||
/// </summary>
|
||
private async Task RP_Crash(AsyncLogger l, string cmd, Rule r, SocketMessage m)
|
||
{
|
||
await l("Will throw an exception.");
|
||
throw new Exception("Requested in response.");
|
||
}
|
||
|
||
/// <summary>
|
||
/// Prints all guild values (IDs for users, channels, roles) to console.
|
||
/// The guild info displayed is the one in which the command is invoked.
|
||
/// No parameters.
|
||
/// </summary>
|
||
private Task RP_DumpID(AsyncLogger l, string cmd, Rule r, SocketMessage m)
|
||
{
|
||
var g = ((SocketGuildUser)m.Author).Guild;
|
||
var result = new StringBuilder();
|
||
|
||
result.AppendLine("Users:");
|
||
foreach (var item in g.Users)
|
||
result.AppendLine($"{item.Id} {item.Username}#{item.Discriminator}");
|
||
result.AppendLine();
|
||
|
||
result.AppendLine("Channels:");
|
||
foreach (var item in g.Channels) result.AppendLine($"{item.Id} #{item.Name}");
|
||
result.AppendLine();
|
||
result.AppendLine("Roles:");
|
||
foreach (var item in g.Roles) result.AppendLine($"{item.Id} {item.Name}");
|
||
result.AppendLine();
|
||
|
||
Console.WriteLine(result.ToString());
|
||
return Task.CompletedTask;
|
||
}
|
||
#endif
|
||
/// <summary>
|
||
/// Sends a message to a specified channel.
|
||
/// Parameters: say (channel) (message)
|
||
/// </summary>
|
||
private async Task RP_Say(AsyncLogger l, string cmd, Rule r, SocketMessage m)
|
||
{
|
||
string[] @in = SplitParams(cmd, 3);
|
||
if (@in.Length != 3)
|
||
{
|
||
await l("Error: say: Incorrect number of parameters.");
|
||
return;
|
||
}
|
||
|
||
var target = await GetMessageTargetAsync(@in[1], m);
|
||
if (target == null)
|
||
{
|
||
await l("Error: say: Unable to resolve given target.");
|
||
return;
|
||
}
|
||
|
||
// CHANGE THE SAY
|
||
@in[2] = ProcessText(@in[2], m);
|
||
await target.SendMessageAsync(@in[2]);
|
||
}
|
||
|
||
/// <summary>
|
||
/// Reports the incoming message to a given channel.
|
||
/// Parameters: report (channel)
|
||
/// </summary>
|
||
private async Task RP_Report(AsyncLogger l, string cmd, Rule r, SocketMessage m)
|
||
{
|
||
string[] @in = SplitParams(cmd);
|
||
if (@in.Length != 2)
|
||
{
|
||
await l("Error: report: Incorrect number of parameters.");
|
||
return;
|
||
}
|
||
|
||
var target = await GetMessageTargetAsync(@in[1], m);
|
||
if (target == null)
|
||
{
|
||
await l("Error: report: Unable to resolve given target.");
|
||
return;
|
||
}
|
||
|
||
|
||
var responsefield = new StringBuilder();
|
||
responsefield.AppendLine("```");
|
||
foreach (var line in r.Responses)
|
||
responsefield.AppendLine(line.Replace("\r", "").Replace("\n", "\\n"));
|
||
responsefield.Append("```");
|
||
await target.SendMessageAsync("", embed: new EmbedBuilder()
|
||
{
|
||
Color = new Color(0xEDCE00), // configurable later?
|
||
|
||
Author = new EmbedAuthorBuilder()
|
||
{
|
||
Name = $"{m.Author.Username}#{m.Author.Discriminator} said:",
|
||
IconUrl = m.Author.GetAvatarUrl()
|
||
},
|
||
Description = m.Content,
|
||
|
||
Footer = new EmbedFooterBuilder()
|
||
{
|
||
Text = $"Rule '{r.DisplayName}'",
|
||
IconUrl = _client.CurrentUser.GetAvatarUrl()
|
||
},
|
||
Timestamp = m.Timestamp
|
||
}.AddField(new EmbedFieldBuilder()
|
||
{
|
||
Name = "Additional info",
|
||
Value = $"Channel: <#{m.Channel.Id}>\n" // NOTE: manually mentioning channel here
|
||
+ $"Username: {m.Author.Mention}\n"
|
||
+ $"Message ID: {m.Id}"
|
||
}).AddField(new EmbedFieldBuilder()
|
||
{
|
||
Name = "Executing response:",
|
||
Value = responsefield.ToString()
|
||
}));
|
||
}
|
||
|
||
/// <summary>
|
||
/// Deletes the incoming message.
|
||
/// No parameters.
|
||
/// </summary>
|
||
private async Task RP_Remove(AsyncLogger l, string cmd, Rule r, SocketMessage m)
|
||
{
|
||
// Parameters are not checked
|
||
await m.DeleteAsync();
|
||
}
|
||
|
||
/// <summary>
|
||
/// Executes an external program and sends standard output to the given channel.
|
||
/// Parameters: exec (channel) (command line)
|
||
/// </summary>
|
||
private async Task RP_Exec(AsyncLogger l, string cmd, Rule r, SocketMessage m)
|
||
{
|
||
var @in = SplitParams(cmd, 4);
|
||
if (@in.Length < 3)
|
||
{
|
||
await l("exec: Incorrect number of parameters.");
|
||
}
|
||
|
||
string result;
|
||
var target = await GetMessageTargetAsync(@in[1], m);
|
||
if (target == null)
|
||
{
|
||
await l("Error: exec: Unable to resolve given channel.");
|
||
return;
|
||
}
|
||
|
||
ProcessStartInfo ps = new ProcessStartInfo()
|
||
{
|
||
FileName = @in[2],
|
||
Arguments = (@in.Length > 3 ? @in[3] : ""),
|
||
UseShellExecute = false,
|
||
RedirectStandardOutput = true
|
||
};
|
||
using (Process p = Process.Start(ps))
|
||
{
|
||
p.WaitForExit(5000); // waiting at most 5 seconds
|
||
if (p.HasExited)
|
||
{
|
||
if (p.ExitCode != 0) await l("exec: Process returned exit code " + p.ExitCode);
|
||
using (var stdout = p.StandardOutput)
|
||
{
|
||
result = await stdout.ReadToEndAsync();
|
||
}
|
||
}
|
||
else
|
||
{
|
||
await l("exec: Process is taking too long to exit. Killing process.");
|
||
p.Kill();
|
||
return;
|
||
}
|
||
}
|
||
|
||
result = ProcessText(result.Trim(), m);
|
||
await target.SendMessageAsync(result);
|
||
}
|
||
|
||
/// <summary>
|
||
/// Bans the sender of the incoming message.
|
||
/// No parameters.
|
||
/// </summary>
|
||
// TODO add parameter for message auto-deleting
|
||
private async Task RP_Ban(AsyncLogger l, string cmd, Rule r, SocketMessage m)
|
||
{
|
||
SocketGuild g = ((SocketGuildUser)m.Author).Guild;
|
||
await g.AddBanAsync(m.Author);
|
||
}
|
||
|
||
/// <summary>
|
||
/// Grants or revokes a specified role to/from a given user.
|
||
/// Parameters: grantrole/revokerole (user ID or @_) (role ID)
|
||
/// </summary>
|
||
private async Task RP_GrantRevokeRole(AsyncLogger l, string cmd, Rule r, SocketMessage m)
|
||
{
|
||
string[] @in = SplitParams(cmd);
|
||
if (@in.Length != 3)
|
||
{
|
||
await l($"Error: {@in[0]}: incorrect number of parameters.");
|
||
return;
|
||
}
|
||
if (!ulong.TryParse(@in[2], out var roleID))
|
||
{
|
||
await l($"Error: {@in[0]}: Invalid role ID specified.");
|
||
return;
|
||
}
|
||
|
||
// Finding role
|
||
var gu = (SocketGuildUser)m.Author;
|
||
SocketRole rl = gu.Guild.GetRole(roleID);
|
||
if (rl == null)
|
||
{
|
||
await l($"Error: {@in[0]}: Specified role not found.");
|
||
return;
|
||
}
|
||
|
||
// Finding user
|
||
SocketGuildUser target;
|
||
if (@in[1] == "@_")
|
||
{
|
||
target = gu;
|
||
}
|
||
else
|
||
{
|
||
if (!ulong.TryParse(@in[1], out var userID))
|
||
{
|
||
await l($"Error: {@in[0]}: Invalid user ID specified.");
|
||
return;
|
||
}
|
||
target = gu.Guild.GetUser(userID);
|
||
if (target == null)
|
||
{
|
||
await l($"Error: {@in[0]}: Given user ID does not exist in this server.");
|
||
return;
|
||
}
|
||
}
|
||
|
||
if (@in[0].ToLower() == "grantrole")
|
||
{
|
||
await target.AddRoleAsync(rl);
|
||
}
|
||
else
|
||
{
|
||
await target.RemoveRoleAsync(rl);
|
||
}
|
||
}
|
||
|
||
|
||
}
|
||
}
|