2018-10-28 18:44:30 +00:00
|
|
|
|
using Newtonsoft.Json.Linq;
|
|
|
|
|
using Noikoio.RegexBot.ConfigItem;
|
|
|
|
|
using System;
|
2018-10-31 21:29:08 +00:00
|
|
|
|
using System.Linq;
|
2018-10-28 18:44:30 +00:00
|
|
|
|
using System.Text.RegularExpressions;
|
|
|
|
|
|
|
|
|
|
namespace Noikoio.RegexBot.Module.VoteTempChannel
|
|
|
|
|
{
|
2018-10-29 01:39:48 +00:00
|
|
|
|
class Configuration
|
2018-10-28 18:44:30 +00:00
|
|
|
|
{
|
2018-10-29 02:53:56 +00:00
|
|
|
|
/// <summary>
|
2018-10-31 20:11:12 +00:00
|
|
|
|
/// Channel name in which voting takes place.
|
2018-10-29 02:53:56 +00:00
|
|
|
|
/// </summary>
|
2018-10-31 20:11:12 +00:00
|
|
|
|
public string VoteChannel { get; }
|
2018-10-29 02:53:56 +00:00
|
|
|
|
/// <summary>
|
2018-10-31 20:11:12 +00:00
|
|
|
|
/// Command used to vote for the channel's creation.
|
2018-10-29 02:53:56 +00:00
|
|
|
|
/// </summary>
|
2018-10-31 20:11:12 +00:00
|
|
|
|
public string VoteCommand { get; }
|
2018-10-29 02:53:56 +00:00
|
|
|
|
/// <summary>
|
|
|
|
|
/// Number of votes needed to create the channel.
|
|
|
|
|
/// </summary>
|
2018-10-28 18:44:30 +00:00
|
|
|
|
public int VotePassThreshold { get; }
|
2018-10-29 02:53:56 +00:00
|
|
|
|
/// <summary>
|
|
|
|
|
/// Amount of time that a voting session can last starting from its initial vote.
|
|
|
|
|
/// </summary>
|
2018-10-29 01:39:48 +00:00
|
|
|
|
public TimeSpan VotingDuration { get; }
|
2018-10-29 02:53:56 +00:00
|
|
|
|
/// <summary>
|
|
|
|
|
/// Amount of time to wait before another vote may be initiated, either after a failed vote
|
|
|
|
|
/// or from expiration of the temporary channel.
|
|
|
|
|
/// </summary>
|
2018-10-29 01:39:48 +00:00
|
|
|
|
public TimeSpan VotingCooldown { get; }
|
2018-10-28 18:44:30 +00:00
|
|
|
|
|
2018-10-29 02:53:56 +00:00
|
|
|
|
/// <summary>
|
2018-10-31 20:11:12 +00:00
|
|
|
|
/// Name of the temporary channel, without prefix.
|
2018-10-29 02:53:56 +00:00
|
|
|
|
/// </summary>
|
2018-10-31 20:11:12 +00:00
|
|
|
|
public string TempChannelName { get; }
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// Amount of time that the temporary channel can exist without activity before expiring and being deleted.
|
|
|
|
|
/// </summary>
|
|
|
|
|
public TimeSpan ChannelDuration { get; }
|
2018-10-29 02:53:56 +00:00
|
|
|
|
|
2018-10-31 21:29:08 +00:00
|
|
|
|
/// <summary>
|
|
|
|
|
/// Entities that are allowed to cast the initial vote.
|
|
|
|
|
/// An empty list allows anyone to initiate a vote.
|
|
|
|
|
/// </summary>
|
|
|
|
|
public EntityList VoteStarters { get; }
|
|
|
|
|
|
2018-10-29 01:39:48 +00:00
|
|
|
|
public Configuration(JObject j)
|
2018-10-28 18:44:30 +00:00
|
|
|
|
{
|
|
|
|
|
VoteCommand = j["VoteCommand"]?.Value<string>();
|
|
|
|
|
if (string.IsNullOrWhiteSpace(VoteCommand))
|
|
|
|
|
throw new RuleImportException("'VoteCommand' must be specified.");
|
|
|
|
|
if (VoteCommand.Contains(" "))
|
|
|
|
|
throw new RuleImportException("'VoteCommand' must not contain spaces.");
|
|
|
|
|
|
2018-10-29 02:53:56 +00:00
|
|
|
|
TempChannelName = ParseChannelNameConfig(j, "TempChannelName");
|
2018-10-31 20:11:12 +00:00
|
|
|
|
VoteChannel = ParseChannelNameConfig(j, "VoteChannel");
|
2018-10-28 18:44:30 +00:00
|
|
|
|
|
|
|
|
|
var vptProp = j["VotePassThreshold"];
|
|
|
|
|
if (vptProp == null)
|
|
|
|
|
throw new RuleImportException("'VotePassThreshold' must be specified.");
|
|
|
|
|
if (vptProp.Type != JTokenType.Integer)
|
|
|
|
|
throw new NotImplementedException("'VotePassThreshold' must be an integer.");
|
|
|
|
|
VotePassThreshold = vptProp.Value<int>();
|
|
|
|
|
if (VotePassThreshold <= 0)
|
|
|
|
|
throw new NotImplementedException("'VotePassThreshold' must be greater than zero.");
|
|
|
|
|
|
2018-10-29 02:53:56 +00:00
|
|
|
|
ChannelDuration = ParseTimeConfig(j, "ChannelDuration");
|
2018-10-29 01:39:48 +00:00
|
|
|
|
VotingDuration = ParseTimeConfig(j, "VotingDuration");
|
|
|
|
|
VotingCooldown = ParseTimeConfig(j, "VotingCooldown");
|
2018-10-31 21:29:08 +00:00
|
|
|
|
|
|
|
|
|
VoteStarters = new EntityList(j["VoteStarters"]);
|
|
|
|
|
// Accepts empty lists.
|
2018-10-28 18:44:30 +00:00
|
|
|
|
}
|
|
|
|
|
|
2018-10-29 02:53:56 +00:00
|
|
|
|
private string ParseChannelNameConfig(JObject conf, string valueName)
|
|
|
|
|
{
|
2018-10-31 20:11:12 +00:00
|
|
|
|
var value = conf[valueName]?.Value<string>();
|
2018-10-29 02:53:56 +00:00
|
|
|
|
if (string.IsNullOrWhiteSpace(value))
|
|
|
|
|
throw new RuleImportException($"'{valueName}' must be specified.");
|
2018-10-31 20:11:12 +00:00
|
|
|
|
if (!Regex.IsMatch(value, @"^([A-Za-z0-9]|[-_ ])+$"))
|
2018-10-29 02:53:56 +00:00
|
|
|
|
throw new RuleImportException($"'{valueName}' contains one or more invalid characters.");
|
|
|
|
|
return value;
|
|
|
|
|
}
|
|
|
|
|
|
2018-10-28 18:44:30 +00:00
|
|
|
|
private TimeSpan ParseTimeConfig(JObject conf, string valueName)
|
|
|
|
|
{
|
|
|
|
|
var inputstr = conf[valueName]?.Value<string>();
|
|
|
|
|
if (string.IsNullOrWhiteSpace(inputstr))
|
|
|
|
|
throw new RuleImportException($"'{valueName}' must be specified.");
|
|
|
|
|
|
|
|
|
|
try
|
|
|
|
|
{
|
|
|
|
|
return ParseShorthandTimeInput(inputstr);
|
|
|
|
|
}
|
|
|
|
|
catch (ArgumentException)
|
|
|
|
|
{
|
|
|
|
|
throw new RuleImportException($"'{valueName}' could not be parsed as a length of time. See documentation.");
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private static readonly Regex ShorthandTimeInput = new Regex(@"^(?:(?<day>\d+)d)?(?:(?<hr>\d+)h)?(?:(?<min>\d+)m)?$");
|
|
|
|
|
// TODO Could be improved or better adapted? I copied this straight from an old project.
|
|
|
|
|
public static TimeSpan ParseShorthandTimeInput(string ti)
|
|
|
|
|
{
|
|
|
|
|
ti = ti.ToLower();
|
|
|
|
|
var time = ShorthandTimeInput.Match(ti);
|
|
|
|
|
if (!time.Success) throw new ArgumentException("Input is not shorthand time.");
|
|
|
|
|
|
|
|
|
|
int minutes = 0;
|
|
|
|
|
string inday = time.Groups["day"].Value;
|
|
|
|
|
string inhr = time.Groups["hr"].Value;
|
|
|
|
|
string inmin = time.Groups["min"].Value;
|
|
|
|
|
if (inday != "")
|
|
|
|
|
{
|
|
|
|
|
minutes += int.Parse(inday) * 1440;
|
|
|
|
|
}
|
|
|
|
|
if (inhr != "")
|
|
|
|
|
{
|
|
|
|
|
minutes += int.Parse(inhr) * 60;
|
|
|
|
|
}
|
|
|
|
|
if (inmin != "")
|
|
|
|
|
{
|
|
|
|
|
minutes += int.Parse(inmin);
|
|
|
|
|
}
|
|
|
|
|
return new TimeSpan(0, minutes, 0);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|