RegexBot/RuleResponder_Responses.cs
Noikoio 3e668a3660 First commit in new repository
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.
2017-06-23 12:33:54 -07:00

267 lines
9 KiB
C#
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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;
}
// 
@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);
}
}
}
}