using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Runtime.Serialization;
namespace TGS.Interface
{
///
/// For setting up authentication no matter the chat provider
///
[DataContract]
[KnownType(typeof(IRCSetupInfo))]
[KnownType(typeof(DiscordSetupInfo))]
public class ChatSetupInfo
{
const int AdminListIndex = 0;
const int AdminModeIndex = 1;
const int AdminChannelIndex = 2;
const int DevChannelIndex = 3;
const int WDChannelIndex = 4;
const int GameChannelIndex = 5;
const int ProviderIndex = 6;
const int EnabledIndex = 7;
///
/// Starting index of which child classes should use to write their custom data to
///
protected const int BaseIndex = 8;
///
/// Set to if a child constructor should use the baseInfo parameter of to initialize it's property fields, otherwise
///
protected readonly bool InitializeFields;
///
/// Raw access to the underlying data
///
[DataMember]
public IList DataFields { get; protected set; }
///
/// Constructs a from optional
///
/// The that this is for
/// Optional past data
/// The number of fields in this chat provider
protected internal ChatSetupInfo(ChatProvider provider, ChatSetupInfo baseInfo, int numFields)
{
numFields += BaseIndex;
InitializeFields = baseInfo == null || baseInfo.DataFields.Count != numFields;
if (InitializeFields)
{
DataFields = new List(numFields);
for (var I = 0; I < numFields; ++I)
DataFields.Add(null);
AdminList = new List();
AdminChannels = new List();
DevChannels = new List();
GameChannels = new List();
WatchdogChannels = new List();
AdminsAreSpecial = false;
Enabled = false;
}
else
DataFields = baseInfo.DataFields;
Provider = provider;
Specialize(true); //to check we have a valid provider
}
///
/// Recreates as the correct child
///
/// If , is returned provided is a valid
/// A new based on the type
ChatSetupInfo Specialize(bool checkOnly)
{
switch (Provider)
{
case ChatProvider.IRC:
if (!checkOnly)
return new IRCSetupInfo(this);
break;
case ChatProvider.Discord:
if (!checkOnly)
return new DiscordSetupInfo(this);
break;
default:
throw new Exception("Invalid provider!");
}
return null;
}
///
/// Properly formats a name for the
///
/// The to format
/// The formatted
protected virtual string SanitizeChannelName(string channel)
{
return Specialize(false).SanitizeChannelName(channel);
}
///
/// Sanitizes a list of
///
/// A of strings
void SanitizeChannelNames(IList channelnames)
{
for (var I = 0; I < channelnames.Count; ++I)
if (String.IsNullOrWhiteSpace(channelnames[I]))
{
channelnames.RemoveAt(I);
--I;
}
else
channelnames[I] = SanitizeChannelName(channelnames[I].Trim());
}
///
/// Constructs a from a data list
///
/// The data
public ChatSetupInfo(IList DeserializedData)
{
DataFields = DeserializedData;
Specialize(false); //ensure provider type is valid
}
///
/// The list of admin entries
///
public List AdminList
{
get { return JsonConvert.DeserializeObject>(DataFields[AdminListIndex]); }
set { DataFields[AdminListIndex] = JsonConvert.SerializeObject(value); }
}
///
/// If AdminList corresponds to a Provider specific recognization method
///
public bool AdminsAreSpecial
{
get { return Convert.ToBoolean(DataFields[AdminModeIndex]); }
set { DataFields[AdminModeIndex] = Convert.ToString(value); }
}
///
/// The channels from which admin commands/messages can be sent/received
///
public List AdminChannels
{
get { return JsonConvert.DeserializeObject>(DataFields[AdminChannelIndex]); }
set
{
SanitizeChannelNames(value);
DataFields[AdminChannelIndex] = JsonConvert.SerializeObject(value);
}
}
///
/// The channels to which repo and compile messages are sent
///
public List DevChannels
{
get { return JsonConvert.DeserializeObject>(DataFields[DevChannelIndex]); }
set
{
SanitizeChannelNames(value);
DataFields[DevChannelIndex] = JsonConvert.SerializeObject(value);
}
}
///
/// The channels to which watchdog messages are sent
///
public List WatchdogChannels
{
get { return JsonConvert.DeserializeObject>(DataFields[WDChannelIndex]); }
set
{
SanitizeChannelNames(value);
DataFields[WDChannelIndex] = JsonConvert.SerializeObject(value);
}
}
///
/// The channels to which game messages are sent
///
public List GameChannels
{
get { return JsonConvert.DeserializeObject>(DataFields[GameChannelIndex]); }
set
{
SanitizeChannelNames(value);
DataFields[GameChannelIndex] = JsonConvert.SerializeObject(value);
}
}
///
/// If this chat provider is enabled
///
public bool Enabled
{
get { return Convert.ToBoolean(DataFields[EnabledIndex]); }
set { DataFields[EnabledIndex] = Convert.ToString(value); }
}
///
/// The type of provider
///
public ChatProvider Provider
{
get { return (ChatProvider)Convert.ToInt32(DataFields[ProviderIndex]); }
set { DataFields[ProviderIndex] = Convert.ToString((int)value); }
}
}
///
/// Chat provider for IRC. Admin entries should be user nicknames in normal mode or required channel flags in special mode
///
[DataContract]
public sealed class IRCSetupInfo : ChatSetupInfo
{
const int URLIndex = 0;
const int PortIndex = 1;
const int NickIndex = 2;
const int AuthTargetIndex = 3;
const int AuthMessageIndex = 4;
const int AuthLevelIndex = 5;
const int FieldsLen = 6;
///
/// Construct IRC setup info from optional generic info. Defaults to TGS3 on rizons IRC server
///
/// Optional generic info
public IRCSetupInfo(ChatSetupInfo baseInfo = null) : base(ChatProvider.IRC, baseInfo, FieldsLen)
{
if (!InitializeFields)
return;
Nickname = "TGS3";
URL = "irc.rizon.net";
Port = 6667;
AuthTarget = "";
AuthMessage = "";
AdminsAreSpecial = true;
AuthLevel = IRCMode.Op;
}
///
protected override string SanitizeChannelName(string working)
{
if (working[0] != '#')
return "#" + working;
return working;
}
///
/// The port of the IRC server
///
public ushort Port
{
get { return Convert.ToUInt16(DataFields[BaseIndex + PortIndex]); }
set { DataFields[BaseIndex + PortIndex] = value.ToString(); }
}
///
/// The URL of the IRC server
///
public string URL
{
get { return DataFields[BaseIndex + URLIndex]; }
set { DataFields[BaseIndex + URLIndex] = value; }
}
///
/// The nickname of the IRC bot
///
public string Nickname
{
get { return DataFields[BaseIndex + NickIndex]; }
set { DataFields[BaseIndex + NickIndex] = value; }
}
///
/// The target for sending authentication messages
///
public string AuthTarget
{
get { return DataFields[BaseIndex + AuthTargetIndex]; }
set { DataFields[BaseIndex + AuthTargetIndex] = value; }
}
///
/// The authentication message
///
public string AuthMessage
{
get { return DataFields[BaseIndex + AuthMessageIndex]; }
set { DataFields[BaseIndex + AuthMessageIndex] = value; }
}
///
/// The minimum mode required to use admin bot commands when in special auth mode
///
public IRCMode AuthLevel
{
get { return (IRCMode)Convert.ToInt32(DataFields[BaseIndex + AuthLevelIndex]); }
set { DataFields[BaseIndex + AuthLevelIndex] = Convert.ToString((int)value); }
}
}
///
/// Chat provider for Discord. Admin entires should be user ids in normal mode or group ids in special mode
///
[DataContract]
public sealed class DiscordSetupInfo : ChatSetupInfo
{
const int BotTokenIndex = 0;
const int FieldsLen = 1;
///
/// Construct Discord setup info from optional generic info. Default is not a valid discord bot tokent
///
/// Optional generic info
public DiscordSetupInfo(ChatSetupInfo baseInfo = null) : base(ChatProvider.Discord, baseInfo, FieldsLen)
{
if (!InitializeFields)
return;
BotToken = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"; //needless to say, this is fake
}
///
protected override string SanitizeChannelName(string working)
{
working = working.Replace("<", "").Replace(">", "").Replace("&", ""); //filter out some stuff that can come in the copypasta
try
{
Convert.ToUInt64(working);
}
catch
{
throw new Exception("Invalid Discord channel ID!");
}
return working;
}
///
/// The Discord bot token to use. See https://discordapp.com/developers/applications/me for registering bot accounts
///
public string BotToken
{
get { return DataFields[BaseIndex + BotTokenIndex]; }
set { DataFields[BaseIndex + BotTokenIndex] = value; }
}
}
}