Fully implemented AutoRespond
This commit is contained in:
parent
f19ef5a662
commit
7dbab38728
3 changed files with 63 additions and 16 deletions
|
@ -1,9 +1,7 @@
|
||||||
using System;
|
using Discord.WebSocket;
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Text;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
using Discord.WebSocket;
|
|
||||||
using Newtonsoft.Json.Linq;
|
using Newtonsoft.Json.Linq;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
namespace Noikoio.RegexBot.Feature.AutoRespond
|
namespace Noikoio.RegexBot.Feature.AutoRespond
|
||||||
{
|
{
|
||||||
|
@ -14,10 +12,9 @@ namespace Noikoio.RegexBot.Feature.AutoRespond
|
||||||
/// The major differences between this and <see cref="AutoMod"/> include:
|
/// The major differences between this and <see cref="AutoMod"/> include:
|
||||||
/// <list type="bullet">
|
/// <list type="bullet">
|
||||||
/// <item><description>Does not listen for message edits.</description></item>
|
/// <item><description>Does not listen for message edits.</description></item>
|
||||||
/// <item><description>Moderators are not exempt from any defined triggers by default.</description></item>
|
/// <item><description>Moderators are not exempt from any defined triggers.</description></item>
|
||||||
/// <item><description>Responses are limited to only two types, and only one is allowed per rule.</description></item>
|
/// <item><description>Responses are limited to the invoking channel.</description></item>
|
||||||
/// <item><description>Does not support fine-grained matching options.</description></item>
|
/// <item><description>Per-channel rate limiting.</description></item>
|
||||||
/// <item><description>Support for rate limiting.</description></item>
|
|
||||||
/// </list>
|
/// </list>
|
||||||
/// </para>
|
/// </para>
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
@ -47,7 +44,14 @@ namespace Noikoio.RegexBot.Feature.AutoRespond
|
||||||
[ConfigSection("autoresponses")]
|
[ConfigSection("autoresponses")]
|
||||||
public override Task<object> ProcessConfiguration(JToken configSection)
|
public override Task<object> ProcessConfiguration(JToken configSection)
|
||||||
{
|
{
|
||||||
throw new NotImplementedException();
|
var responses = new List<ResponseDefinition>();
|
||||||
|
foreach (JObject def in configSection)
|
||||||
|
{
|
||||||
|
// Everything is left to the constructor
|
||||||
|
responses.Add(new ResponseDefinition(def));
|
||||||
|
}
|
||||||
|
|
||||||
|
return Task.FromResult<object>(responses.AsReadOnly());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,7 +1,5 @@
|
||||||
using Discord.WebSocket;
|
using Discord.WebSocket;
|
||||||
using System;
|
using System.Diagnostics;
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Text;
|
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
namespace Noikoio.RegexBot.Feature.AutoRespond
|
namespace Noikoio.RegexBot.Feature.AutoRespond
|
||||||
|
@ -10,10 +8,53 @@ namespace Noikoio.RegexBot.Feature.AutoRespond
|
||||||
{
|
{
|
||||||
private async Task ProcessMessage(SocketMessage msg, ResponseDefinition def)
|
private async Task ProcessMessage(SocketMessage msg, ResponseDefinition def)
|
||||||
{
|
{
|
||||||
// Filtering checks
|
// Checks before executing
|
||||||
|
if (def.Filter.IsFiltered(msg)) return;
|
||||||
|
if (!def.RateLimit.AddUsage(msg.Channel.Id)) return;
|
||||||
|
|
||||||
// Rate limit checks
|
await Log($"'{def.Label}' triggered in #{msg.Channel.Name} by {msg.Author}");
|
||||||
|
var (type, text) = def.Response;
|
||||||
|
|
||||||
|
if (type == ResponseDefinition.ResponseType.Reply) await ProcessReply(msg, text);
|
||||||
|
else if (type == ResponseDefinition.ResponseType.Exec) await ProcessExec(msg, text);
|
||||||
|
}
|
||||||
|
|
||||||
|
private async Task ProcessReply(SocketMessage msg, string text)
|
||||||
|
{
|
||||||
|
await msg.Channel.SendMessageAsync(text);
|
||||||
|
}
|
||||||
|
|
||||||
|
private async Task ProcessExec(SocketMessage msg, string text)
|
||||||
|
{
|
||||||
|
string[] cmdline = text.Split(new char[] { ' ' }, 2);
|
||||||
|
|
||||||
|
ProcessStartInfo ps = new ProcessStartInfo()
|
||||||
|
{
|
||||||
|
FileName = cmdline[0],
|
||||||
|
Arguments = (cmdline.Length == 2 ? cmdline[1] : ""),
|
||||||
|
UseShellExecute = false, // ???
|
||||||
|
CreateNoWindow = true,
|
||||||
|
RedirectStandardOutput = true
|
||||||
|
};
|
||||||
|
using (Process p = Process.Start(ps))
|
||||||
|
{
|
||||||
|
p.WaitForExit(5000); // waiting at most 5 seconds
|
||||||
|
if (p.HasExited)
|
||||||
|
{
|
||||||
|
if (p.ExitCode != 0) await Log("exec: Process returned exit code " + p.ExitCode);
|
||||||
|
using (var stdout = p.StandardOutput)
|
||||||
|
{
|
||||||
|
var result = await stdout.ReadToEndAsync();
|
||||||
|
await msg.Channel.SendMessageAsync(result);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
await Log("exec: Process is taking too long to exit. Killing process.");
|
||||||
|
p.Kill();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,7 +8,7 @@ namespace Noikoio.RegexBot.Feature.AutoRespond
|
||||||
/// </summary>
|
/// </summary>
|
||||||
class RateLimitCache
|
class RateLimitCache
|
||||||
{
|
{
|
||||||
public const ushort DefaultTimeout = 30; // TODO make configurable
|
public const ushort DefaultTimeout = 20; // this is Skeeter's fault
|
||||||
|
|
||||||
private readonly ushort _timeout;
|
private readonly ushort _timeout;
|
||||||
private Dictionary<ulong, DateTime> _cache;
|
private Dictionary<ulong, DateTime> _cache;
|
||||||
|
@ -32,6 +32,8 @@ namespace Noikoio.RegexBot.Feature.AutoRespond
|
||||||
/// <returns>True on success. False if the given ID already exists.</returns>
|
/// <returns>True on success. False if the given ID already exists.</returns>
|
||||||
public bool AddUsage(ulong id)
|
public bool AddUsage(ulong id)
|
||||||
{
|
{
|
||||||
|
if (_timeout == 0) return true;
|
||||||
|
|
||||||
Clean();
|
Clean();
|
||||||
if (_cache.ContainsKey(id)) return false;
|
if (_cache.ContainsKey(id)) return false;
|
||||||
_cache.Add(id, DateTime.Now);
|
_cache.Add(id, DateTime.Now);
|
||||||
|
|
Loading…
Reference in a new issue