migrate from perforce
This commit is contained in:
26
Concilium.sln
Normal file
26
Concilium.sln
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
|
||||||
|
Microsoft Visual Studio Solution File, Format Version 11.00
|
||||||
|
# Visual Studio 2010
|
||||||
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Concilium", "Concilium\Concilium.csproj", "{2695100D-D24B-4B41-8035-D1E8ED9A87CF}"
|
||||||
|
EndProject
|
||||||
|
Global
|
||||||
|
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||||
|
Debug|Any CPU = Debug|Any CPU
|
||||||
|
Debug|x86 = Debug|x86
|
||||||
|
Release|Any CPU = Release|Any CPU
|
||||||
|
Release|x86 = Release|x86
|
||||||
|
EndGlobalSection
|
||||||
|
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||||
|
{2695100D-D24B-4B41-8035-D1E8ED9A87CF}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{2695100D-D24B-4B41-8035-D1E8ED9A87CF}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{2695100D-D24B-4B41-8035-D1E8ED9A87CF}.Debug|x86.ActiveCfg = Debug|x86
|
||||||
|
{2695100D-D24B-4B41-8035-D1E8ED9A87CF}.Debug|x86.Build.0 = Debug|x86
|
||||||
|
{2695100D-D24B-4B41-8035-D1E8ED9A87CF}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{2695100D-D24B-4B41-8035-D1E8ED9A87CF}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
{2695100D-D24B-4B41-8035-D1E8ED9A87CF}.Release|x86.ActiveCfg = Release|x86
|
||||||
|
{2695100D-D24B-4B41-8035-D1E8ED9A87CF}.Release|x86.Build.0 = Release|x86
|
||||||
|
EndGlobalSection
|
||||||
|
GlobalSection(SolutionProperties) = preSolution
|
||||||
|
HideSolutionNode = FALSE
|
||||||
|
EndGlobalSection
|
||||||
|
EndGlobal
|
||||||
155
Concilium/App.cs
Normal file
155
Concilium/App.cs
Normal file
@@ -0,0 +1,155 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Configuration;
|
||||||
|
using System.Data;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Windows;
|
||||||
|
using System.IO;
|
||||||
|
using System.Threading;
|
||||||
|
using log4net.Appender;
|
||||||
|
using log4net.Config;
|
||||||
|
using log4net;
|
||||||
|
using log4net.Layout;
|
||||||
|
using Concilium.Bot;
|
||||||
|
using Concilium.Helpers;
|
||||||
|
using System.Net;
|
||||||
|
using System.Diagnostics;
|
||||||
|
|
||||||
|
namespace Concilium
|
||||||
|
{
|
||||||
|
public class App
|
||||||
|
{
|
||||||
|
public static void Main(string[] args)
|
||||||
|
{
|
||||||
|
Thread.CurrentThread.Name = "Main";
|
||||||
|
Console.BufferWidth = 120;
|
||||||
|
Console.BufferHeight = 1000;
|
||||||
|
Console.WindowWidth = 120;
|
||||||
|
|
||||||
|
var directory = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), "Concilium");
|
||||||
|
|
||||||
|
var allConsoleAppender = new ColoredConsoleAppender();
|
||||||
|
allConsoleAppender.Layout = new PatternLayout("%message (%logger)%newline");
|
||||||
|
var debugMapping = new log4net.Appender.ColoredConsoleAppender.LevelColors()
|
||||||
|
{
|
||||||
|
Level = log4net.Core.Level.Debug,
|
||||||
|
ForeColor = ColoredConsoleAppender.Colors.HighIntensity
|
||||||
|
};
|
||||||
|
var infoMapping = new log4net.Appender.ColoredConsoleAppender.LevelColors()
|
||||||
|
{
|
||||||
|
Level = log4net.Core.Level.Info,
|
||||||
|
ForeColor = ColoredConsoleAppender.Colors.White
|
||||||
|
};
|
||||||
|
var warningMapping = new log4net.Appender.ColoredConsoleAppender.LevelColors()
|
||||||
|
{
|
||||||
|
Level = log4net.Core.Level.Warn,
|
||||||
|
ForeColor = ColoredConsoleAppender.Colors.Yellow
|
||||||
|
};
|
||||||
|
var errorMapping = new log4net.Appender.ColoredConsoleAppender.LevelColors()
|
||||||
|
{
|
||||||
|
Level = log4net.Core.Level.Error,
|
||||||
|
ForeColor = ColoredConsoleAppender.Colors.Red
|
||||||
|
};
|
||||||
|
var fatalMapping = new log4net.Appender.ColoredConsoleAppender.LevelColors()
|
||||||
|
{
|
||||||
|
Level = log4net.Core.Level.Fatal,
|
||||||
|
BackColor = ColoredConsoleAppender.Colors.Red,
|
||||||
|
ForeColor = ColoredConsoleAppender.Colors.Yellow
|
||||||
|
};
|
||||||
|
allConsoleAppender.AddMapping(debugMapping);
|
||||||
|
allConsoleAppender.AddMapping(infoMapping);
|
||||||
|
allConsoleAppender.AddMapping(warningMapping);
|
||||||
|
allConsoleAppender.AddMapping(errorMapping);
|
||||||
|
allConsoleAppender.AddMapping(fatalMapping);
|
||||||
|
var levelRangeFilter = new log4net.Filter.LevelRangeFilter();
|
||||||
|
levelRangeFilter.LevelMin = log4net.Core.Level.Info;
|
||||||
|
levelRangeFilter.LevelMax = log4net.Core.Level.Off;
|
||||||
|
var noMessageTypesFilter = new log4net.Filter.LoggerMatchFilter();
|
||||||
|
noMessageTypesFilter.LoggerToMatch = "MESSAGETYPES";
|
||||||
|
noMessageTypesFilter.AcceptOnMatch = false;
|
||||||
|
noMessageTypesFilter.Next = levelRangeFilter;
|
||||||
|
var noConciliumFilter = new log4net.Filter.LoggerMatchFilter();
|
||||||
|
noConciliumFilter.LoggerToMatch = Log.Get().Logger.Name;
|
||||||
|
noConciliumFilter.AcceptOnMatch = false;
|
||||||
|
noConciliumFilter.Next = noMessageTypesFilter;
|
||||||
|
allConsoleAppender.AddFilter(noConciliumFilter);
|
||||||
|
allConsoleAppender.ActivateOptions();
|
||||||
|
|
||||||
|
var conciliumConsoleAppender = new ColoredConsoleAppender();
|
||||||
|
var conciliumFilter = new log4net.Filter.LoggerMatchFilter();
|
||||||
|
conciliumFilter.LoggerToMatch = Log.Get().Logger.Name;
|
||||||
|
conciliumFilter.AcceptOnMatch = true;
|
||||||
|
conciliumFilter.Next = new log4net.Filter.DenyAllFilter();
|
||||||
|
var ownMapping = new log4net.Appender.ColoredConsoleAppender.LevelColors()
|
||||||
|
{
|
||||||
|
Level = log4net.Core.Level.Info,
|
||||||
|
ForeColor = ColoredConsoleAppender.Colors.Cyan
|
||||||
|
};
|
||||||
|
var ownErrorMapping = new log4net.Appender.ColoredConsoleAppender.LevelColors()
|
||||||
|
{
|
||||||
|
Level = log4net.Core.Level.Error,
|
||||||
|
ForeColor = ColoredConsoleAppender.Colors.Red
|
||||||
|
};
|
||||||
|
conciliumConsoleAppender.AddMapping(ownMapping);
|
||||||
|
conciliumConsoleAppender.AddMapping(errorMapping);
|
||||||
|
conciliumConsoleAppender.AddMapping(fatalMapping);
|
||||||
|
conciliumConsoleAppender.AddMapping(warningMapping);
|
||||||
|
conciliumConsoleAppender.AddFilter(conciliumFilter);
|
||||||
|
conciliumConsoleAppender.Layout = new PatternLayout("%message%newline");
|
||||||
|
conciliumConsoleAppender.ActivateOptions();
|
||||||
|
|
||||||
|
var fileAppender = new FileAppender();
|
||||||
|
fileAppender.File = Path.Combine(directory, "Concilium.log");
|
||||||
|
fileAppender.Layout = new PatternLayout("%timestamp [%thread] %-5level %logger - %message%newline");
|
||||||
|
fileAppender.ActivateOptions();
|
||||||
|
|
||||||
|
BasicConfigurator.Configure(new IAppender[] { conciliumConsoleAppender, allConsoleAppender, fileAppender });
|
||||||
|
|
||||||
|
var concilium = new Concilium.Bot.Concilium();
|
||||||
|
|
||||||
|
ConsoleHelpers.SetConsoleCtrlHandler(new HandlerRoutine((t) =>
|
||||||
|
{
|
||||||
|
var isclosing = false;
|
||||||
|
switch (t)
|
||||||
|
{
|
||||||
|
case CtrlTypes.CTRL_C_EVENT:
|
||||||
|
isclosing = true;
|
||||||
|
Console.WriteLine("CTRL+C received!");
|
||||||
|
break;
|
||||||
|
|
||||||
|
case CtrlTypes.CTRL_BREAK_EVENT:
|
||||||
|
isclosing = true;
|
||||||
|
Console.WriteLine("CTRL+BREAK received!");
|
||||||
|
break;
|
||||||
|
|
||||||
|
case CtrlTypes.CTRL_CLOSE_EVENT:
|
||||||
|
isclosing = true;
|
||||||
|
Console.WriteLine("Program being closed!");
|
||||||
|
break;
|
||||||
|
|
||||||
|
case CtrlTypes.CTRL_LOGOFF_EVENT:
|
||||||
|
case CtrlTypes.CTRL_SHUTDOWN_EVENT:
|
||||||
|
isclosing = true;
|
||||||
|
Console.WriteLine("User is logging off!");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isclosing && concilium != null)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
concilium.Save();
|
||||||
|
concilium = null;
|
||||||
|
}
|
||||||
|
catch (Exception)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}), true);
|
||||||
|
|
||||||
|
concilium.Run();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
18
Concilium/Bot/BotFeatureAttribute.cs
Normal file
18
Concilium/Bot/BotFeatureAttribute.cs
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
|
||||||
|
namespace Concilium.Bot
|
||||||
|
{
|
||||||
|
[AttributeUsage(AttributeTargets.Class, AllowMultiple = true)]
|
||||||
|
public class BotFeatureAttribute : Attribute
|
||||||
|
{
|
||||||
|
public BotFeatureAttribute(string _sName)
|
||||||
|
{
|
||||||
|
Name = _sName;
|
||||||
|
}
|
||||||
|
|
||||||
|
public string Name { get; private set; }
|
||||||
|
}
|
||||||
|
}
|
||||||
23
Concilium/Bot/BotFeatureBase.cs
Normal file
23
Concilium/Bot/BotFeatureBase.cs
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
|
||||||
|
namespace Concilium.Bot
|
||||||
|
{
|
||||||
|
public abstract class BotFeatureBase : IBotFeature
|
||||||
|
{
|
||||||
|
public virtual IrcDotNet.IrcClient Client
|
||||||
|
{
|
||||||
|
get;
|
||||||
|
set;
|
||||||
|
}
|
||||||
|
|
||||||
|
public virtual void Load()
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public abstract void Execute(string _sCommand, string _sSource, string _sTarget, string _sMessage, IList<string> _parameters, string _ip);
|
||||||
|
}
|
||||||
|
}
|
||||||
580
Concilium/Bot/Concilium.cs
Normal file
580
Concilium/Bot/Concilium.cs
Normal file
@@ -0,0 +1,580 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading;
|
||||||
|
using System.Text.RegularExpressions;
|
||||||
|
using System.Net;
|
||||||
|
using System.Web;
|
||||||
|
using Newtonsoft.Json.Linq;
|
||||||
|
using Newtonsoft.Json;
|
||||||
|
using System.IO;
|
||||||
|
using System.Xml;
|
||||||
|
using System.ServiceModel.Syndication;
|
||||||
|
using System.Net.Sockets;
|
||||||
|
using System.Collections;
|
||||||
|
using Concilium.Helpers;
|
||||||
|
using System.Net.NetworkInformation;
|
||||||
|
using System.Diagnostics;
|
||||||
|
using System.Drawing;
|
||||||
|
using IrcDotNet;
|
||||||
|
using System.Reflection;
|
||||||
|
|
||||||
|
namespace Concilium.Bot
|
||||||
|
{
|
||||||
|
public class RssItem
|
||||||
|
{
|
||||||
|
public string Title;
|
||||||
|
public string Link;
|
||||||
|
}
|
||||||
|
|
||||||
|
public class RssFeed
|
||||||
|
{
|
||||||
|
public string Url;
|
||||||
|
public List<RssItem> LastItems;
|
||||||
|
}
|
||||||
|
|
||||||
|
public class UserInfo
|
||||||
|
{
|
||||||
|
public DateTime? LastWritten;
|
||||||
|
public DateTime? LastJoined;
|
||||||
|
public DateTime? LastLeft;
|
||||||
|
|
||||||
|
public List<RssFeed> SubscribedFeeds;
|
||||||
|
}
|
||||||
|
|
||||||
|
public class BotData
|
||||||
|
{
|
||||||
|
public Dictionary<string, UserInfo> Info;
|
||||||
|
public Dictionary<string, List<string>> ChannelUsers;
|
||||||
|
public List<string> LogBlackList;
|
||||||
|
public Mafia Mafia;
|
||||||
|
public Resistance Resistance;
|
||||||
|
public PredicateLogic PredicateLogic;
|
||||||
|
}
|
||||||
|
|
||||||
|
public class Concilium : IrcBot
|
||||||
|
{
|
||||||
|
private Timer userMonitorTimer;
|
||||||
|
private Timer saveTimer;
|
||||||
|
private Timer rssTimer;
|
||||||
|
public static BotData Data;
|
||||||
|
private List<IBotFeature> botFeatures = new List<IBotFeature>();
|
||||||
|
|
||||||
|
protected override void InitializeChatCommandProcessors()
|
||||||
|
{
|
||||||
|
foreach (var type in Assembly.GetExecutingAssembly().GetTypes())
|
||||||
|
{
|
||||||
|
var attributes = type.GetCustomAttributes(typeof(BotFeatureAttribute), true).Cast<BotFeatureAttribute>();
|
||||||
|
if (attributes.Count() == 0)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
var botFeature = Activator.CreateInstance(type) as IBotFeature;
|
||||||
|
botFeatures.Add(botFeature);
|
||||||
|
foreach (var attribute in attributes)
|
||||||
|
{
|
||||||
|
var name = attribute.Name;
|
||||||
|
ChatCommandProcessors.Add(name, (client, source, targets, message, parameters) =>
|
||||||
|
{
|
||||||
|
string sIp = null;
|
||||||
|
if (source is IrcUser)
|
||||||
|
{
|
||||||
|
sIp = GetIP((source as IrcUser).HostName);
|
||||||
|
}
|
||||||
|
botFeature.Execute(name, source.Name, targets.First().Name, message, parameters, sIp);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ChatCommandProcessors.Add(".random", ProcessChatRandom);
|
||||||
|
ChatCommandProcessors.Add(".log", ProcessLog);
|
||||||
|
ChatCommandProcessors.Add(".help", ProcessHelp);
|
||||||
|
ChatCommandProcessors.Add(".admin", ProcessAdmin);
|
||||||
|
ChatCommandProcessors.Add(".blacklist", ProcessBlackList);
|
||||||
|
ChatCommandProcessors.Add(">", ProcessPredicateLogic);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void InitializeCommandProcessors()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public Concilium()
|
||||||
|
{
|
||||||
|
Load();
|
||||||
|
Connect();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void OnClientRegistered(IrcClient client)
|
||||||
|
{
|
||||||
|
base.OnClientRegistered(client);
|
||||||
|
|
||||||
|
Client.Channels.Join("#makegames");
|
||||||
|
Client.Channels.Join("#sppro");
|
||||||
|
|
||||||
|
foreach (var botFeature in botFeatures)
|
||||||
|
{
|
||||||
|
botFeature.Client = Client;
|
||||||
|
botFeature.Load();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void OnChannelMessageReceived(IrcChannel channel, IrcMessageEventArgs e)
|
||||||
|
{
|
||||||
|
UpdateLastWrite(e.Source.Name, e.Text, e.Targets.Select(t => t.Name));
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void OnLocalUserMessageReceived(IrcLocalUser localUser, IrcMessageEventArgs e)
|
||||||
|
{
|
||||||
|
UpdateLastWrite(e.Source.Name, e.Text, e.Targets.Select(t => t.Name));
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void UpdateLastWrite(string _sNickName, string _sMessage, IEnumerable<string> _targets)
|
||||||
|
{
|
||||||
|
if (!Concilium.Data.Info.ContainsKey(_sNickName))
|
||||||
|
Concilium.Data.Info[_sNickName] = new UserInfo();
|
||||||
|
|
||||||
|
Concilium.Data.Info[_sNickName].LastWritten = DateTime.Now;
|
||||||
|
|
||||||
|
var target = _targets.FirstOrDefault();
|
||||||
|
string channel;
|
||||||
|
if (string.IsNullOrEmpty(target))
|
||||||
|
channel = "#makegames";//return;
|
||||||
|
else
|
||||||
|
channel = target;
|
||||||
|
|
||||||
|
if (channel[0] == '#')
|
||||||
|
channel = channel.Substring(1);
|
||||||
|
|
||||||
|
var now = DateTime.Now.Year.ToString() + '-' + DateTime.Now.Month.ToString() + "-" + DateTime.Now.Day.ToString();
|
||||||
|
var path = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), "Concilium", channel, now + ".log");
|
||||||
|
Directory.CreateDirectory(Path.GetDirectoryName(path));
|
||||||
|
using (var stream = new FileStream(path, FileMode.Append))
|
||||||
|
{
|
||||||
|
var message = DateTime.Now.Hour + ":" + DateTime.Now.Minute + ":" + DateTime.Now.Second + " " + _sNickName + " " + _sMessage + "\r\n";
|
||||||
|
var bytes = Encoding.UTF8.GetBytes(message);
|
||||||
|
stream.Write(bytes, 0, bytes.Length);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void OnLocalUserJoinedChannel(IrcLocalUser localUser, IrcChannelEventArgs e)
|
||||||
|
{
|
||||||
|
if (!Concilium.Data.ChannelUsers.ContainsKey(e.Channel.Name))
|
||||||
|
{
|
||||||
|
Concilium.Data.ChannelUsers[e.Channel.Name] = new List<string>();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void OnLocalUserLeftChannel(IrcLocalUser localUser, IrcChannelEventArgs e)
|
||||||
|
{
|
||||||
|
if (Concilium.Data.ChannelUsers.ContainsKey(e.Channel.Name))
|
||||||
|
{
|
||||||
|
Concilium.Data.ChannelUsers.Remove(e.Channel.Name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Load()
|
||||||
|
{
|
||||||
|
if (Concilium.Data != null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
saveTimer = new Timer((object botImpl) =>
|
||||||
|
{
|
||||||
|
this.Save();
|
||||||
|
}, this, 0, 60000);
|
||||||
|
|
||||||
|
var path = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), "Concilium", "data.json");
|
||||||
|
if (File.Exists(path))
|
||||||
|
{
|
||||||
|
Log.Get().Info(string.Format("Loading Concilium.Data from: {0}", path));
|
||||||
|
var dataJson = File.ReadAllText(path);
|
||||||
|
Concilium.Data = JsonConvert.DeserializeObject<BotData>(dataJson);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Concilium.Data == null)
|
||||||
|
Concilium.Data = new BotData();
|
||||||
|
if (Concilium.Data.Info == null)
|
||||||
|
Concilium.Data.Info = new Dictionary<string, UserInfo>();
|
||||||
|
if (Concilium.Data.ChannelUsers == null)
|
||||||
|
Concilium.Data.ChannelUsers = new Dictionary<string, List<string>>();
|
||||||
|
if (Concilium.Data.LogBlackList == null)
|
||||||
|
Concilium.Data.LogBlackList = new List<string>();
|
||||||
|
if (Concilium.Data.PredicateLogic == null)
|
||||||
|
Concilium.Data.PredicateLogic = new PredicateLogic();
|
||||||
|
if (Concilium.Data.Mafia == null)
|
||||||
|
Concilium.Data.Mafia = new Mafia();
|
||||||
|
if (Concilium.Data.Resistance == null)
|
||||||
|
Concilium.Data.Resistance = new Resistance();
|
||||||
|
|
||||||
|
foreach (var info in Concilium.Data.Info)
|
||||||
|
{
|
||||||
|
if (info.Value.SubscribedFeeds == null)
|
||||||
|
info.Value.SubscribedFeeds = new List<RssFeed>();
|
||||||
|
|
||||||
|
foreach (var feed in info.Value.SubscribedFeeds)
|
||||||
|
{
|
||||||
|
if (feed.LastItems == null)
|
||||||
|
feed.LastItems = new List<RssItem>();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Save()
|
||||||
|
{
|
||||||
|
if (Concilium.Data == null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
var path = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), "Concilium", "data.json");
|
||||||
|
Log.Get().Info(string.Format("Saving data to: {0}", path));
|
||||||
|
var dataJson = JsonConvert.SerializeObject(Concilium.Data, Newtonsoft.Json.Formatting.Indented);
|
||||||
|
while (true)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
File.WriteAllText(path, dataJson);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
catch (Exception)
|
||||||
|
{
|
||||||
|
Thread.Sleep(1000);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private List<string> GetParameters(string message)
|
||||||
|
{
|
||||||
|
return CmdLineToArgvW.SplitArgs(message).ToList();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Color ColorFromHSV(double hue, double saturation, double value)
|
||||||
|
{
|
||||||
|
int hi = Convert.ToInt32(Math.Floor(hue / 60)) % 6;
|
||||||
|
double f = hue / 60 - Math.Floor(hue / 60);
|
||||||
|
|
||||||
|
value = value * 255;
|
||||||
|
int v = Convert.ToInt32(value);
|
||||||
|
int p = Convert.ToInt32(value * (1 - saturation));
|
||||||
|
int q = Convert.ToInt32(value * (1 - f * saturation));
|
||||||
|
int t = Convert.ToInt32(value * (1 - (1 - f) * saturation));
|
||||||
|
|
||||||
|
if (hi == 0)
|
||||||
|
return Color.FromArgb(255, v, t, p);
|
||||||
|
else if (hi == 1)
|
||||||
|
return Color.FromArgb(255, q, v, p);
|
||||||
|
else if (hi == 2)
|
||||||
|
return Color.FromArgb(255, p, v, t);
|
||||||
|
else if (hi == 3)
|
||||||
|
return Color.FromArgb(255, p, q, v);
|
||||||
|
else if (hi == 4)
|
||||||
|
return Color.FromArgb(255, t, p, v);
|
||||||
|
else
|
||||||
|
return Color.FromArgb(255, v, p, q);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void ProcessHelp(IrcClient client, IIrcMessageSource source, IList<IIrcMessageTarget> targets, string message, IList<string> parameters)
|
||||||
|
{
|
||||||
|
Client.LocalUser.SendMessage(GetDefaultReplyTargets(client, source, targets), "I understand following commands: " + string.Join(" ", ChatCommandProcessors.Keys));
|
||||||
|
}
|
||||||
|
|
||||||
|
private void ProcessBlackList(IrcClient client, IIrcMessageSource source, IList<IIrcMessageTarget> targets, string message, IList<string> parameters)
|
||||||
|
{
|
||||||
|
if (!IsOp(source))
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (parameters.Count < 1)
|
||||||
|
{
|
||||||
|
Client.LocalUser.SendMessage(GetDefaultReplyTargets(client, source, targets), "Usage: .blacklist {show|add nickname|del nickname}.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (parameters[0] == "show")
|
||||||
|
{
|
||||||
|
Client.LocalUser.SendMessage(GetDefaultReplyTargets(client, source, targets), "Blacklisted members: " + string.Join(", ", Concilium.Data.LogBlackList));
|
||||||
|
}
|
||||||
|
else if (parameters[0] == "add")
|
||||||
|
{
|
||||||
|
if (parameters.Count > 1 && !string.IsNullOrEmpty(parameters[1]))
|
||||||
|
{
|
||||||
|
Concilium.Data.LogBlackList.Add(parameters[1]);
|
||||||
|
Client.LocalUser.SendMessage(GetDefaultReplyTargets(client, source, targets), "Added " + parameters[1] + " to the black list.");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Client.LocalUser.SendMessage(GetDefaultReplyTargets(client, source, targets), "Can't add to black list. Nickname was not specified.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (parameters[0] == "del")
|
||||||
|
{
|
||||||
|
if (parameters.Count > 1 && !string.IsNullOrEmpty(parameters[1]))
|
||||||
|
{
|
||||||
|
if (Concilium.Data.LogBlackList.Remove(parameters[1]))
|
||||||
|
{
|
||||||
|
Client.LocalUser.SendMessage(GetDefaultReplyTargets(client, source, targets), "Removed " + parameters[1] + " from the black list.");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Client.LocalUser.SendMessage(GetDefaultReplyTargets(client, source, targets), parameters[1] + " was not in the black list.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Client.LocalUser.SendMessage(GetDefaultReplyTargets(client, source, targets), "Can't add to black list. Nickname was not specified.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Client.LocalUser.SendMessage(GetDefaultReplyTargets(client, source, targets), "Usage: .blacklist {show|add nickname|del nickname}.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void ProcessPredicateLogic(IrcClient client, IIrcMessageSource source, IList<IIrcMessageTarget> targets, string message, IList<string> parameters)
|
||||||
|
{
|
||||||
|
var input = string.Join(" ", parameters);
|
||||||
|
var output = Concilium.Data.PredicateLogic.Parse(input);
|
||||||
|
if (!string.IsNullOrEmpty(output))
|
||||||
|
Client.LocalUser.SendMessage(GetDefaultReplyTargets(client, source, targets), output);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void ProcessLog(IrcClient client, IIrcMessageSource source, IList<IIrcMessageTarget> targets, string message, IList<string> parameters)
|
||||||
|
{
|
||||||
|
if (parameters.Count < 2)
|
||||||
|
{
|
||||||
|
Client.LocalUser.SendMessage(GetDefaultReplyTargets(client, source, targets), "Usage: .log number unit (highlight). Unit is either s(econd), m(inute), h(our), d(ay) or w(eek).");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
int number = 0;
|
||||||
|
if (!int.TryParse(parameters[0], out number))
|
||||||
|
{
|
||||||
|
Client.LocalUser.SendMessage(GetDefaultReplyTargets(client, source, targets), "First parameter must be an integer.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
string unit = parameters[1].ToLower();
|
||||||
|
|
||||||
|
TimeSpan logDuration = new TimeSpan();
|
||||||
|
if (unit == "s")
|
||||||
|
logDuration = TimeSpan.FromSeconds(number);
|
||||||
|
else if (unit == "m")
|
||||||
|
logDuration = TimeSpan.FromMinutes(number);
|
||||||
|
else if (unit == "h")
|
||||||
|
logDuration = TimeSpan.FromHours(number);
|
||||||
|
else if (unit == "d")
|
||||||
|
logDuration = TimeSpan.FromDays(number);
|
||||||
|
else if (unit == "w")
|
||||||
|
logDuration = TimeSpan.FromDays(7 * number);
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Client.LocalUser.SendMessage(GetDefaultReplyTargets(client, source, targets), "Second parameter must be either s(econd), m(inute), h(our), d(ay) or w(eek).");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (logDuration > TimeSpan.FromHours(2) && !IsOp(source))
|
||||||
|
logDuration = TimeSpan.FromHours(2);
|
||||||
|
|
||||||
|
DateTime startDate = DateTime.Now - logDuration;
|
||||||
|
DateTime endDate = new DateTime(DateTime.Now.Year, DateTime.Now.Month, DateTime.Now.Day + 1);
|
||||||
|
endDate.AddMilliseconds(-1);
|
||||||
|
|
||||||
|
var target = targets.FirstOrDefault();
|
||||||
|
string channel;
|
||||||
|
if (target == null || string.IsNullOrEmpty(target.Name))
|
||||||
|
channel = "#makegames";//return;
|
||||||
|
else
|
||||||
|
channel = target.Name;
|
||||||
|
|
||||||
|
if (channel[0] == '#')
|
||||||
|
channel = channel.Substring(1);
|
||||||
|
|
||||||
|
var userColors = new Dictionary<string, System.Drawing.Color>();
|
||||||
|
var log = new List<dynamic>();
|
||||||
|
for (DateTime date = startDate; date <= endDate; date = date.AddDays(1))
|
||||||
|
{
|
||||||
|
var now = date.Year.ToString() + '-' + date.Month.ToString() + "-" + date.Day.ToString();
|
||||||
|
var path = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), "Concilium", channel, now + ".log");
|
||||||
|
if (File.Exists(path))
|
||||||
|
{
|
||||||
|
using (var sr = new StreamReader(path))
|
||||||
|
{
|
||||||
|
log.Add(date.ToLongDateString());
|
||||||
|
|
||||||
|
string sMessage = sr.ReadLine();
|
||||||
|
while (sMessage != null)
|
||||||
|
{
|
||||||
|
var tokens = sMessage.ReverseFormat("{0}:{1}:{2} {3} {4}");
|
||||||
|
var logDay = new DateTime(date.Year, date.Month, date.Day, int.Parse(tokens[0]), int.Parse(tokens[1]), int.Parse(tokens[2]));
|
||||||
|
if (logDay > startDate)
|
||||||
|
{
|
||||||
|
var nickName = tokens[3];
|
||||||
|
var messageContent = tokens[4];
|
||||||
|
|
||||||
|
log.Add(new
|
||||||
|
{
|
||||||
|
time = logDay.ToLongTimeString(),
|
||||||
|
nick = nickName,
|
||||||
|
message = messageContent
|
||||||
|
});
|
||||||
|
|
||||||
|
userColors[nickName] = new Color();
|
||||||
|
}
|
||||||
|
|
||||||
|
sMessage = sr.ReadLine();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
string result = "<html><head><style type=\"text/css\">";
|
||||||
|
result += "body, document, table { font-family: Verdana, sans-serif; background: #222; color: white; margin: 0; padding: 0; width: 100%; } ";
|
||||||
|
result += "p { margin: 0px } ";
|
||||||
|
result += "a { color: #80A0FF } ";
|
||||||
|
result += "a:visited { color: #A080FF } ";
|
||||||
|
result += ".date { font-size: 18px; margin: 5px; } ";
|
||||||
|
result += ".time { font-size: 10px; margin: 2px; width: 80px; } ";
|
||||||
|
result += ".nick { font-weight: bold; margin: 2px; text-align: right; width: 1px; } ";
|
||||||
|
result += ".highlight { background: #FFE0A0; color: #102040; } ";
|
||||||
|
result += "</style></head><body><table>";
|
||||||
|
|
||||||
|
double angle = 0.0;
|
||||||
|
var users = userColors.Keys.ToList();
|
||||||
|
foreach (var user in users)
|
||||||
|
{
|
||||||
|
userColors[user] = ColorFromHSV(angle, 0.75, 0.75);
|
||||||
|
angle += 360.0 / users.Count;
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach (var logEntry in log)
|
||||||
|
{
|
||||||
|
if (logEntry is string)
|
||||||
|
{
|
||||||
|
result += "<tr><td colspan=\"3\" class=\"date\">" + (logEntry as string) + "</td></tr>";
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
var colorString = ColorTranslator.ToHtml(userColors[logEntry.nick]);
|
||||||
|
result += "<tr>";
|
||||||
|
result += "<td class=\"time\">" + logEntry.time + "</td>";
|
||||||
|
result += "<td class=\"nick\" style=\"color:" + colorString + "\"><" + logEntry.nick + "></td>";
|
||||||
|
|
||||||
|
var sMessage = Regex.Replace(logEntry.message, "http\\://[a-zA-Z0-9\\-\\.]+(/\\S*)?", "<a href=\"$&\">$&</a>");
|
||||||
|
sMessage = Regex.Replace(sMessage, "https\\://[a-zA-Z0-9\\-\\.]+(/\\S*)?", "<a href=\"$&\">$&</a>");
|
||||||
|
result += "<td class=\"msg\">" + HttpUtility.HtmlEncode(sMessage) + "</td>";
|
||||||
|
result += "</tr>";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
result += "</html></body>";
|
||||||
|
if (parameters.Count > 2)
|
||||||
|
result = Regex.Replace(result, parameters[2], "<span class=\"highlight\">$&</span>");
|
||||||
|
|
||||||
|
using (var wc = new WebClient())
|
||||||
|
{
|
||||||
|
var reqparm = new System.Collections.Specialized.NameValueCollection();
|
||||||
|
reqparm.Add("file", result);
|
||||||
|
byte[] responsebytes = wc.UploadValues("http://xTr1m.com/conciliumlog.php", "POST", reqparm);
|
||||||
|
string responsebody = Encoding.UTF8.GetString(responsebytes);
|
||||||
|
|
||||||
|
Client.LocalUser.SendMessage(GetDefaultReplyTargets(client, source, targets), "Log updated: http://www.xTr1m.com/temp/concilium.html");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private bool IsOp(IIrcMessageSource source)
|
||||||
|
{
|
||||||
|
if (source.Name == "xTr1m")
|
||||||
|
return true;
|
||||||
|
|
||||||
|
return source.Name.StartsWith("!") || source.Name.StartsWith("@");
|
||||||
|
}
|
||||||
|
|
||||||
|
private void ProcessAdmin(IrcClient client, IIrcMessageSource source, IList<IIrcMessageTarget> targets, string message, IList<string> parameters)
|
||||||
|
{
|
||||||
|
if (source.Name != "xTr1m" && source.Name != "Concilium")
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (parameters[0] == "say")
|
||||||
|
{
|
||||||
|
Client.LocalUser.SendMessage(parameters[1], string.Join(" ", parameters.Skip(2)));
|
||||||
|
}
|
||||||
|
else if (parameters[0] == "restart")
|
||||||
|
{
|
||||||
|
Disconnect();
|
||||||
|
Connect();
|
||||||
|
}
|
||||||
|
else if (parameters[0] == "quit")
|
||||||
|
{
|
||||||
|
this.Save();
|
||||||
|
Disconnect();
|
||||||
|
System.Environment.Exit(0);
|
||||||
|
}
|
||||||
|
else if (parameters[0] == "topic")
|
||||||
|
{
|
||||||
|
client.GetChannel(parameters[1]).SetTopic(string.Join(" ", parameters.Skip(2)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void ProcessChatRandom(IrcClient client, IIrcMessageSource source, IList<IIrcMessageTarget> targets, string message, IList<string> parameters)
|
||||||
|
{
|
||||||
|
if (parameters.Count != 2)
|
||||||
|
throw new InvalidCommandParametersException(".random", 2);
|
||||||
|
|
||||||
|
Log.Get().Info(string.Format("{0} requested a random number", source.Name));
|
||||||
|
var min = double.Parse(parameters[0]);
|
||||||
|
var max = double.Parse(parameters[1]);
|
||||||
|
var len = max - min;
|
||||||
|
var rand = new Random();
|
||||||
|
Client.LocalUser.SendMessage(GetDefaultReplyTargets(client, source, targets), (Math.Floor((rand.NextDouble() * len + min) * 100.0) / 100.0).ToString());
|
||||||
|
}
|
||||||
|
|
||||||
|
public static string GetIP(string hostName)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var host = Dns.GetHostEntry(hostName);
|
||||||
|
foreach (IPAddress ip in host.AddressList)
|
||||||
|
{
|
||||||
|
if (ip.AddressFamily == AddressFamily.InterNetwork)
|
||||||
|
{
|
||||||
|
return ip.ToString();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var nics = NetworkInterface.GetAllNetworkInterfaces();
|
||||||
|
foreach (var nic in nics)
|
||||||
|
{
|
||||||
|
var ipProps = nic.GetIPProperties();
|
||||||
|
|
||||||
|
// We're only interested in IPv4 addresses for this example.
|
||||||
|
var ipv4Addrs = ipProps.UnicastAddresses
|
||||||
|
.Where(addr => addr.Address.AddressFamily == AddressFamily.InterNetwork);
|
||||||
|
|
||||||
|
foreach (var addr in ipv4Addrs)
|
||||||
|
{
|
||||||
|
if (addr.IPv4Mask == null)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
return addr.Address.ToString();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static WebClient CreateWebClient()
|
||||||
|
{
|
||||||
|
var wc = new WebClient();
|
||||||
|
wc.Headers.Add(HttpRequestHeader.UserAgent, "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.11 (KHTML, like Gecko) Chrome/23.0.1271.64 Safari/537.11");
|
||||||
|
wc.Headers.Add(HttpRequestHeader.AcceptLanguage, "de-DE,de;q=0.8,en-US;q=0.6,en;q=0.4");
|
||||||
|
wc.Headers.Add(HttpRequestHeader.Referer, "91.194.90.37");
|
||||||
|
return wc;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
25
Concilium/Bot/Features/FortuneFeature.cs
Normal file
25
Concilium/Bot/Features/FortuneFeature.cs
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
using Concilium.Helpers;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
|
||||||
|
namespace Concilium.Bot.Features
|
||||||
|
{
|
||||||
|
[BotFeature(".fortune")]
|
||||||
|
public class FortuneFeature : BotFeatureBase
|
||||||
|
{
|
||||||
|
public override void Execute(string _sCommand, string _sSource, string _sTarget, string _sMessage, IList<string> _parameters, string _ip)
|
||||||
|
{
|
||||||
|
if (_parameters.Count != 0)
|
||||||
|
throw new InvalidCommandParametersException(".fortune", 0);
|
||||||
|
|
||||||
|
var wc = Concilium.CreateWebClient();
|
||||||
|
var result = Encoding.UTF8.GetString(wc.DownloadData("http://www.fortunefortoday.com/getfortuneonly.php"));
|
||||||
|
result = result.Replace("\n", "");
|
||||||
|
Log.Get().Info(string.Format("{0} requested a fortune cookie", _sSource));
|
||||||
|
|
||||||
|
Client.LocalUser.SendMessage(Concilium.GetDefaultReplyTarget(_sSource, _sTarget), string.Format("{0}: {1}", _sSource, result));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
127
Concilium/Bot/Features/GoogleFeature.cs
Normal file
127
Concilium/Bot/Features/GoogleFeature.cs
Normal file
@@ -0,0 +1,127 @@
|
|||||||
|
using Concilium.Helpers;
|
||||||
|
using Newtonsoft.Json;
|
||||||
|
using Newtonsoft.Json.Linq;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Web;
|
||||||
|
|
||||||
|
namespace Concilium.Bot.Features
|
||||||
|
{
|
||||||
|
[BotFeature(".googlefight")]
|
||||||
|
[BotFeature(".google")]
|
||||||
|
[BotFeature(".googleimage")]
|
||||||
|
public class GoogleFeature : BotFeatureBase
|
||||||
|
{
|
||||||
|
public override void Execute(string _sCommand, string _sSource, string _sTarget, string _sMessage, IList<string> _parameters, string _ip)
|
||||||
|
{
|
||||||
|
string sReply = null;
|
||||||
|
if (_sCommand == ".googlefight")
|
||||||
|
sReply = ProcessChatGoogleFight(_parameters, _ip);
|
||||||
|
else if (_sCommand == ".google")
|
||||||
|
sReply = ProcessChatGoogle(_parameters, _ip);
|
||||||
|
else if (_sCommand == ".googleimage")
|
||||||
|
sReply = ProcessChatGoogleImage(_parameters, _ip);
|
||||||
|
else
|
||||||
|
throw new NotImplementedException();
|
||||||
|
|
||||||
|
Client.LocalUser.SendMessage(Concilium.GetDefaultReplyTarget(_sSource, _sTarget), sReply);
|
||||||
|
}
|
||||||
|
|
||||||
|
private dynamic SearchGoolgeFor(string _sQuery, string _sType, string _ip)
|
||||||
|
{
|
||||||
|
var wc = Concilium.CreateWebClient();
|
||||||
|
_ip = _ip == null ? "" : "&userip=" + _ip;
|
||||||
|
var result = wc.DownloadData("http://ajax.googleapis.com/ajax/services/search/" + _sType + "?v=1.0&q=" + HttpUtility.UrlEncode(_sQuery) + _ip);
|
||||||
|
|
||||||
|
return JsonConvert.DeserializeObject(Encoding.UTF8.GetString(result));
|
||||||
|
}
|
||||||
|
|
||||||
|
private string ProcessChatGoogle(IList<string> _parameters, string _ip)
|
||||||
|
{
|
||||||
|
var query = string.Join(" ", _parameters);
|
||||||
|
dynamic json = SearchGoolgeFor(query, "web", _ip);
|
||||||
|
|
||||||
|
if (json.responseData == null)
|
||||||
|
{
|
||||||
|
Log.Get().Info(string.Format("Google search failed: {0}", json.responseDetails.Value as string));
|
||||||
|
return string.Format("Google search failed: {0}", json.responseDetails.Value as string);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (json.responseData.results == null || (json.responseData.results is JArray && (json.responseData.results as JArray).Count == 0))
|
||||||
|
{
|
||||||
|
return "No results found";
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
string url = json.responseData.results[0].url.Value;
|
||||||
|
string title = json.responseData.results[0].title.Value;
|
||||||
|
title = HttpUtility.HtmlDecode(title);
|
||||||
|
|
||||||
|
return string.Format("{0} {1}", title, url);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private string ProcessChatGoogleImage(IList<string> _parameters, string _ip)
|
||||||
|
{
|
||||||
|
var query = string.Join(" ", _parameters);
|
||||||
|
var json = SearchGoolgeFor(query, "images", _ip);
|
||||||
|
|
||||||
|
if (json.responseData == null)
|
||||||
|
{
|
||||||
|
Log.Get().Info(string.Format("Google search failed: {0}", json.responseDetails.Value as string));
|
||||||
|
return string.Format("Google search failed: {0}", json.responseDetails.Value as string);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (json.responseData.results == null || (json.responseData.results is JArray && (json.responseData.results as JArray).Count == 0))
|
||||||
|
{
|
||||||
|
return "No results found";
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
string url = json.responseData.results[0].url.Value;
|
||||||
|
string title = json.responseData.results[0].title.Value;
|
||||||
|
title = HttpUtility.HtmlDecode(title);
|
||||||
|
|
||||||
|
return string.Format("{0} {1}", title, url);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private string ProcessChatGoogleFight(IList<string> _parameters, string _ip)
|
||||||
|
{
|
||||||
|
var joinedParams = string.Join(" ", _parameters.ToArray());
|
||||||
|
if (_parameters.Count() != 2)
|
||||||
|
throw new InvalidCommandParametersException(".googlefight", 2);
|
||||||
|
|
||||||
|
var json1 = SearchGoolgeFor(_parameters[0], "web", _ip);
|
||||||
|
var json2 = SearchGoolgeFor(_parameters[1], "web", _ip);
|
||||||
|
|
||||||
|
if (json1.responseData == null || json2.responseData == null)
|
||||||
|
{
|
||||||
|
Log.Get().Info(string.Format("Googlefighting failed: {0} {1}", json1.responseDetails.Value as string, json2.responseDetails.Value as string));
|
||||||
|
return string.Format("Googlefighting failed: {0} {1}", json1.responseDetails.Value as string, json2.responseDetails.Value as string);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
//Count and display the hits
|
||||||
|
var hits1 = int.Parse(json1.responseData.cursor.estimatedResultCount == null ? "0" : json1.responseData.cursor.estimatedResultCount.Value as string);
|
||||||
|
var hits2 = int.Parse(json2.responseData.cursor.estimatedResultCount == null ? "0" : json2.responseData.cursor.estimatedResultCount.Value as string);
|
||||||
|
|
||||||
|
var total = hits1 + hits2;
|
||||||
|
float percent1 = (float)Math.Floor(10000.0f * (float)hits1 / (float)total) / 100.0f;
|
||||||
|
float percent2 = (float)Math.Floor(10000.0f * (float)hits2 / (float)total) / 100.0f;
|
||||||
|
|
||||||
|
var hits1s = json1.responseData.cursor.resultCount == null ? "0" : json1.responseData.cursor.resultCount.Value as string;
|
||||||
|
var hits2s = json2.responseData.cursor.resultCount == null ? "0" : json2.responseData.cursor.resultCount.Value as string;
|
||||||
|
|
||||||
|
Log.Get().Info(string.Format("Googlefighting {0} and {1}", _parameters[0], _parameters[1]));
|
||||||
|
return string.Format("\"{0}\": {1} hits ({2}%), \"{3}\": {4} hits ({5}%)", _parameters[0], hits1s, percent1, _parameters[1], hits2s, percent2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
61
Concilium/Bot/Features/JokeFeature.cs
Normal file
61
Concilium/Bot/Features/JokeFeature.cs
Normal file
@@ -0,0 +1,61 @@
|
|||||||
|
using Concilium.Helpers;
|
||||||
|
using Newtonsoft.Json;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Web;
|
||||||
|
|
||||||
|
namespace Concilium.Bot.Features
|
||||||
|
{
|
||||||
|
[BotFeature(".joke")]
|
||||||
|
public class JokeFeature : BotFeatureBase
|
||||||
|
{
|
||||||
|
public override void Execute(string _sCommand, string _sSource, string _sTarget, string _sMessage, IList<string> _parameters, string _ip)
|
||||||
|
{
|
||||||
|
string target = "";
|
||||||
|
if (_parameters.Count == 1)
|
||||||
|
target = _parameters[0];
|
||||||
|
else if (_parameters.Count > 1)
|
||||||
|
throw new InvalidCommandParametersException(".joke", 1);
|
||||||
|
else
|
||||||
|
{
|
||||||
|
var minDate = DateTime.Now;
|
||||||
|
|
||||||
|
foreach (var entry in Concilium.Data.Info)
|
||||||
|
{
|
||||||
|
if (entry.Value.LastWritten.HasValue && entry.Value.LastWritten.Value < minDate)
|
||||||
|
{
|
||||||
|
minDate = entry.Value.LastWritten.Value;
|
||||||
|
target = entry.Key;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (target == "")
|
||||||
|
target = "Concilium";
|
||||||
|
}
|
||||||
|
|
||||||
|
var wc = Concilium.CreateWebClient();
|
||||||
|
var result = wc.DownloadData("http://api.icndb.com/jokes/random?lastName=&firstName=" + target);
|
||||||
|
|
||||||
|
dynamic json = JsonConvert.DeserializeObject(Encoding.UTF8.GetString(result));
|
||||||
|
|
||||||
|
if (json.type == null || json.type.Value != "success")
|
||||||
|
{
|
||||||
|
Log.Get().Info(string.Format("Joke failed: {0}", _sSource));
|
||||||
|
Client.LocalUser.SendMessage(Concilium.GetDefaultReplyTarget(_sSource, _sTarget), "Joke failed");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
var joke = json.value.joke.Value as string;
|
||||||
|
joke = joke.Replace(" ", " ");
|
||||||
|
joke = joke.Replace(" .", ".");
|
||||||
|
joke = joke.Replace(" ,", ",");
|
||||||
|
joke = joke.Replace(" 's", "'s");
|
||||||
|
joke = HttpUtility.HtmlDecode(joke);
|
||||||
|
Log.Get().Info(string.Format("{0} wants a joke about {1}", _sSource, target));
|
||||||
|
Client.LocalUser.SendMessage(Concilium.GetDefaultReplyTarget(_sSource, _sTarget), joke);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
287
Concilium/Bot/Features/MafiaFeature.cs
Normal file
287
Concilium/Bot/Features/MafiaFeature.cs
Normal file
@@ -0,0 +1,287 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
|
||||||
|
namespace Concilium.Bot.Features
|
||||||
|
{
|
||||||
|
[BotFeature(".mafia")]
|
||||||
|
public class MafiaFeature : BotFeatureBase
|
||||||
|
{
|
||||||
|
public static string MafiaChannel = "#sppro.mafia";
|
||||||
|
|
||||||
|
public override void Load()
|
||||||
|
{
|
||||||
|
var channel = Client.GetChannel(MafiaChannel);
|
||||||
|
if (channel == null)
|
||||||
|
{
|
||||||
|
Client.Channels.Join(MafiaChannel);
|
||||||
|
channel = Client.GetChannel(MafiaChannel);
|
||||||
|
}
|
||||||
|
|
||||||
|
Concilium.Data.Mafia.DayBegins += () =>
|
||||||
|
{
|
||||||
|
foreach (var user in channel.Users)
|
||||||
|
user.Voice();
|
||||||
|
};
|
||||||
|
Concilium.Data.Mafia.NightBegins += () =>
|
||||||
|
{
|
||||||
|
foreach (var user in channel.Users)
|
||||||
|
user.DeVoice();
|
||||||
|
};
|
||||||
|
Concilium.Data.Mafia.OnUserJoined += (nickName) =>
|
||||||
|
{
|
||||||
|
channel.Users.First(u => u.User.NickName == nickName).Voice();
|
||||||
|
};
|
||||||
|
Concilium.Data.Mafia.OnUserDied += (nickName) =>
|
||||||
|
{
|
||||||
|
channel.Users.First(u => u.User.NickName == nickName).DeVoice();
|
||||||
|
};
|
||||||
|
Concilium.Data.Mafia.GameOver += () =>
|
||||||
|
{
|
||||||
|
foreach (var user in channel.Users)
|
||||||
|
user.DeVoice();
|
||||||
|
|
||||||
|
Concilium.Data.Mafia = null;
|
||||||
|
channel.SetModes("-m");
|
||||||
|
};
|
||||||
|
Concilium.Data.Mafia.OnLobbyNotice += (notice) =>
|
||||||
|
{
|
||||||
|
Client.LocalUser.SendMessage(MafiaChannel, notice);
|
||||||
|
};
|
||||||
|
Concilium.Data.Mafia.OnUsersNotice += (users, notice) =>
|
||||||
|
{
|
||||||
|
foreach (var user in users)
|
||||||
|
Client.LocalUser.SendMessage(user, notice);
|
||||||
|
};
|
||||||
|
|
||||||
|
Concilium.Data.Mafia.CheckState();
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void Execute(string _sCommand, string _sSource, string _sTarget, string _sMessage, IList<string> _parameters, string _ip)
|
||||||
|
{
|
||||||
|
if (_parameters.Count == 0)
|
||||||
|
{
|
||||||
|
Client.LocalUser.SendMessage(_sSource, "Mafia is played at the " + MafiaChannel + " channel.");
|
||||||
|
Client.GetChannel(MafiaChannel).Invite(_sSource);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_sTarget != null && _sTarget != MafiaChannel)
|
||||||
|
{
|
||||||
|
Client.LocalUser.SendMessage(_sSource, "Mafia is played at the " + MafiaChannel + " channel.");
|
||||||
|
Client.GetChannel(MafiaChannel).Invite(_sSource);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var action = _parameters[0];
|
||||||
|
if (action == "help")
|
||||||
|
{
|
||||||
|
if (_parameters.Count == 1)
|
||||||
|
Client.LocalUser.SendMessage(_sSource, "Mafia commands: help, create, join, vote, unvote, detect, save, status, kill. Use \".mafia help %command%\" to learn more.");
|
||||||
|
else
|
||||||
|
{
|
||||||
|
var helpAction = _parameters[1];
|
||||||
|
if (helpAction == "help")
|
||||||
|
{
|
||||||
|
Client.LocalUser.SendMessage(_sSource, string.Format("Are you dumb, {0}?", _sSource));
|
||||||
|
}
|
||||||
|
else if (helpAction == "create")
|
||||||
|
{
|
||||||
|
Client.LocalUser.SendMessage(_sSource, "Creates a new mafia game. Expects no _parameters.");
|
||||||
|
}
|
||||||
|
else if (helpAction == "start")
|
||||||
|
{
|
||||||
|
Client.LocalUser.SendMessage(_sSource, "Starts a mafia game when at least 5 players have joined. Expects no parameter.");
|
||||||
|
}
|
||||||
|
else if (helpAction == "join")
|
||||||
|
{
|
||||||
|
Client.LocalUser.SendMessage(_sSource, "Join the current mafia game. Expects no _parameters.");
|
||||||
|
}
|
||||||
|
else if (helpAction == "vote")
|
||||||
|
{
|
||||||
|
Client.LocalUser.SendMessage(_sSource, "Places a vote. May be used several times. Parameter: The nick name of the player you're voting for.");
|
||||||
|
}
|
||||||
|
else if (helpAction == "unvote")
|
||||||
|
{
|
||||||
|
Client.LocalUser.SendMessage(_sSource, "Removes your vote if it exists.");
|
||||||
|
}
|
||||||
|
else if (helpAction == "detect")
|
||||||
|
{
|
||||||
|
Client.LocalUser.SendMessage(_sSource, "Detectives can discover if one player is a mafioso once each night. Parameter: The nick name of the player you're detecting.");
|
||||||
|
}
|
||||||
|
else if (helpAction == "save")
|
||||||
|
{
|
||||||
|
Client.LocalUser.SendMessage(_sSource, "Doctors can rescue one player from a possible mafioso assault. Parameter: The nick name of the player you're detecting.");
|
||||||
|
}
|
||||||
|
else if (helpAction == "kill")
|
||||||
|
{
|
||||||
|
Client.LocalUser.SendMessage(_sSource, "Vigilantes can kill one player at will during the night. Parameter: The nick name of the player to be killed.");
|
||||||
|
}
|
||||||
|
else if (helpAction == "status")
|
||||||
|
{
|
||||||
|
Client.LocalUser.SendMessage(_sSource, "Announces the current game status.");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Client.LocalUser.SendMessage(_sSource, "There's no such command available in mafia.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (action == "reset")
|
||||||
|
{
|
||||||
|
if (Concilium.Data.Mafia != null && _sTarget == "Concilium" && _sSource == Concilium.Data.Mafia.GameCreator)
|
||||||
|
{
|
||||||
|
Client.LocalUser.SendMessage(MafiaChannel, "The mafia game was shut down. (reset command used by " + Concilium.Data.Mafia.GameCreator + ")");
|
||||||
|
Concilium.Data.Mafia = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (action == "create")
|
||||||
|
{
|
||||||
|
if (Concilium.Data.Mafia != null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
Concilium.Data.Mafia = new Mafia();
|
||||||
|
Load();
|
||||||
|
Concilium.Data.Mafia.Init(_sSource);
|
||||||
|
foreach (var user in Client.GetChannel(MafiaChannel).Users)
|
||||||
|
user.DeVoice();
|
||||||
|
|
||||||
|
foreach (var channel in Client.Channels)
|
||||||
|
{
|
||||||
|
if (channel.Name != MafiaChannel)
|
||||||
|
Client.LocalUser.SendMessage(channel, "A mafia game was just created! If you'd like to play, join " + MafiaChannel + " now!");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (action == "start")
|
||||||
|
{
|
||||||
|
if (Concilium.Data.Mafia == null)
|
||||||
|
{
|
||||||
|
Client.LocalUser.SendMessage(_sSource, "There's currently no running mafia game.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Concilium.Data.Mafia.StartGame(_sSource);
|
||||||
|
Client.GetChannel(MafiaChannel).SetModes("+m");
|
||||||
|
}
|
||||||
|
else if (action == "join")
|
||||||
|
{
|
||||||
|
if (Concilium.Data.Mafia == null)
|
||||||
|
{
|
||||||
|
Client.LocalUser.SendMessage(_sSource, "There's currently no running mafia game.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Concilium.Data.Mafia.JoinPlayer(_sSource);
|
||||||
|
}
|
||||||
|
else if (action == "kill")
|
||||||
|
{
|
||||||
|
if (Concilium.Data.Mafia == null)
|
||||||
|
{
|
||||||
|
Client.LocalUser.SendMessage(_sSource, "There's currently no running mafia game.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_sTarget == "Concilium")
|
||||||
|
{
|
||||||
|
Client.LocalUser.SendMessage(_sSource, "Kill only via query!");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (_parameters.Count != 2)
|
||||||
|
Client.LocalUser.SendMessage(_sSource, "Vigilantes can kill one player at will during the night. Parameter: The nick name of the player to be killed.");
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Concilium.Data.Mafia.VoteVigilanteKill(_sSource, _parameters[1]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (action == "vote")
|
||||||
|
{
|
||||||
|
if (Concilium.Data.Mafia == null)
|
||||||
|
{
|
||||||
|
Client.LocalUser.SendMessage(_sSource, "There's currently no running mafia game.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_sTarget == "Concilium")
|
||||||
|
{
|
||||||
|
Client.LocalUser.SendMessage(_sSource, "Place a vote only via query!");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (_parameters.Count != 2)
|
||||||
|
Client.LocalUser.SendMessage(_sSource, "Places a vote. May be used several times. Parameter: The nick name of the player you're voting for.");
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Concilium.Data.Mafia.PlayerVote(_sSource, _parameters[1]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (action == "unvote")
|
||||||
|
{
|
||||||
|
if (Concilium.Data.Mafia == null)
|
||||||
|
{
|
||||||
|
Client.LocalUser.SendMessage(_sSource, "There's currently no running mafia game.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Concilium.Data.Mafia.Unvote(_sSource);
|
||||||
|
}
|
||||||
|
else if (action == "detect")
|
||||||
|
{
|
||||||
|
if (Concilium.Data.Mafia == null)
|
||||||
|
{
|
||||||
|
Client.LocalUser.SendMessage(_sSource, "There's currently no running mafia game.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_sTarget == "Concilium")
|
||||||
|
{
|
||||||
|
Client.LocalUser.SendMessage(_sSource, "Detective work should only be done via query!");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (_parameters.Count != 2)
|
||||||
|
Client.LocalUser.SendMessage(_sSource, "Detectives can discover if one player is a mafioso once each night. Parameter: The nick name of the player you're detecting.");
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Concilium.Data.Mafia.DetectMafioso(_sSource, _parameters[1]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (action == "save")
|
||||||
|
{
|
||||||
|
if (Concilium.Data.Mafia == null)
|
||||||
|
{
|
||||||
|
Client.LocalUser.SendMessage(_sSource, "There's currently no running mafia game.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_sTarget == "Concilium")
|
||||||
|
{
|
||||||
|
Client.LocalUser.SendMessage(_sSource, "Doctor work should only be done via query!");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (_parameters.Count != 2)
|
||||||
|
Client.LocalUser.SendMessage(_sSource, "Doctors can rescue one player from a possible mafioso assault. Parameter: The nick name of the player you're detecting.");
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Concilium.Data.Mafia.SaveCivilist(_sSource, _parameters[1]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (action == "status")
|
||||||
|
{
|
||||||
|
if (Concilium.Data.Mafia == null)
|
||||||
|
{
|
||||||
|
Client.LocalUser.SendMessage(_sSource, "There's currently no running mafia game.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Client.LocalUser.SendMessage(Concilium.GetDefaultReplyTarget(_sSource, _sTarget), Concilium.Data.Mafia.GetStatus());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
143
Concilium/Bot/Features/RssFeature.cs
Normal file
143
Concilium/Bot/Features/RssFeature.cs
Normal file
@@ -0,0 +1,143 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.ServiceModel.Syndication;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading;
|
||||||
|
using System.Xml;
|
||||||
|
|
||||||
|
namespace Concilium.Bot.Features
|
||||||
|
{
|
||||||
|
[BotFeature(".rssadd")]
|
||||||
|
[BotFeature(".rssdel")]
|
||||||
|
[BotFeature(".rsslist")]
|
||||||
|
public class RssFeature : BotFeatureBase
|
||||||
|
{
|
||||||
|
public override void Load()
|
||||||
|
{
|
||||||
|
m_Timer = new Timer(RssTimerStart, this, 0, 60000);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void RssTimerStart(object state)
|
||||||
|
{
|
||||||
|
if (Concilium.Data == null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
foreach (var nickName in Concilium.Data.Info.Keys.ToList())
|
||||||
|
{
|
||||||
|
if (Concilium.Data.Info[nickName].SubscribedFeeds != null)
|
||||||
|
{
|
||||||
|
foreach (var feed in Concilium.Data.Info[nickName].SubscribedFeeds.ToList())
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var reader = XmlReader.Create(feed.Url);
|
||||||
|
var synFeed = SyndicationFeed.Load(reader);
|
||||||
|
|
||||||
|
var newList = new List<RssItem>();
|
||||||
|
foreach (SyndicationItem i in synFeed.Items)
|
||||||
|
{
|
||||||
|
newList.Add(new RssItem() { Link = i.Links[0].Uri.ToString(), Title = i.Title.Text });
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach (var item in newList)
|
||||||
|
{
|
||||||
|
if (feed.LastItems != null && feed.LastItems.Any(li => li.Link == item.Link))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
Client.LocalUser.SendMessage(nickName, string.Format("{0} {1}", item.Title, item.Link));
|
||||||
|
}
|
||||||
|
|
||||||
|
feed.LastItems = newList;
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
Client.LocalUser.SendNotice(nickName, string.Format("Error while checking {0}: {1}", feed.Url, e.Message));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void Execute(string _sCommand, string _sSource, string _sTarget, string _sMessage, IList<string> _parameters, string _ip)
|
||||||
|
{
|
||||||
|
if (_sCommand == ".rssadd")
|
||||||
|
ProcessChatRssAdd(_sSource, _sMessage, _parameters);
|
||||||
|
else if (_sCommand == ".rssdel")
|
||||||
|
ProcessChatRssAdd(_sSource, _sMessage, _parameters);
|
||||||
|
else if (_sCommand == ".rsslist")
|
||||||
|
ProcessChatRssAdd(_sSource, _sMessage, _parameters);
|
||||||
|
else
|
||||||
|
throw new NotImplementedException();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void ProcessChatRssAdd(string _sSource, string _sMessage, IList<string> _parameters)
|
||||||
|
{
|
||||||
|
if (_parameters.Count != 1)
|
||||||
|
throw new InvalidCommandParametersException(".rssadd", 1);
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
XmlReader reader = XmlReader.Create(_parameters[0], new XmlReaderSettings() { DtdProcessing = DtdProcessing.Parse });
|
||||||
|
SyndicationFeed synFeed = SyndicationFeed.Load(reader);
|
||||||
|
|
||||||
|
if (Concilium.Data.Info[_sSource].SubscribedFeeds == null)
|
||||||
|
Concilium.Data.Info[_sSource].SubscribedFeeds = new List<RssFeed>();
|
||||||
|
|
||||||
|
if (!Concilium.Data.Info[_sSource].SubscribedFeeds.Any(f => f.Url == _parameters[0]))
|
||||||
|
{
|
||||||
|
Concilium.Data.Info[_sSource].SubscribedFeeds.Add(new RssFeed() { Url = _parameters[0], LastItems = new List<RssItem>() });
|
||||||
|
Client.LocalUser.SendMessage(_sSource, "RSS feed subscribed successfully");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Client.LocalUser.SendMessage(_sSource, "RSS feed already subscribed");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception)
|
||||||
|
{
|
||||||
|
Client.LocalUser.SendMessage(_sSource, "Error: RSS feed not recognized");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void ProcessChatRssDel(string _sSource, string _sMessage, IList<string> _parameters)
|
||||||
|
{
|
||||||
|
if (_parameters.Count != 1)
|
||||||
|
throw new InvalidCommandParametersException(".rssdel", 1);
|
||||||
|
|
||||||
|
if (Concilium.Data.Info[_sSource].SubscribedFeeds == null)
|
||||||
|
{
|
||||||
|
Client.LocalUser.SendMessage(_sSource, "RSS feed doesn't exist");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
var rssFeed = Concilium.Data.Info[_sSource].SubscribedFeeds.FirstOrDefault(f => f.Url == _parameters[0]);
|
||||||
|
if (rssFeed != null)
|
||||||
|
{
|
||||||
|
Concilium.Data.Info[_sSource].SubscribedFeeds.Remove(rssFeed);
|
||||||
|
Client.LocalUser.SendMessage(_sSource, "RSS feed removed successfully");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Client.LocalUser.SendMessage(_sSource, "RSS feed doesn't exist");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void ProcessChatRssList(string _sSource, string _sMessage, IList<string> _parameters)
|
||||||
|
{
|
||||||
|
if (_parameters.Count != 0)
|
||||||
|
throw new InvalidCommandParametersException(".rsslist", 0);
|
||||||
|
|
||||||
|
Client.LocalUser.SendMessage(_sSource, "Currently subscribed RSS feeds:");
|
||||||
|
if (Concilium.Data.Info[_sSource].SubscribedFeeds == null || Concilium.Data.Info[_sSource].SubscribedFeeds.Count == 0)
|
||||||
|
Client.LocalUser.SendMessage(_sSource, "(none)");
|
||||||
|
else foreach (var rssFeed in Concilium.Data.Info[_sSource].SubscribedFeeds)
|
||||||
|
{
|
||||||
|
Client.LocalUser.SendMessage(_sSource, rssFeed.Url);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private Timer m_Timer;
|
||||||
|
}
|
||||||
|
}
|
||||||
243
Concilium/Bot/Features/TheResistanceFeature.cs
Normal file
243
Concilium/Bot/Features/TheResistanceFeature.cs
Normal file
@@ -0,0 +1,243 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
|
||||||
|
namespace Concilium.Bot.Features
|
||||||
|
{
|
||||||
|
[BotFeature(".resist")]
|
||||||
|
public class TheResistanceFeature : BotFeatureBase
|
||||||
|
{
|
||||||
|
public static string ResistanceChannel = "#sppro.mafia";
|
||||||
|
|
||||||
|
public override void Load()
|
||||||
|
{
|
||||||
|
var channel = Client.GetChannel(ResistanceChannel);
|
||||||
|
if (channel == null)
|
||||||
|
{
|
||||||
|
Client.Channels.Join(ResistanceChannel);
|
||||||
|
channel = Client.GetChannel(ResistanceChannel);
|
||||||
|
}
|
||||||
|
|
||||||
|
Concilium.Data.Resistance.GameOver += () =>
|
||||||
|
{
|
||||||
|
Concilium.Data.Resistance = null;
|
||||||
|
};
|
||||||
|
Concilium.Data.Resistance.OnLobbyNotice += (notice) =>
|
||||||
|
{
|
||||||
|
Client.LocalUser.SendMessage(ResistanceChannel, notice);
|
||||||
|
};
|
||||||
|
Concilium.Data.Resistance.OnUsersNotice += (users, notice) =>
|
||||||
|
{
|
||||||
|
foreach (var user in users)
|
||||||
|
Client.LocalUser.SendMessage(user, notice);
|
||||||
|
};
|
||||||
|
|
||||||
|
Concilium.Data.Resistance.CheckState();
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void Execute(string _sCommand, string _sSource, string _sTarget, string _sMessage, IList<string> _parameters, string _ip)
|
||||||
|
{
|
||||||
|
if (_parameters.Count == 0)
|
||||||
|
{
|
||||||
|
Client.GetChannel(ResistanceChannel).Invite(_sSource);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var action = _parameters[0];
|
||||||
|
if (action == "admin" && (_sSource == "Concilium" || _sSource == "xTr1m"))
|
||||||
|
{
|
||||||
|
action = _parameters[0];
|
||||||
|
_sSource = _parameters[1];
|
||||||
|
_parameters = _parameters.Skip(2).ToList();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_sTarget != null && _sTarget != ResistanceChannel)
|
||||||
|
{
|
||||||
|
Client.LocalUser.SendMessage(_sSource, "The Resistance is played at the " + ResistanceChannel + "channel.");
|
||||||
|
Client.GetChannel(ResistanceChannel).Invite(_sSource);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (action == "help")
|
||||||
|
{
|
||||||
|
if (_parameters.Count == 1)
|
||||||
|
Client.LocalUser.SendMessage(_sSource, "Resistance commands: help, create, reset, join, agree, disagree, team, execute, sabotage, status, missions. Use \".resist help %command%\" to learn more.");
|
||||||
|
else
|
||||||
|
{
|
||||||
|
var helpAction = _parameters[1];
|
||||||
|
if (helpAction == "help")
|
||||||
|
{
|
||||||
|
Client.LocalUser.SendMessage(_sSource, string.Format("Are you dumb, {0}?", _sSource));
|
||||||
|
}
|
||||||
|
else if (helpAction == "create")
|
||||||
|
{
|
||||||
|
Client.LocalUser.SendMessage(_sSource, "Creates a new The Resistance game. Expects no _parameters.");
|
||||||
|
}
|
||||||
|
else if (helpAction == "reset")
|
||||||
|
{
|
||||||
|
Client.LocalUser.SendMessage(_sSource, "The creator of a The Resistance game can shut it down.");
|
||||||
|
}
|
||||||
|
else if (helpAction == "start")
|
||||||
|
{
|
||||||
|
Client.LocalUser.SendMessage(_sSource, "Starts a The Resistance game when at least 5 players have joined. Expects no parameter.");
|
||||||
|
}
|
||||||
|
else if (helpAction == "join")
|
||||||
|
{
|
||||||
|
Client.LocalUser.SendMessage(_sSource, "Join the current The Resistance game. Expects no _parameters.");
|
||||||
|
}
|
||||||
|
else if (helpAction == "status")
|
||||||
|
{
|
||||||
|
Client.LocalUser.SendMessage(_sSource, "Announces the current game status.");
|
||||||
|
}
|
||||||
|
else if (helpAction == "agree")
|
||||||
|
{
|
||||||
|
Client.LocalUser.SendMessage(_sSource, "Only via query. The player hereby agrees with the team proposed by the leader.");
|
||||||
|
}
|
||||||
|
else if (helpAction == "team")
|
||||||
|
{
|
||||||
|
Client.LocalUser.SendMessage(_sSource, "Only via query. The leader hereby declares his or her team members.");
|
||||||
|
}
|
||||||
|
else if (helpAction == "disagree")
|
||||||
|
{
|
||||||
|
Client.LocalUser.SendMessage(_sSource, "Only via query. The player hereby disagrees with the team proposed by the leader.");
|
||||||
|
}
|
||||||
|
else if (helpAction == "execute")
|
||||||
|
{
|
||||||
|
Client.LocalUser.SendMessage(_sSource, "Only via query. The player hereby helps to execute the mission.");
|
||||||
|
}
|
||||||
|
else if (helpAction == "sabotage")
|
||||||
|
{
|
||||||
|
Client.LocalUser.SendMessage(_sSource, "Only via query. The player hereby sabotages the mission. Can only be done by spies.");
|
||||||
|
}
|
||||||
|
else if (helpAction == "missions")
|
||||||
|
{
|
||||||
|
Client.LocalUser.SendMessage(_sSource, "Posts the mission Concilium.Data defined in the rules for this game (amount of team members and sabotages per mission).");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Client.LocalUser.SendMessage(_sSource, "There's no such command available in The Resistance.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (action == "reset")
|
||||||
|
{
|
||||||
|
if (Concilium.Data.Resistance != null && _sTarget == null && (_sSource == Concilium.Data.Resistance.GameCreator || _sSource == "xTr1m"))
|
||||||
|
{
|
||||||
|
Client.LocalUser.SendMessage(ResistanceChannel, "This The Resistance game was shut down. (reset command used by " + Concilium.Data.Resistance.GameCreator + ")");
|
||||||
|
Concilium.Data.Resistance = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (action == "create")
|
||||||
|
{
|
||||||
|
if (Concilium.Data.Resistance != null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
Concilium.Data.Resistance = new Resistance();
|
||||||
|
Load();
|
||||||
|
Concilium.Data.Resistance.Init(_sSource);
|
||||||
|
|
||||||
|
foreach (var channel in Client.Channels)
|
||||||
|
{
|
||||||
|
if (channel.Name != ResistanceChannel)
|
||||||
|
Client.LocalUser.SendMessage(channel, "A The Resistance game was just created! If you'd like to play, join " + ResistanceChannel + " now!");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (action == "start")
|
||||||
|
{
|
||||||
|
if (Concilium.Data.Resistance == null)
|
||||||
|
{
|
||||||
|
Client.LocalUser.SendMessage(_sSource, "There's currently no running The Resistance game.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Concilium.Data.Resistance.StartGame(_sSource);
|
||||||
|
}
|
||||||
|
else if (action == "join")
|
||||||
|
{
|
||||||
|
if (Concilium.Data.Resistance == null)
|
||||||
|
{
|
||||||
|
Client.LocalUser.SendMessage(_sSource, "There's currently no running The Resistance game.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Concilium.Data.Resistance.JoinPlayer(_sSource);
|
||||||
|
}
|
||||||
|
else if (action == "status")
|
||||||
|
{
|
||||||
|
if (Concilium.Data.Resistance == null)
|
||||||
|
{
|
||||||
|
Client.LocalUser.SendMessage(_sSource, "There's currently no running The Resistance game.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Client.LocalUser.SendMessage(Concilium.GetDefaultReplyTarget(_sSource, _sTarget), Concilium.Data.Resistance.GetStatus());
|
||||||
|
}
|
||||||
|
else if (action == "agree")
|
||||||
|
{
|
||||||
|
if (Concilium.Data.Resistance == null)
|
||||||
|
{
|
||||||
|
Client.LocalUser.SendMessage(_sSource, "There's currently no running The Resistance game.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_sTarget == "Concilium")
|
||||||
|
Concilium.Data.Resistance.AgreeTeam(_sSource);
|
||||||
|
else
|
||||||
|
Client.LocalUser.SendMessage(ResistanceChannel, "Agree only via PM. " + _sSource + "'s command was " + (char)2 + "not" + (char)2 + "executed");
|
||||||
|
}
|
||||||
|
else if (action == "team")
|
||||||
|
{
|
||||||
|
if (Concilium.Data.Resistance == null)
|
||||||
|
{
|
||||||
|
Client.LocalUser.SendMessage(_sSource, "There's currently no running The Resistance game.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_sTarget == "Concilium")
|
||||||
|
Concilium.Data.Resistance.SetTeamMembers(_sSource, _parameters.Skip(1));
|
||||||
|
else
|
||||||
|
Client.LocalUser.SendMessage(ResistanceChannel, "Set up a team only via PM. " + _sSource + "'s command was " + (char)2 + "not" + (char)2 + "executed");
|
||||||
|
}
|
||||||
|
else if (action == "disagree")
|
||||||
|
{
|
||||||
|
if (Concilium.Data.Resistance == null)
|
||||||
|
{
|
||||||
|
Client.LocalUser.SendMessage(_sSource, "There's currently no running The Resistance game.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_sTarget == "Concilium")
|
||||||
|
Concilium.Data.Resistance.DisagreeTeam(_sSource);
|
||||||
|
else
|
||||||
|
Client.LocalUser.SendMessage(ResistanceChannel, "Disagree only via PM. " + _sSource + "'s command was " + (char)2 + "not" + (char)2 + "executed");
|
||||||
|
}
|
||||||
|
else if (action == "execute")
|
||||||
|
{
|
||||||
|
if (Concilium.Data.Resistance == null)
|
||||||
|
{
|
||||||
|
Client.LocalUser.SendMessage(_sSource, "There's currently no running The Resistance game.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_sTarget == "Concilium")
|
||||||
|
Concilium.Data.Resistance.ExecuteMission(_sSource);
|
||||||
|
else
|
||||||
|
Client.LocalUser.SendMessage(ResistanceChannel, "Execute mission only via PM. " + _sSource + "'s command was " + (char)2 + "not" + (char)2 + "executed");
|
||||||
|
}
|
||||||
|
else if (action == "sabotage")
|
||||||
|
{
|
||||||
|
if (Concilium.Data.Resistance == null)
|
||||||
|
{
|
||||||
|
Client.LocalUser.SendMessage(_sSource, "There's currently no running The Resistance game.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_sTarget == "Concilium")
|
||||||
|
Concilium.Data.Resistance.SabotageMission(_sSource);
|
||||||
|
else
|
||||||
|
Client.LocalUser.SendMessage(ResistanceChannel, "Sabotage mission only via PM. " + _sSource + "'s command was " + (char)2 + "not" + (char)2 + "executed");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
182
Concilium/Bot/Features/UserMonitorFeature.cs
Normal file
182
Concilium/Bot/Features/UserMonitorFeature.cs
Normal file
@@ -0,0 +1,182 @@
|
|||||||
|
using Concilium.Helpers;
|
||||||
|
using IrcDotNet;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading;
|
||||||
|
|
||||||
|
namespace Concilium.Bot.Features
|
||||||
|
{
|
||||||
|
[BotFeature(".lastjoin")]
|
||||||
|
[BotFeature(".lastpart")]
|
||||||
|
[BotFeature(".lastwrite")]
|
||||||
|
public class UserMonitorFeature : BotFeatureBase
|
||||||
|
{
|
||||||
|
public override void Load()
|
||||||
|
{
|
||||||
|
m_Timer = new Timer(UserMonitorTimerStart, this, 0, 1000);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void UserMonitorTimerStart(object state)
|
||||||
|
{
|
||||||
|
foreach (var channelUser in Concilium.Data.ChannelUsers)
|
||||||
|
{
|
||||||
|
var channelName = channelUser.Key;
|
||||||
|
var users = channelUser.Value.ToList();
|
||||||
|
IrcChannel channel;
|
||||||
|
|
||||||
|
if ((channel = Client.Channels.FirstOrDefault(c => c.Name == channelName)) != null)
|
||||||
|
{
|
||||||
|
foreach (var nickName in users)
|
||||||
|
{
|
||||||
|
if (!channel.Users.Any(u => u.User.NickName == nickName))
|
||||||
|
{
|
||||||
|
if (!Concilium.Data.Info.ContainsKey(nickName))
|
||||||
|
Concilium.Data.Info[nickName] = new UserInfo();
|
||||||
|
|
||||||
|
Concilium.Data.Info[nickName].LastLeft = DateTime.Now;
|
||||||
|
Log.Get().Info(string.Format("{0} just left {1}", nickName, channelName));
|
||||||
|
channelUser.Value.Remove(nickName);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach (var userNick in channel.Users)
|
||||||
|
{
|
||||||
|
if (!users.Any(u => u == userNick.User.NickName))
|
||||||
|
{
|
||||||
|
if (!Concilium.Data.Info.ContainsKey(userNick.User.NickName))
|
||||||
|
Concilium.Data.Info[userNick.User.NickName] = new UserInfo();
|
||||||
|
|
||||||
|
Concilium.Data.Info[userNick.User.NickName].LastJoined = DateTime.Now;
|
||||||
|
Log.Get().Info(string.Format("{0} just joined {1}", userNick, channelName));
|
||||||
|
channelUser.Value.Add(userNick.User.NickName);
|
||||||
|
userNick.User.PropertyChanged += (s, e) =>
|
||||||
|
{
|
||||||
|
if (e.PropertyName == "HostName")
|
||||||
|
{
|
||||||
|
OnJoin(userNick);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
userNick.User.WhoIs();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnJoin(IrcChannelUser userNick)
|
||||||
|
{
|
||||||
|
var whitelist = new string[]
|
||||||
|
{
|
||||||
|
"mirlix",
|
||||||
|
"xTr1m",
|
||||||
|
"BlueCobold",
|
||||||
|
"Daeva",
|
||||||
|
"dcu",
|
||||||
|
"eXpl0it3r",
|
||||||
|
"Lightkey",
|
||||||
|
"MasterQ32",
|
||||||
|
"Melan",
|
||||||
|
"Paprikachu",
|
||||||
|
"Socke",
|
||||||
|
"Sofa",
|
||||||
|
"Schorsch",
|
||||||
|
"Nimelrian",
|
||||||
|
"ompf",
|
||||||
|
"Yatekii",
|
||||||
|
"Marrrk",
|
||||||
|
"Marrrrk"
|
||||||
|
};
|
||||||
|
|
||||||
|
foreach (var nick in whitelist)
|
||||||
|
{
|
||||||
|
if (userNick.User.NickName.StartsWith(nick, StringComparison.InvariantCultureIgnoreCase) || userNick.User.NickName.EndsWith(nick, StringComparison.InvariantCultureIgnoreCase))
|
||||||
|
{
|
||||||
|
if (!userNick.Modes.Contains('v'))
|
||||||
|
{
|
||||||
|
userNick.Voice();
|
||||||
|
}
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Auto-kick:
|
||||||
|
//////////////////////////////////////////////////////////////////////
|
||||||
|
bool bBlackList = false;
|
||||||
|
|
||||||
|
// Kitty
|
||||||
|
bBlackList |= (userNick.User.NickName.ToLowerInvariant().Contains("kitty") || userNick.User.HostName.Contains("dyn.telefonica.de"));
|
||||||
|
|
||||||
|
if (bBlackList)
|
||||||
|
{
|
||||||
|
userNick.Kick("black listed");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void Execute(string _sCommand, string _sSource, string _sTarget, string _sMessage, IList<string> _parameters, string _ip)
|
||||||
|
{
|
||||||
|
if (_parameters.Count != 1)
|
||||||
|
throw new InvalidCommandParametersException(_sCommand, 1);
|
||||||
|
|
||||||
|
string sParameter = _parameters.First();
|
||||||
|
string sReply = null;
|
||||||
|
if (!Concilium.Data.Info.ContainsKey(sParameter))
|
||||||
|
{
|
||||||
|
sReply = string.Format("I have no information about {0} :(", sParameter);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (_sCommand == ".lastjoin")
|
||||||
|
sReply = ProcessChatLastJoin(_sSource, _sMessage, sParameter);
|
||||||
|
else if (_sCommand == ".lastpart")
|
||||||
|
sReply = ProcessChatLastPart(_sSource, _sMessage, sParameter);
|
||||||
|
else if (_sCommand == ".lastwrite")
|
||||||
|
sReply = ProcessChatLastWrite(_sSource, _sMessage, sParameter);
|
||||||
|
else
|
||||||
|
throw new NotImplementedException();
|
||||||
|
}
|
||||||
|
|
||||||
|
Client.LocalUser.SendMessage(Concilium.GetDefaultReplyTarget(_sSource, _sTarget), sReply);
|
||||||
|
}
|
||||||
|
|
||||||
|
private string ProcessChatLastJoin(string _sSource, string _sMessage, string _sParameter)
|
||||||
|
{
|
||||||
|
if (!Concilium.Data.Info[_sParameter].LastJoined.HasValue)
|
||||||
|
{
|
||||||
|
return string.Format("{0} joined before I did", _sParameter);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return string.Format("{0}'s last join date was: {1}", _sParameter, Concilium.Data.Info[_sParameter].LastJoined.Value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private string ProcessChatLastPart(string _sSource, string _sMessage, string _sParameter)
|
||||||
|
{
|
||||||
|
if (!Concilium.Data.Info[_sParameter].LastLeft.HasValue)
|
||||||
|
{
|
||||||
|
return string.Format("I didn't witness {0} leaving", _sParameter);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return string.Format("{0} left: {1}", _sParameter, Concilium.Data.Info[_sParameter].LastLeft.Value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private string ProcessChatLastWrite(string _sSource, string _sMessage, string _sParameter)
|
||||||
|
{
|
||||||
|
if (!Concilium.Data.Info[_sParameter].LastWritten.HasValue)
|
||||||
|
{
|
||||||
|
return string.Format("I've not seen any text from {0}", _sParameter);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return string.Format("{0}'s last message was on: {1}", _sParameter, Concilium.Data.Info[_sParameter].LastWritten.Value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private Timer m_Timer;
|
||||||
|
}
|
||||||
|
}
|
||||||
15
Concilium/Bot/IBotFeature.cs
Normal file
15
Concilium/Bot/IBotFeature.cs
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
using IrcDotNet;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
|
||||||
|
namespace Concilium.Bot
|
||||||
|
{
|
||||||
|
public interface IBotFeature
|
||||||
|
{
|
||||||
|
void Load();
|
||||||
|
void Execute(string _sCommand, string _sSource, string _sTarget, string _sMessage, IList<string> _parameters, string _ip);
|
||||||
|
IrcClient Client { get; set; }
|
||||||
|
}
|
||||||
|
}
|
||||||
56
Concilium/Bot/InvalidCommandParametersException.cs
Normal file
56
Concilium/Bot/InvalidCommandParametersException.cs
Normal file
@@ -0,0 +1,56 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading;
|
||||||
|
using log4net;
|
||||||
|
using Concilium.Helpers;
|
||||||
|
using System.Net;
|
||||||
|
using System.Diagnostics;
|
||||||
|
|
||||||
|
namespace Concilium.Bot
|
||||||
|
{
|
||||||
|
public class InvalidCommandParametersException : Exception
|
||||||
|
{
|
||||||
|
public InvalidCommandParametersException(string _sCommand, int minParameters, int? maxParameters = null)
|
||||||
|
: base()
|
||||||
|
{
|
||||||
|
m_sCommand = _sCommand;
|
||||||
|
|
||||||
|
Debug.Assert(minParameters >= 0,
|
||||||
|
"minParameters must be at least zero.");
|
||||||
|
Debug.Assert(maxParameters == null || maxParameters >= minParameters,
|
||||||
|
"maxParameters must be at least minParameters.");
|
||||||
|
|
||||||
|
this.MinParameters = minParameters;
|
||||||
|
this.MaxParameters = maxParameters ?? minParameters;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int MinParameters
|
||||||
|
{
|
||||||
|
get;
|
||||||
|
private set;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int MaxParameters
|
||||||
|
{
|
||||||
|
get;
|
||||||
|
private set;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override string Message
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
if (this.MinParameters == 0 && this.MaxParameters == 0)
|
||||||
|
return string.Format("Command {0} takes no parameters", m_sCommand);
|
||||||
|
else if (this.MinParameters == this.MaxParameters)
|
||||||
|
return string.Format("Command {0} takes {1} parameters", m_sCommand, this.MinParameters);
|
||||||
|
else
|
||||||
|
return string.Format("Command {0} takes {1} to {2} parameters", m_sCommand, this.MinParameters, this.MaxParameters);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private string m_sCommand;
|
||||||
|
}
|
||||||
|
}
|
||||||
393
Concilium/Bot/IrcBot.cs
Normal file
393
Concilium/Bot/IrcBot.cs
Normal file
@@ -0,0 +1,393 @@
|
|||||||
|
using Concilium.Helpers;
|
||||||
|
using IrcDotNet;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Collections.ObjectModel;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Text.RegularExpressions;
|
||||||
|
using System.Threading;
|
||||||
|
|
||||||
|
namespace Concilium.Bot
|
||||||
|
{
|
||||||
|
// Provides core functionality for an IRC bot that operates via multiple clients.
|
||||||
|
public abstract class IrcBot : IDisposable
|
||||||
|
{
|
||||||
|
private const int clientQuitTimeout = 1000;
|
||||||
|
|
||||||
|
// Dictionary of all chat command processors, keyed by name.
|
||||||
|
private IDictionary<string, ChatCommandProcessor> chatCommandProcessors;
|
||||||
|
|
||||||
|
// Dictionary of all command processors, keyed by name.
|
||||||
|
private IDictionary<string, CommandProcessor> commandProcessors;
|
||||||
|
|
||||||
|
// True if the read loop is currently active, false if ready to terminate.
|
||||||
|
private bool isRunning;
|
||||||
|
|
||||||
|
private bool isDisposed = false;
|
||||||
|
|
||||||
|
public IrcBot()
|
||||||
|
{
|
||||||
|
this.isRunning = false;
|
||||||
|
this.commandProcessors = new Dictionary<string, CommandProcessor>(StringComparer.InvariantCultureIgnoreCase);
|
||||||
|
InitializeCommandProcessors();
|
||||||
|
|
||||||
|
this.chatCommandProcessors = new Dictionary<string, ChatCommandProcessor>(StringComparer.InvariantCultureIgnoreCase);
|
||||||
|
InitializeChatCommandProcessors();
|
||||||
|
}
|
||||||
|
|
||||||
|
~IrcBot()
|
||||||
|
{
|
||||||
|
Dispose(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
public virtual string QuitMessage
|
||||||
|
{
|
||||||
|
get { return "Big brother isn't watching"; }
|
||||||
|
}
|
||||||
|
|
||||||
|
protected IDictionary<string, ChatCommandProcessor> ChatCommandProcessors
|
||||||
|
{
|
||||||
|
get { return this.chatCommandProcessors; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public StandardIrcClient Client
|
||||||
|
{
|
||||||
|
get;
|
||||||
|
private set;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected IDictionary<string, CommandProcessor> CommandProcessors
|
||||||
|
{
|
||||||
|
get { return this.commandProcessors; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Dispose()
|
||||||
|
{
|
||||||
|
Dispose(true);
|
||||||
|
GC.SuppressFinalize(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void Dispose(bool disposing)
|
||||||
|
{
|
||||||
|
if (!this.isDisposed)
|
||||||
|
{
|
||||||
|
if (disposing)
|
||||||
|
{
|
||||||
|
// Disconnect each client gracefully.
|
||||||
|
if (Client != null)
|
||||||
|
{
|
||||||
|
Client.Quit(clientQuitTimeout, this.QuitMessage);
|
||||||
|
Client.Dispose();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
this.isDisposed = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Run()
|
||||||
|
{
|
||||||
|
// Read commands from stdin until bot terminates.
|
||||||
|
this.isRunning = true;
|
||||||
|
while (this.isRunning)
|
||||||
|
{
|
||||||
|
Console.Write("> ");
|
||||||
|
var line = Console.ReadLine();
|
||||||
|
if (line == null)
|
||||||
|
break;
|
||||||
|
if (line.Length == 0)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
var parts = line.Split(' ');
|
||||||
|
var command = parts[0].ToLower();
|
||||||
|
var parameters = parts.Skip(1).ToArray();
|
||||||
|
ReadCommand(command, parameters);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Stop()
|
||||||
|
{
|
||||||
|
this.isRunning = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected abstract void InitializeCommandProcessors();
|
||||||
|
|
||||||
|
private void ReadCommand(string command, IList<string> parameters)
|
||||||
|
{
|
||||||
|
CommandProcessor processor;
|
||||||
|
if (this.commandProcessors.TryGetValue(command, out processor))
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
processor(command, parameters);
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
Log.Get().Error(string.Format("Error: {0}", ex.Message));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Log.Get().Error(string.Format("Command '{0}' not recognized.", command));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void Connect()
|
||||||
|
{
|
||||||
|
var registrationInfo = new IrcUserRegistrationInfo()
|
||||||
|
{
|
||||||
|
UserName = "Concilium",
|
||||||
|
NickName = "Concilium",
|
||||||
|
Password = "K3kst0ru5",
|
||||||
|
RealName = "#sppro knowledge bot"
|
||||||
|
};
|
||||||
|
|
||||||
|
// Create new IRC client and connect to given server.
|
||||||
|
Client = new StandardIrcClient();
|
||||||
|
Client.FloodPreventer = new IrcStandardFloodPreventer(4, 2000);
|
||||||
|
Client.Connected += IrcClient_Connected;
|
||||||
|
Client.Disconnected += IrcClient_Disconnected;
|
||||||
|
Client.Registered += IrcClient_Registered;
|
||||||
|
Client.RawMessageReceived += IrcClient_RawMessageReceived;
|
||||||
|
|
||||||
|
// Wait until connection has succeeded or timed out.
|
||||||
|
using (var connectedEvent = new ManualResetEventSlim(false))
|
||||||
|
{
|
||||||
|
Client.Connected += (sender2, e2) => connectedEvent.Set();
|
||||||
|
Client.Connect("irc.euirc.net", 6665, false, registrationInfo);
|
||||||
|
if (!connectedEvent.Wait(10000))
|
||||||
|
{
|
||||||
|
Client.Dispose();
|
||||||
|
Log.Get().Error("Connection timed out");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Log.Get().Info("Now connected");
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Disconnect()
|
||||||
|
{
|
||||||
|
// Disconnect IRC client that is connected to given server.
|
||||||
|
Client.Quit(clientQuitTimeout, this.QuitMessage);
|
||||||
|
Client.Dispose();
|
||||||
|
|
||||||
|
// Remove client from connection.
|
||||||
|
Client = null;
|
||||||
|
|
||||||
|
Log.Get().Info("Disconnected");
|
||||||
|
}
|
||||||
|
|
||||||
|
protected abstract void InitializeChatCommandProcessors();
|
||||||
|
|
||||||
|
private bool ReadChatCommand(IrcClient client, IrcMessageEventArgs eventArgs)
|
||||||
|
{
|
||||||
|
// Check if given message represents chat command.
|
||||||
|
var line = eventArgs.Text;
|
||||||
|
if (line.Length > 1 && line.StartsWith(".") || line.StartsWith(">"))
|
||||||
|
{
|
||||||
|
// Process command.
|
||||||
|
var parts = line.Split(' ');
|
||||||
|
var command = parts.First();
|
||||||
|
var parameters = parts.Skip(1).ToArray();
|
||||||
|
ReadChatCommand(client, eventArgs.Source, eventArgs.Targets, command, parameters);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void ReadChatCommand(IrcClient client, IIrcMessageSource source, IList<IIrcMessageTarget> targets, string command, string[] parameters)
|
||||||
|
{
|
||||||
|
var defaultReplyTargets = GetDefaultReplyTargets(client, source, targets);
|
||||||
|
|
||||||
|
ChatCommandProcessor processor;
|
||||||
|
if (this.chatCommandProcessors.TryGetValue(command, out processor))
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
processor(client, source, targets, command, parameters);
|
||||||
|
}
|
||||||
|
catch (InvalidCommandParametersException exInvalidCommandParameters)
|
||||||
|
{
|
||||||
|
client.LocalUser.SendNotice(defaultReplyTargets, exInvalidCommandParameters.Message);
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
if (source is IIrcMessageTarget)
|
||||||
|
{
|
||||||
|
client.LocalUser.SendNotice(defaultReplyTargets, string.Format("Error processing '{0}' command: {1}", command, ex.Message));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (source is IIrcMessageTarget)
|
||||||
|
{
|
||||||
|
client.LocalUser.SendNotice(defaultReplyTargets, string.Format("Command '{0}' not recognized.", command));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected virtual void OnRawMessageReceived(IrcClient client, IrcRawMessageEventArgs e) { }
|
||||||
|
|
||||||
|
protected virtual void OnClientConnect(IrcClient client) { }
|
||||||
|
|
||||||
|
protected virtual void OnClientDisconnect(IrcClient client) { }
|
||||||
|
|
||||||
|
protected virtual void OnClientRegistered(IrcClient client) { }
|
||||||
|
|
||||||
|
protected virtual void OnLocalUserJoinedChannel(IrcLocalUser localUser, IrcChannelEventArgs e) { }
|
||||||
|
|
||||||
|
protected virtual void OnLocalUserLeftChannel(IrcLocalUser localUser, IrcChannelEventArgs e) { }
|
||||||
|
|
||||||
|
protected virtual void OnLocalUserNoticeReceived(IrcLocalUser localUser, IrcMessageEventArgs e) { }
|
||||||
|
|
||||||
|
protected virtual void OnLocalUserMessageReceived(IrcLocalUser localUser, IrcMessageEventArgs e) { }
|
||||||
|
|
||||||
|
protected virtual void OnChannelUserJoined(IrcChannel channel, IrcChannelUserEventArgs e) { }
|
||||||
|
|
||||||
|
protected virtual void OnChannelUserLeft(IrcChannel channel, IrcChannelUserEventArgs e) { }
|
||||||
|
|
||||||
|
protected virtual void OnChannelNoticeReceived(IrcChannel channel, IrcMessageEventArgs e) { }
|
||||||
|
|
||||||
|
protected virtual void OnChannelMessageReceived(IrcChannel channel, IrcMessageEventArgs e) { }
|
||||||
|
|
||||||
|
#region IRC Client Event Handlers
|
||||||
|
|
||||||
|
private void IrcClient_Connected(object sender, EventArgs e)
|
||||||
|
{
|
||||||
|
var client = (IrcClient)sender;
|
||||||
|
|
||||||
|
OnClientConnect(client);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void IrcClient_Disconnected(object sender, EventArgs e)
|
||||||
|
{
|
||||||
|
var client = (IrcClient)sender;
|
||||||
|
|
||||||
|
OnClientDisconnect(client);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void IrcClient_Registered(object sender, EventArgs e)
|
||||||
|
{
|
||||||
|
var client = (IrcClient)sender;
|
||||||
|
|
||||||
|
client.LocalUser.NoticeReceived += IrcClient_LocalUser_NoticeReceived;
|
||||||
|
client.LocalUser.MessageReceived += IrcClient_LocalUser_MessageReceived;
|
||||||
|
client.LocalUser.JoinedChannel += IrcClient_LocalUser_JoinedChannel;
|
||||||
|
client.LocalUser.LeftChannel += IrcClient_LocalUser_LeftChannel;
|
||||||
|
|
||||||
|
OnClientRegistered(client);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void IrcClient_LocalUser_NoticeReceived(object sender, IrcMessageEventArgs e)
|
||||||
|
{
|
||||||
|
var localUser = (IrcLocalUser)sender;
|
||||||
|
|
||||||
|
OnLocalUserNoticeReceived(localUser, e);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void IrcClient_LocalUser_MessageReceived(object sender, IrcMessageEventArgs e)
|
||||||
|
{
|
||||||
|
var localUser = (IrcLocalUser)sender;
|
||||||
|
|
||||||
|
if (e.Source is IrcUser)
|
||||||
|
{
|
||||||
|
// Read message and process if it is chat command.
|
||||||
|
if (ReadChatCommand(localUser.Client, e))
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
OnLocalUserMessageReceived(localUser, e);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void IrcClient_LocalUser_JoinedChannel(object sender, IrcChannelEventArgs e)
|
||||||
|
{
|
||||||
|
var localUser = (IrcLocalUser)sender;
|
||||||
|
|
||||||
|
e.Channel.UserJoined += IrcClient_Channel_UserJoined;
|
||||||
|
e.Channel.UserLeft += IrcClient_Channel_UserLeft;
|
||||||
|
e.Channel.MessageReceived += IrcClient_Channel_MessageReceived;
|
||||||
|
e.Channel.NoticeReceived += IrcClient_Channel_NoticeReceived;
|
||||||
|
|
||||||
|
OnLocalUserJoinedChannel(localUser, e);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void IrcClient_LocalUser_LeftChannel(object sender, IrcChannelEventArgs e)
|
||||||
|
{
|
||||||
|
var localUser = (IrcLocalUser)sender;
|
||||||
|
|
||||||
|
e.Channel.UserJoined -= IrcClient_Channel_UserJoined;
|
||||||
|
e.Channel.UserLeft -= IrcClient_Channel_UserLeft;
|
||||||
|
e.Channel.MessageReceived -= IrcClient_Channel_MessageReceived;
|
||||||
|
e.Channel.NoticeReceived -= IrcClient_Channel_NoticeReceived;
|
||||||
|
|
||||||
|
OnLocalUserJoinedChannel(localUser, e);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void IrcClient_RawMessageReceived(object sender, IrcRawMessageEventArgs e)
|
||||||
|
{
|
||||||
|
var client = (IrcClient)sender;
|
||||||
|
|
||||||
|
OnRawMessageReceived(client, e);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void IrcClient_Channel_UserLeft(object sender, IrcChannelUserEventArgs e)
|
||||||
|
{
|
||||||
|
var channel = (IrcChannel)sender;
|
||||||
|
|
||||||
|
OnChannelUserJoined(channel, e);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void IrcClient_Channel_UserJoined(object sender, IrcChannelUserEventArgs e)
|
||||||
|
{
|
||||||
|
var channel = (IrcChannel)sender;
|
||||||
|
|
||||||
|
OnChannelUserLeft(channel, e);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void IrcClient_Channel_NoticeReceived(object sender, IrcMessageEventArgs e)
|
||||||
|
{
|
||||||
|
var channel = (IrcChannel)sender;
|
||||||
|
|
||||||
|
OnChannelNoticeReceived(channel, e);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void IrcClient_Channel_MessageReceived(object sender, IrcMessageEventArgs e)
|
||||||
|
{
|
||||||
|
var channel = (IrcChannel)sender;
|
||||||
|
|
||||||
|
if (e.Source is IrcUser)
|
||||||
|
{
|
||||||
|
// Read message and process if it is chat command.
|
||||||
|
if (ReadChatCommand(channel.Client, e))
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
OnChannelMessageReceived(channel, e);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
public static IList<IIrcMessageTarget> GetDefaultReplyTargets(IrcClient client, IIrcMessageSource source, IList<IIrcMessageTarget> targets)
|
||||||
|
{
|
||||||
|
if (targets.Contains(client.LocalUser) && source is IIrcMessageTarget)
|
||||||
|
return new[] { (IIrcMessageTarget)source };
|
||||||
|
else
|
||||||
|
return targets;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static string GetDefaultReplyTarget(string _sSource, string _sTarget)
|
||||||
|
{
|
||||||
|
if (_sTarget == "Concilium")
|
||||||
|
return _sSource;
|
||||||
|
else
|
||||||
|
return _sTarget;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected delegate void ChatCommandProcessor(IrcClient client, IIrcMessageSource source, IList<IIrcMessageTarget> targets, string command, IList<string> parameters);
|
||||||
|
|
||||||
|
protected delegate void CommandProcessor(string command, IList<string> parameters);
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
26
Concilium/Bot/IrcClientExtensions.cs
Normal file
26
Concilium/Bot/IrcClientExtensions.cs
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
using IrcDotNet;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
|
||||||
|
namespace Concilium.Bot
|
||||||
|
{
|
||||||
|
public static class IrcClientExtensions
|
||||||
|
{
|
||||||
|
public static IrcChannel GetChannel(this IrcClient _client, string _sChannelName)
|
||||||
|
{
|
||||||
|
return _client.Channels.FirstOrDefault(c => c.Name == _sChannelName);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static IrcUser GetUser(this IrcClient _client, string _sNickName)
|
||||||
|
{
|
||||||
|
return _client.Users.FirstOrDefault(u => u.NickName == _sNickName);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static IrcChannelUser GetUser(this IrcChannel _channel, string _sNickName)
|
||||||
|
{
|
||||||
|
return _channel.Users.FirstOrDefault(u => u.User.NickName == _sNickName);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
631
Concilium/Bot/Mafia.cs
Normal file
631
Concilium/Bot/Mafia.cs
Normal file
@@ -0,0 +1,631 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using Concilium.Helpers;
|
||||||
|
|
||||||
|
namespace Concilium.Bot
|
||||||
|
{
|
||||||
|
public class Mafia
|
||||||
|
{
|
||||||
|
private static class Strings
|
||||||
|
{
|
||||||
|
public static string Welcome = "A new mafia game was started by {0}!";
|
||||||
|
public static string TooFewPlayers = "There are still too few players. At least 5 players are required.";
|
||||||
|
public static string PlayingMafioso = "Both you and {0} are playing as a mafiosos. Your job is to take over the city by ensuring that in the end the mafiosos outnumber the civilists. Kill one civilist every night.";
|
||||||
|
public static string PlayingCivilist = "You're playing as a civilist. Your job is to try to discover the mafiosos infiltrating your city. Do a public voting each day on who should be killed. Kill all mafiosos and you win.";
|
||||||
|
public static string PlayingDoctor = "You're playing as a doctor. Your job is to guard a civilist each night to prevent his/her death, should he become a target from the mafiosos infiltrating your city. You also count as a civilist, do a public voting each day on who should be killed. Kill all mafiosos and you win.";
|
||||||
|
public static string PlayingDetective = "You're playing as a detective. Your job is to try each night to discover one of the mafiosos infiltrating your city. You also count as a civilist, do a public voting each day on who should be killed. Kill all mafiosos and you win.";
|
||||||
|
public static string PlayingVigilante = "You're playing as a vigilante. Your job is to try to discover the mafiosos infiltrating your city. Do a public voting each day on who should be killed. At night you can kill any player at will. Kill all mafiosos and you win.";
|
||||||
|
public static string HelpNightMafioso = "You're a mafioso and it's night. Discuss with the mafia and agree on one target. Vote for that target by querying " + (char)2 + ".mafia vote %nickName%" + (char)2 + " now.";
|
||||||
|
public static string HelpNightCivilist = "You're civilist and it's night. Go to bed and relax.";
|
||||||
|
public static string HelpNightDoctor = "You're a doctor and it's night. Your job is to guard and save a civilist now, do that by querying " + (char)2 + ".mafia save %nickName%" + (char)2 + " now.";
|
||||||
|
public static string HelpNightDetective = "You're a detective and it's night. Your job is to detect whether a player is a mafioso. Do that by querying " + (char)2 + ".mafia detect %nickName%" + (char)2 + " now.";
|
||||||
|
public static string HelpNightVigilante = "You're a vigilante and it's night. Your job is to kill all mafia players. Kill your suspect by querying " + (char)2 + ".mafia kill %nickName%" + (char)2 + " now.";
|
||||||
|
public static string UserJoined = "{0} joined the mafia game!";
|
||||||
|
public static string UserCantJoin = "I'm sorry, {0}. You can't join the current mafia game, since it already started.";
|
||||||
|
public static string UserDuplicate = "You already joined the mafia game!";
|
||||||
|
public static string GameBegins = "All necessary players joined! Let the game begin!";
|
||||||
|
public static string DayBegins = "The sun comes out, it's day. Everybody wakes up.";
|
||||||
|
public static string[] Deaths = new string[]
|
||||||
|
{
|
||||||
|
"This morning, the police found the body of {0} floating in the river. The chest had wounds from bullet impacts.",
|
||||||
|
"After the neighbours alarmed the police, {0} was found dead at home. Experts believe that he was poisoned while consuming breakfast.",
|
||||||
|
"The neighbourhood was scared this morning, when the car of {0} suddenly exploded. When the firemen arrived, the corpse was already carbonized.",
|
||||||
|
"A citizen called the police this morning, indicating that he found the head of {0}, cut off, in his trash bin. There is no trace from the rest of the body."
|
||||||
|
};
|
||||||
|
public static string VoteStatus = "The citizens currently vote for killing: ";
|
||||||
|
public static string DeathRole = "Upon closer inspection of the crime scene, the police could discover from the surrounding belongings that the victim was a " + (char)2 + "{0}" + (char)2 + ".";
|
||||||
|
public static string LynchRole = "Upon closer inspection of the dead body, the citizens discover from the belongings that the victim was a " + (char)2 + "{0}" + (char)2 + ".";
|
||||||
|
public static string NoDeathsOvernight = "This night was calm, that's a relief for the city. No player died.";
|
||||||
|
public static string DayPreparation = "Each player must now vote who they think is a mafioso and should be killed. Just write via query " + (char)2 + ".mafia vote %nickName%" + (char)2 + " to vote.";
|
||||||
|
public static string CantVote = "You can't vote at this time.";
|
||||||
|
public static string CantUnvote = "You can't unvote at this time.";
|
||||||
|
public static string InvalidVote = "I don't know who you mean. Please choose one from: ";
|
||||||
|
public static string SelfVote = "You can't vote for youself!";
|
||||||
|
public static string FirstVote = "{0} thinks that {1} should be killed.";
|
||||||
|
public static string Unvote = "{0} is not so sure anymore and removes his/her vote.";
|
||||||
|
public static string NextVote = "{0} changed his/her mind and proposes {1} to be killed.";
|
||||||
|
public static string DayEnds = "As the day reaches its end and the sun sets, all players assemble in the execution place.";
|
||||||
|
public static string LynchPlayer = "Agreed upon by public voting, {0} is pushed forward, and a rope is tied around the neck. Finally what remains is the lifeless look of {0}'s half-opened eyes.";
|
||||||
|
public static string NightBegins = "The stars begin to shine, the city is quiet. It is now nighttime. All mafiosos will now meet in secret and agree on their victim.";
|
||||||
|
public static string DetectiveIntro = "The detective might now be able to catch a mafioso on its way to their meeting place. Just write in a query " + (char)2 + ".mafia detect %nickName%" + (char)2 + " to check.";
|
||||||
|
public static string DetectiveNotNight = "It's not night yet. You can only operate when the streets are dark.";
|
||||||
|
public static string DetectiveAlreadyDone = "You've already done your job this night! You found out that {0} is{1} a mafioso.";
|
||||||
|
public static string DetectiveFinished = "During your inspection this night you conclude that {0} is{1} a mafioso.";
|
||||||
|
public static string DoctorIntro = "The doctor can now decide which player should be cured, for the case that this player will be a target of a mafioso attack. Just write in a query " + (char)2 + ".mafia save %nickName%" + (char)2 + " to save that player from a possible death.";
|
||||||
|
public static string DoctorNotNight = "It's not night yet. The mafia only operates at night, and then it's where you should choose whom to guard.";
|
||||||
|
public static string DoctorFinished = "OK, {0} will definitely survive this night.";
|
||||||
|
public static string VigilanteNotNight = "It's not night yet. You should only do your killing at night.";
|
||||||
|
public static string VigilanteFinished = "OK, you're about to kill {0} tonight.";
|
||||||
|
public static string MafiosoIntro = "Each mafioso must now vote who they want to kill. All votes must target the same player. Just write in a query " + (char)2 + ".mafia vote %nickName%" + (char)2 + " to vote.";
|
||||||
|
public static string NightEnds = "The stars start to fade. Slowly the sky turns into shades of blue.";
|
||||||
|
public static string CivilistsWin = "All mafiosos were killed! Civilists win this game!";
|
||||||
|
public static string MafiososWin = "The mafiosos managed to take over the city! They outnumber the citizens and therefore win this game!";
|
||||||
|
public static string HallOfFame = "Following players participated: ";
|
||||||
|
}
|
||||||
|
|
||||||
|
public enum State
|
||||||
|
{
|
||||||
|
Lobby,
|
||||||
|
Day,
|
||||||
|
Night
|
||||||
|
};
|
||||||
|
|
||||||
|
public enum Role
|
||||||
|
{
|
||||||
|
Unassigned,
|
||||||
|
Civilist,
|
||||||
|
Mafioso,
|
||||||
|
Detective,
|
||||||
|
Doctor,
|
||||||
|
Avenger,
|
||||||
|
Vigilante
|
||||||
|
};
|
||||||
|
|
||||||
|
public delegate void DummyHandler();
|
||||||
|
public event DummyHandler GameOver;
|
||||||
|
private void SendGameOver()
|
||||||
|
{
|
||||||
|
if (GameOver != null)
|
||||||
|
GameOver();
|
||||||
|
}
|
||||||
|
public event DummyHandler DayBegins;
|
||||||
|
private void SendDayBegins()
|
||||||
|
{
|
||||||
|
if (DayBegins != null)
|
||||||
|
DayBegins();
|
||||||
|
}
|
||||||
|
public event DummyHandler NightBegins;
|
||||||
|
private void SendNightBegins()
|
||||||
|
{
|
||||||
|
if (NightBegins != null)
|
||||||
|
NightBegins();
|
||||||
|
}
|
||||||
|
|
||||||
|
public delegate void LobbyNoticeHandler(string notice);
|
||||||
|
public event LobbyNoticeHandler OnLobbyNotice;
|
||||||
|
private void SendLobbyNotice(string notice)
|
||||||
|
{
|
||||||
|
if (OnLobbyNotice != null)
|
||||||
|
OnLobbyNotice(notice);
|
||||||
|
}
|
||||||
|
|
||||||
|
public delegate void UsersNoticeHandler(IEnumerable<string> users, string notice);
|
||||||
|
public event UsersNoticeHandler OnUsersNotice;
|
||||||
|
private void SendUsersNotice(IEnumerable<string> users, string notice)
|
||||||
|
{
|
||||||
|
if (OnUsersNotice != null && users.Count() > 0)
|
||||||
|
OnUsersNotice(users, notice);
|
||||||
|
}
|
||||||
|
|
||||||
|
public delegate void UserEventHandler(string nickName);
|
||||||
|
public event UserEventHandler OnUserJoined;
|
||||||
|
private void SendUserJoined(string nickName)
|
||||||
|
{
|
||||||
|
if (OnUserJoined != null)
|
||||||
|
OnUserJoined(nickName);
|
||||||
|
}
|
||||||
|
public event UserEventHandler OnUserDied;
|
||||||
|
private void SendUserDied(string nickName)
|
||||||
|
{
|
||||||
|
if (OnUserDied != null)
|
||||||
|
OnUserDied(nickName);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Mafia()
|
||||||
|
{
|
||||||
|
this.CurrentState = State.Lobby;
|
||||||
|
this.FirstDay = true;
|
||||||
|
this.NumPlayers = -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Init(string nickName)
|
||||||
|
{
|
||||||
|
this.GameCreator = nickName;
|
||||||
|
SendLobbyNotice(string.Format(Strings.Welcome, this.GameCreator));
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool StartGame(string nickName)
|
||||||
|
{
|
||||||
|
if (CurrentState != State.Lobby)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (GameCreator != nickName)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (allPlayers.Count < 5)
|
||||||
|
{
|
||||||
|
SendLobbyNotice(string.Format(Strings.TooFewPlayers, nickName));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.NumPlayers = allPlayers.Count;
|
||||||
|
CheckState();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool JoinPlayer(string nickName)
|
||||||
|
{
|
||||||
|
if (CurrentState != State.Lobby)
|
||||||
|
{
|
||||||
|
SendUsersNotice(new List<string> { nickName }, string.Format(Strings.UserCantJoin, nickName));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (allPlayers.ContainsKey(nickName))
|
||||||
|
{
|
||||||
|
SendUsersNotice(new List<string> { nickName }, Strings.UserDuplicate);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
allPlayers[nickName] = Role.Unassigned;
|
||||||
|
SendLobbyNotice(string.Format(Strings.UserJoined, nickName));
|
||||||
|
OnUserJoined(nickName);
|
||||||
|
CheckState();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void CheckState()
|
||||||
|
{
|
||||||
|
if (string.IsNullOrEmpty(GameCreator))
|
||||||
|
return;
|
||||||
|
|
||||||
|
switch (CurrentState)
|
||||||
|
{
|
||||||
|
case State.Lobby:
|
||||||
|
if (allPlayers.Count == NumPlayers)
|
||||||
|
{
|
||||||
|
SendLobbyNotice(Strings.GameBegins);
|
||||||
|
|
||||||
|
var specialRoles = new List<Role>() { Role.Doctor, Role.Detective, Role.Vigilante };
|
||||||
|
specialRoles.Shuffle();
|
||||||
|
|
||||||
|
// Assign roles
|
||||||
|
var players = new List<string>(allPlayers.Keys);
|
||||||
|
players.Shuffle();
|
||||||
|
allPlayers[players[0]] = Role.Mafioso;
|
||||||
|
SendUsersNotice(new List<string>() { players[0] }, string.Format(Strings.PlayingMafioso, players[1]));
|
||||||
|
allPlayers[players[1]] = Role.Mafioso;
|
||||||
|
SendUsersNotice(new List<string>() { players[1] }, string.Format(Strings.PlayingMafioso, players[0]));
|
||||||
|
allPlayers[players[2]] = specialRoles.First(); specialRoles.RemoveAt(0);
|
||||||
|
allPlayers[players[3]] = specialRoles.First(); specialRoles.RemoveAt(0);
|
||||||
|
foreach (var remainingPlayer in allPlayers.Where(p => p.Value == Role.Unassigned).ToList())
|
||||||
|
allPlayers[remainingPlayer.Key] = Role.Civilist;
|
||||||
|
|
||||||
|
SendUsersNotice(allPlayers.Where(p => p.Value == Role.Civilist).Select(p => p.Key), Strings.PlayingCivilist);
|
||||||
|
foreach (var playerEntry in allPlayers)
|
||||||
|
{
|
||||||
|
if (playerEntry.Value == Role.Detective)
|
||||||
|
SendUsersNotice(new List<string>() { playerEntry.Key }, Strings.PlayingDetective);
|
||||||
|
else if (playerEntry.Value == Role.Doctor)
|
||||||
|
SendUsersNotice(new List<string>() { playerEntry.Key }, Strings.PlayingDoctor);
|
||||||
|
else if (playerEntry.Value == Role.Vigilante)
|
||||||
|
SendUsersNotice(new List<string>() { playerEntry.Key }, Strings.PlayingVigilante);
|
||||||
|
}
|
||||||
|
GenerateHallOfFame();
|
||||||
|
BeginDay();
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case State.Day:
|
||||||
|
if (PlayerVotes.Count == allPlayers.Count)
|
||||||
|
{
|
||||||
|
SendLobbyNotice(Strings.DayEnds);
|
||||||
|
var dict = new Dictionary<string, int>();
|
||||||
|
foreach (var vote in PlayerVotes)
|
||||||
|
{
|
||||||
|
if (!dict.ContainsKey(vote.Value))
|
||||||
|
dict[vote.Value] = 0;
|
||||||
|
|
||||||
|
dict[vote.Value] = dict[vote.Value] + 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
var maxVotes = dict.Max(d => d.Value);
|
||||||
|
var candidates = dict.Where(d => d.Value == maxVotes).Select(d => d.Key).ToArray();
|
||||||
|
var rand = new Random();
|
||||||
|
var candidate = candidates[rand.Next(candidates.Length)];
|
||||||
|
var role = allPlayers[candidate];
|
||||||
|
allPlayers.Remove(candidate);
|
||||||
|
OnUserDied(candidate);
|
||||||
|
SendLobbyNotice(string.Format(Strings.LynchPlayer, candidate));
|
||||||
|
SendLobbyNotice(string.Format(Strings.LynchRole, role.ToString()));
|
||||||
|
BeginNight();
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case State.Night:
|
||||||
|
if (PlayerVotes.Count == GetMafiosos().Count() && PlayerVotes.All(v => v.Value == PlayerVotes.First().Value) && (GetDoctor() == null || DoctorSave != null) && (GetVigilante() == null || VigilanteKill != null) && (GetDetective() == null || DetectiveTarget != null))
|
||||||
|
{
|
||||||
|
MafiosoKill = PlayerVotes.First().Value;
|
||||||
|
SendLobbyNotice(Strings.NightEnds);
|
||||||
|
BeginDay();
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
throw new NotImplementedException("BUG! Implementation incomplete, an internal state was not handled");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void GenerateHallOfFame()
|
||||||
|
{
|
||||||
|
hallOfFame = Strings.HallOfFame + string.Join(", ", allPlayers.Select(p => p.Key + " (" + p.Value.ToString() + ")"));
|
||||||
|
}
|
||||||
|
|
||||||
|
private void BeginDay()
|
||||||
|
{
|
||||||
|
if (CurrentState == State.Day)
|
||||||
|
throw new InvalidOperationException("BUG! Day can't begin when it's already day!");
|
||||||
|
|
||||||
|
CurrentState = State.Day;
|
||||||
|
SendLobbyNotice(Strings.DayBegins);
|
||||||
|
PlayerVotes.Clear();
|
||||||
|
|
||||||
|
if (!FirstDay)
|
||||||
|
{
|
||||||
|
var deaths = Strings.Deaths.ToList();
|
||||||
|
deaths.Shuffle();
|
||||||
|
var deathCount = 0;
|
||||||
|
|
||||||
|
if (MafiosoKill != null && MafiosoKill != DoctorSave)
|
||||||
|
{
|
||||||
|
var role = allPlayers[MafiosoKill];
|
||||||
|
allPlayers.Remove(MafiosoKill);
|
||||||
|
OnUserDied(MafiosoKill);
|
||||||
|
var death = deaths[deathCount++];
|
||||||
|
SendLobbyNotice(string.Format(death, MafiosoKill));
|
||||||
|
SendLobbyNotice(string.Format(Strings.DeathRole, role.ToString()));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (VigilanteKill != null && VigilanteKill != DoctorSave)
|
||||||
|
{
|
||||||
|
var role = allPlayers[VigilanteKill];
|
||||||
|
allPlayers.Remove(VigilanteKill);
|
||||||
|
OnUserDied(VigilanteKill);
|
||||||
|
var death = deaths[deathCount++];
|
||||||
|
SendLobbyNotice(string.Format(death, VigilanteKill));
|
||||||
|
SendLobbyNotice(string.Format(Strings.DeathRole, role.ToString()));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (deathCount == 0)
|
||||||
|
{
|
||||||
|
SendLobbyNotice(Strings.NoDeathsOvernight);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
FirstDay = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (GetMafiosos().Count() == 0)
|
||||||
|
{
|
||||||
|
SendLobbyNotice(Strings.CivilistsWin);
|
||||||
|
SendLobbyNotice(hallOfFame);
|
||||||
|
SendGameOver();
|
||||||
|
}
|
||||||
|
else if (GetMafiosos().Count() > GetAllPlayers().Count() - GetMafiosos().Count())
|
||||||
|
{
|
||||||
|
SendLobbyNotice(Strings.MafiososWin);
|
||||||
|
SendLobbyNotice(hallOfFame);
|
||||||
|
SendGameOver();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
SendLobbyNotice(Strings.DayPreparation);
|
||||||
|
SendDayBegins();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void BeginNight()
|
||||||
|
{
|
||||||
|
if (CurrentState == State.Night)
|
||||||
|
throw new InvalidOperationException("BUG! Night can't begin when it's already night!");
|
||||||
|
|
||||||
|
foreach (var playerEntry in allPlayers)
|
||||||
|
{
|
||||||
|
switch (playerEntry.Value)
|
||||||
|
{
|
||||||
|
case Role.Civilist: SendUsersNotice(new List<string>() { playerEntry.Key }, Strings.HelpNightCivilist); break;
|
||||||
|
case Role.Mafioso: SendUsersNotice(new List<string>() { playerEntry.Key }, Strings.HelpNightMafioso); break;
|
||||||
|
case Role.Doctor: SendUsersNotice(new List<string>() { playerEntry.Key }, Strings.HelpNightDoctor); break;
|
||||||
|
case Role.Detective: SendUsersNotice(new List<string>() { playerEntry.Key }, Strings.HelpNightDetective); break;
|
||||||
|
case Role.Vigilante: SendUsersNotice(new List<string>() { playerEntry.Key }, Strings.HelpNightVigilante); break;
|
||||||
|
default: break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
if (GetMafiosos().Count() == 0)
|
||||||
|
{
|
||||||
|
SendLobbyNotice(Strings.CivilistsWin);
|
||||||
|
SendLobbyNotice(hallOfFame);
|
||||||
|
SendGameOver();
|
||||||
|
}
|
||||||
|
else if (GetMafiosos().Count() > GetAllPlayers().Count() - GetMafiosos().Count())
|
||||||
|
{
|
||||||
|
SendLobbyNotice(Strings.MafiososWin);
|
||||||
|
SendLobbyNotice(hallOfFame);
|
||||||
|
SendGameOver();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
SendLobbyNotice(Strings.NightBegins);
|
||||||
|
CurrentState = State.Night;
|
||||||
|
PlayerVotes.Clear();
|
||||||
|
DetectiveTarget = null;
|
||||||
|
SendNightBegins();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool Unvote(string nickName)
|
||||||
|
{
|
||||||
|
if (!allPlayers.ContainsKey(nickName))
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (CurrentState == State.Day)
|
||||||
|
{
|
||||||
|
if (PlayerVotes.ContainsKey(nickName))
|
||||||
|
{
|
||||||
|
SendLobbyNotice(string.Format(Strings.Unvote, nickName));
|
||||||
|
|
||||||
|
PlayerVotes.Remove(nickName);
|
||||||
|
CheckState();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (CurrentState == State.Night)
|
||||||
|
{
|
||||||
|
if (!GetMafiosos().Contains(nickName))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
var recipients = GetMafiosos().Where(p => p != nickName);
|
||||||
|
if (PlayerVotes.ContainsKey(nickName))
|
||||||
|
{
|
||||||
|
SendUsersNotice(recipients, string.Format(Strings.Unvote, nickName));
|
||||||
|
PlayerVotes.Remove(nickName);
|
||||||
|
CheckState();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
SendUsersNotice(new List<string> { nickName }, Strings.CantUnvote);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool PlayerVote(string nickName, string vote)
|
||||||
|
{
|
||||||
|
if (!allPlayers.ContainsKey(vote))
|
||||||
|
{
|
||||||
|
var message = Strings.InvalidVote + string.Join(", ", GetAllPlayers().Where(p => p != nickName));
|
||||||
|
SendUsersNotice(new List<string> { nickName }, message);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!allPlayers.ContainsKey(nickName))
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (nickName == vote)
|
||||||
|
{
|
||||||
|
SendUsersNotice(new List<string> { nickName }, Strings.SelfVote);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (CurrentState == State.Day)
|
||||||
|
{
|
||||||
|
if (PlayerVotes.ContainsKey(nickName) && PlayerVotes[nickName] != vote)
|
||||||
|
{
|
||||||
|
SendLobbyNotice(string.Format(Strings.NextVote, nickName, vote));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
SendLobbyNotice(string.Format(Strings.FirstVote, nickName, vote));
|
||||||
|
}
|
||||||
|
|
||||||
|
PlayerVotes[nickName] = vote;
|
||||||
|
SendLobbyNotice(GetVoteStatus());
|
||||||
|
CheckState();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
else if (CurrentState == State.Night)
|
||||||
|
{
|
||||||
|
if (!GetMafiosos().Contains(nickName))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
var recipients = GetMafiosos().Where(p => p != nickName);
|
||||||
|
if (PlayerVotes.ContainsKey(nickName) && PlayerVotes[nickName] != vote)
|
||||||
|
{
|
||||||
|
SendUsersNotice(recipients, string.Format(Strings.NextVote, nickName, vote));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
SendUsersNotice(recipients, string.Format(Strings.FirstVote, nickName, vote));
|
||||||
|
}
|
||||||
|
|
||||||
|
PlayerVotes[nickName] = vote;
|
||||||
|
CheckState();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
SendUsersNotice(new List<string> { nickName }, Strings.CantVote);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public string GetVoteStatus()
|
||||||
|
{
|
||||||
|
if (CurrentState == State.Day)
|
||||||
|
{
|
||||||
|
var message = Strings.VoteStatus;
|
||||||
|
message += string.Join(", ", PlayerVotes.Select(v => string.Format("{0} => {1}", v.Key, v.Value)));
|
||||||
|
if (PlayerVotes.Count == 0)
|
||||||
|
message += "(none)";
|
||||||
|
return message;
|
||||||
|
}
|
||||||
|
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool DetectMafioso(string nickName, string query)
|
||||||
|
{
|
||||||
|
if (GetDetective() != nickName)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (CurrentState != State.Night)
|
||||||
|
{
|
||||||
|
SendUsersNotice(new List<string> { nickName }, Strings.DetectiveNotNight);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!allPlayers.ContainsKey(query))
|
||||||
|
{
|
||||||
|
var message = Strings.InvalidVote + string.Join(", ", GetAllPlayers().Where(p => p != nickName));
|
||||||
|
SendUsersNotice(new List<string> { nickName }, message);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
var not = GetMafiosos().Any(s => s == query) ? "" : " not";
|
||||||
|
if (DetectiveTarget != null)
|
||||||
|
{
|
||||||
|
SendUsersNotice(new List<string> { nickName }, string.Format(Strings.DetectiveAlreadyDone, DetectiveTarget, not));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
DetectiveTarget = query;
|
||||||
|
SendUsersNotice(new List<string> { nickName }, string.Format(Strings.DetectiveFinished, DetectiveTarget, not));
|
||||||
|
CheckState();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool SaveCivilist(string nickName, string query)
|
||||||
|
{
|
||||||
|
if (GetDoctor() != nickName)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (CurrentState != State.Night)
|
||||||
|
{
|
||||||
|
SendUsersNotice(new List<string> { nickName }, Strings.DoctorNotNight);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!allPlayers.ContainsKey(query))
|
||||||
|
{
|
||||||
|
var message = Strings.InvalidVote + string.Join(", ", GetAllPlayers().Where(p => p != nickName));
|
||||||
|
SendUsersNotice(new List<string> { nickName }, message);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
DoctorSave = query;
|
||||||
|
SendUsersNotice(new List<string> { nickName }, string.Format(Strings.DoctorFinished, DoctorSave));
|
||||||
|
CheckState();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool VoteVigilanteKill(string nickName, string query)
|
||||||
|
{
|
||||||
|
if (GetVigilante() != nickName)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (CurrentState != State.Night)
|
||||||
|
{
|
||||||
|
SendUsersNotice(new List<string> { nickName }, Strings.VigilanteNotNight);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!allPlayers.ContainsKey(query))
|
||||||
|
{
|
||||||
|
var message = Strings.InvalidVote + string.Join(", ", GetAllPlayers().Where(p => p != nickName));
|
||||||
|
SendUsersNotice(new List<string> { nickName }, message);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
VigilanteKill = query;
|
||||||
|
SendUsersNotice(new List<string> { nickName }, string.Format(Strings.VigilanteFinished, VigilanteKill));
|
||||||
|
CheckState();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public string GetStatus()
|
||||||
|
{
|
||||||
|
if (CurrentState == State.Lobby)
|
||||||
|
{
|
||||||
|
var message = "A game was recently created by " + GameCreator + ". Waiting for players to join. Following players already joined: ";
|
||||||
|
var existing = string.Join(", ", GetAllPlayers());
|
||||||
|
return message + existing;
|
||||||
|
}
|
||||||
|
else if (CurrentState == State.Day)
|
||||||
|
{
|
||||||
|
var message = "It's day. Waiting for all players to place their vote. Following players haven't voted: ";
|
||||||
|
var missing = string.Join(", ", GetAllPlayers().Where(p => !PlayerVotes.Keys.Contains(p)));
|
||||||
|
return message + missing + ". " + GetVoteStatus();
|
||||||
|
}
|
||||||
|
else if (CurrentState == State.Night)
|
||||||
|
{
|
||||||
|
var message = "It's currently night. Everybody is sleeping. (yeah right)";
|
||||||
|
return message;
|
||||||
|
}
|
||||||
|
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
|
public string MafiosoKill;
|
||||||
|
public string DoctorSave;
|
||||||
|
public string VigilanteKill;
|
||||||
|
public string DetectiveTarget;
|
||||||
|
public string GameCreator;
|
||||||
|
public bool FirstDay;
|
||||||
|
public int NumPlayers;
|
||||||
|
public State CurrentState;
|
||||||
|
public Dictionary<string, Role> allPlayers = new Dictionary<string, Role>();
|
||||||
|
public string hallOfFame;
|
||||||
|
public IEnumerable<string> GetAllPlayers() { return allPlayers.Keys; }
|
||||||
|
public string GetDoctor() { return allPlayers.FirstOrDefault(p => p.Value == Role.Doctor).Key; }
|
||||||
|
public string GetVigilante() { return allPlayers.FirstOrDefault(p => p.Value == Role.Vigilante).Key; }
|
||||||
|
public string GetDetective() { return allPlayers.FirstOrDefault(p => p.Value == Role.Detective).Key; }
|
||||||
|
public IEnumerable<string> GetMafiosos() { return allPlayers.Where(p => p.Value == Role.Mafioso).Select(p => p.Key); }
|
||||||
|
public IEnumerable<string> GetCivilists() { return allPlayers.Where(p => p.Value == Role.Civilist).Select(p => p.Key); }
|
||||||
|
public Dictionary<string, string> PlayerVotes = new Dictionary<string, string>();
|
||||||
|
}
|
||||||
|
}
|
||||||
147
Concilium/Bot/PredicateLogic.cs
Normal file
147
Concilium/Bot/PredicateLogic.cs
Normal file
@@ -0,0 +1,147 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
|
||||||
|
namespace Concilium.Bot
|
||||||
|
{
|
||||||
|
public class PredicateLogic
|
||||||
|
{
|
||||||
|
private static string allowedChars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_";
|
||||||
|
public Dictionary<string, List<string>> Predicates;
|
||||||
|
|
||||||
|
public string Parse(string input)
|
||||||
|
{
|
||||||
|
if (Predicates == null)
|
||||||
|
Predicates = new Dictionary<string, List<string>>();
|
||||||
|
|
||||||
|
var lastQuestionMark = input.Last() == '?';
|
||||||
|
var firstQuestionMark = input.First() == '?';
|
||||||
|
var rand = new Random((int)DateTime.Now.TimeOfDay.TotalMilliseconds);
|
||||||
|
if (lastQuestionMark && firstQuestionMark)
|
||||||
|
{
|
||||||
|
bool randomPredicate = rand.Next(2) == 0;
|
||||||
|
if (randomPredicate)
|
||||||
|
{
|
||||||
|
var predicates = Predicates.Where(p => p.Value.Count > 0).ToList();
|
||||||
|
var index = rand.Next(predicates.Count);
|
||||||
|
var kvp = predicates.ElementAt(index);
|
||||||
|
return DisplayPredicate(kvp.Key);
|
||||||
|
}
|
||||||
|
else // randomUser
|
||||||
|
{
|
||||||
|
var users = Predicates.SelectMany(kvp => kvp.Value).Distinct().ToList();
|
||||||
|
var index = rand.Next(users.Count);
|
||||||
|
return DisplayUser(users[index]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (lastQuestionMark)
|
||||||
|
{
|
||||||
|
var predicate = input.Substring(0, input.Length - 1).Trim();
|
||||||
|
|
||||||
|
if (!predicate.All(c => allowedChars.IndexOf(c) != -1))
|
||||||
|
return "Syntax error: unexpected character in predicate";
|
||||||
|
|
||||||
|
if (!Predicates.ContainsKey(predicate) || Predicates[predicate].Count == 0)
|
||||||
|
return "No one is " + predicate;
|
||||||
|
|
||||||
|
return DisplayPredicate(predicate);
|
||||||
|
}
|
||||||
|
else if (firstQuestionMark)
|
||||||
|
{
|
||||||
|
input = input.Substring(1);
|
||||||
|
|
||||||
|
var leftBracket = input.IndexOf('(');
|
||||||
|
var rightBracket = input.IndexOf(')');
|
||||||
|
|
||||||
|
if (leftBracket == -1)
|
||||||
|
return "Syntax error: expecting '('";
|
||||||
|
if (rightBracket == -1)
|
||||||
|
return "Syntax error: expecting ')'";
|
||||||
|
if (rightBracket < leftBracket)
|
||||||
|
return "Syntax error: unexpected ')', was expecting '('";
|
||||||
|
|
||||||
|
var parameter = input.Substring(leftBracket + 1, rightBracket - leftBracket - 1).Trim();
|
||||||
|
|
||||||
|
if (!parameter.Any(c => allowedChars.IndexOf(c) != -1))
|
||||||
|
return "Syntax error: unexpected character in parameter";
|
||||||
|
|
||||||
|
return DisplayUser(parameter);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
var leftBracket = input.IndexOf('(');
|
||||||
|
var rightBracket = input.IndexOf(')');
|
||||||
|
if (leftBracket == -1)
|
||||||
|
return "Syntax error: expecting '('";
|
||||||
|
if (rightBracket == -1)
|
||||||
|
return "Syntax error: expecting ')'";
|
||||||
|
if (rightBracket < leftBracket)
|
||||||
|
return "Syntax error: unexpected ')', was expecting '('";
|
||||||
|
|
||||||
|
var predicate = input.Substring(0, leftBracket).Trim();
|
||||||
|
var parameter = input.Substring(leftBracket + 1, rightBracket - leftBracket - 1).Trim();
|
||||||
|
|
||||||
|
var inverse = predicate[0] == '!';
|
||||||
|
if (inverse)
|
||||||
|
predicate = predicate.Substring(1);
|
||||||
|
|
||||||
|
if (!predicate.All(c => allowedChars.IndexOf(c) != -1))
|
||||||
|
return "Syntax error: unexpected character in predicate";
|
||||||
|
|
||||||
|
if (!parameter.Any(c => allowedChars.IndexOf(c) != -1))
|
||||||
|
return "Syntax error: unexpected character in parameter";
|
||||||
|
|
||||||
|
if (!Predicates.ContainsKey(predicate))
|
||||||
|
Predicates[predicate] = new List<string>();
|
||||||
|
|
||||||
|
if (inverse)
|
||||||
|
{
|
||||||
|
if (Predicates[predicate].Contains(parameter))
|
||||||
|
{
|
||||||
|
Predicates[predicate].Remove(parameter);
|
||||||
|
return parameter + " is no longer " + predicate;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return parameter + " is not currently " + predicate;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (Predicates[predicate].Contains(parameter))
|
||||||
|
{
|
||||||
|
return parameter + " is already " + predicate;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Predicates[predicate].Add(parameter);
|
||||||
|
return parameter + " is now " + predicate;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private string DisplayUser(string user)
|
||||||
|
{
|
||||||
|
var predicates = Predicates.Where(kvp => kvp.Value.Contains(user)).Select(kvp => kvp.Key);
|
||||||
|
if (predicates.Count() == 0)
|
||||||
|
return "I don't know nothing about " + user;
|
||||||
|
|
||||||
|
var list = string.Join(", ", predicates);
|
||||||
|
var lastComma = list.LastIndexOf(',');
|
||||||
|
if (lastComma != -1)
|
||||||
|
list = list.Substring(0, lastComma) + " and" + list.Substring(lastComma + 1, list.Length - lastComma - 1);
|
||||||
|
return user + " is " + list;
|
||||||
|
}
|
||||||
|
|
||||||
|
private string DisplayPredicate(string predicate)
|
||||||
|
{
|
||||||
|
var list = string.Join(", ", Predicates[predicate]);
|
||||||
|
var lastComma = list.LastIndexOf(',');
|
||||||
|
if (lastComma != -1)
|
||||||
|
list = list.Substring(0, lastComma) + " and" + list.Substring(lastComma + 1, list.Length - lastComma - 1);
|
||||||
|
return list + (Predicates[predicate].Count > 1 ? " are " : " is ") + predicate;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
559
Concilium/Bot/Resistance.cs
Normal file
559
Concilium/Bot/Resistance.cs
Normal file
@@ -0,0 +1,559 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using Concilium.Helpers;
|
||||||
|
|
||||||
|
namespace Concilium.Bot
|
||||||
|
{
|
||||||
|
public class Resistance
|
||||||
|
{
|
||||||
|
private static class Strings
|
||||||
|
{
|
||||||
|
public static string Welcome = "A new The Resistance game was started by {0}!";
|
||||||
|
public static string TooFewPlayers = "There are still too few players. At least 5 players are required.";
|
||||||
|
public static string UserJoined = "{0} joined The Resistance game!";
|
||||||
|
public static string UserCantJoin = "I'm sorry, {0}. You can't join the current The Resistance game, since it already started.";
|
||||||
|
public static string UserDuplicate = "You already joined The Resistance game!";
|
||||||
|
public static string GameBegins = "All necessary players joined! Let the game begin!";
|
||||||
|
public static string HallOfFame = "Following players participated: ";
|
||||||
|
public static string AgreeDisagreeNotice = "Every player must now " + (char)2 + ".resist agree" + (char)2 + " or " + (char)2 + ".resist disagree" + (char)2 + " with the team.";
|
||||||
|
public static string ExecuteSabotageNotice = "You must now " + (char)2 + ".resist execute" + (char)2 + " or " + (char)2 + ".resist sabotage" + (char)2 + " the mission.";
|
||||||
|
public static string ExecuteNotice = "You must now " + (char)2 + ".resist execute" + (char)2 + " the mission.";
|
||||||
|
public static string PlayingSpy = "You're playing an imperial spy. Your job is to sabotage as many missions as possible, without revealing your identity to the resistance! The infiltrating spies are: {0}";
|
||||||
|
public static string PlayingResistance = "You're playing in the resistance. Your job is to accomplish as many missions as possible.";
|
||||||
|
public static string NewLeader = "A new leader has been determined: ";
|
||||||
|
public static string LeaderOrder = "The order for determining leaders is as follows: ";
|
||||||
|
public static string BeginGatheringTeam = "The leader must now choose the team members (attempt #{0}). {1} players must be in the team.";
|
||||||
|
public static string BeginVotingTeam = "The proposed team consists of: {0}. Please vote now if you agree or disagree with that team.";
|
||||||
|
public static string BeginMission = "The team will now execute the mission. If there are spies the mission might fail. Required spy sabotages for mission failure: {0}";
|
||||||
|
public static string SpiesWin = "The spies have managed to sabotage 3 missions and won the game!";
|
||||||
|
public static string ResistanceWins = "The resistance has managed to execute 3 missions and wins the game!";
|
||||||
|
public static string ShowVotes = "All players voted, these are the results: {0}";
|
||||||
|
public static string VoteFailed = "No majority could be found, a new team will be selected from a new leader.";
|
||||||
|
public static string LastTry = "This is the last attempt for finding a team. The proposal of the leader will be automatically accepted.";
|
||||||
|
public static string MissionFailed = "The mission was sabotaged and failed, because {0} player(s) sabotaged the mission. Score: Spies({1}), Resistance({2})";
|
||||||
|
public static string MissionAccomplishedClean = "The mission was accomplished successfully without any sabotage. Score: Spies({0}), Resistance({1})";
|
||||||
|
public static string MissionAccomplishedBarely = "The mission was accomplished successfully, although {0} player(s) committed sabotage. Score: Spies({1}), Resistance({2})";
|
||||||
|
public static string MissionData1 = "There are 5 missions, each mission requires a team with a certain amount of people, and requires a certain amount of sabotage acts to fail.";
|
||||||
|
public static string MissionData2 = "Team size/sabotages: ({0}/{1}), ({2}/{3}), ({4}/{5}), ({6}/{7}), ({8}/{9}).";
|
||||||
|
}
|
||||||
|
|
||||||
|
public enum State
|
||||||
|
{
|
||||||
|
Lobby,
|
||||||
|
GatheringTeam,
|
||||||
|
VotingTeam,
|
||||||
|
Mission
|
||||||
|
};
|
||||||
|
|
||||||
|
public enum Role
|
||||||
|
{
|
||||||
|
Unassigned,
|
||||||
|
Spy,
|
||||||
|
Resistance
|
||||||
|
};
|
||||||
|
|
||||||
|
public delegate void DummyHandler();
|
||||||
|
public event DummyHandler GameOver;
|
||||||
|
private void SendGameOver()
|
||||||
|
{
|
||||||
|
if (GameOver != null)
|
||||||
|
GameOver();
|
||||||
|
}
|
||||||
|
public event DummyHandler GatheringBegins;
|
||||||
|
private void SendGatheringBegins()
|
||||||
|
{
|
||||||
|
if (GatheringBegins != null)
|
||||||
|
GatheringBegins();
|
||||||
|
}
|
||||||
|
public event DummyHandler MissionBegins;
|
||||||
|
private void SendMissionBegins()
|
||||||
|
{
|
||||||
|
if (MissionBegins != null)
|
||||||
|
MissionBegins();
|
||||||
|
}
|
||||||
|
|
||||||
|
public delegate void LobbyNoticeHandler(string notice);
|
||||||
|
public event LobbyNoticeHandler OnLobbyNotice;
|
||||||
|
private void SendLobbyNotice(string notice)
|
||||||
|
{
|
||||||
|
if (OnLobbyNotice != null)
|
||||||
|
OnLobbyNotice(notice);
|
||||||
|
}
|
||||||
|
|
||||||
|
public delegate void UsersNoticeHandler(IEnumerable<string> users, string notice);
|
||||||
|
public event UsersNoticeHandler OnUsersNotice;
|
||||||
|
private void SendUsersNotice(IEnumerable<string> users, string notice)
|
||||||
|
{
|
||||||
|
if (OnUsersNotice != null && users.Count() > 0)
|
||||||
|
OnUsersNotice(users, notice);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Resistance()
|
||||||
|
{
|
||||||
|
this.CurrentState = State.Lobby;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Init(string nickName)
|
||||||
|
{
|
||||||
|
this.GameCreator = nickName;
|
||||||
|
this.Leader = null;
|
||||||
|
this.NumPlayers = -1;
|
||||||
|
this.CurrentMission = 0;
|
||||||
|
this.ScoreSpies = 0;
|
||||||
|
this.ScoreResistance = 0;
|
||||||
|
this.TeamTries = 0;
|
||||||
|
SendLobbyNotice(string.Format(Strings.Welcome, this.GameCreator));
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool StartGame(string nickName)
|
||||||
|
{
|
||||||
|
if (CurrentState != State.Lobby)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (GameCreator != nickName)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (allPlayers.Count < 5)
|
||||||
|
{
|
||||||
|
SendLobbyNotice(string.Format(Strings.TooFewPlayers, nickName));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.NumPlayers = allPlayers.Count;
|
||||||
|
CheckState();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool JoinPlayer(string nickName)
|
||||||
|
{
|
||||||
|
if (CurrentState != State.Lobby)
|
||||||
|
{
|
||||||
|
SendUsersNotice(new List<string> { nickName }, string.Format(Strings.UserCantJoin, nickName));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (allPlayers.ContainsKey(nickName))
|
||||||
|
{
|
||||||
|
SendUsersNotice(new List<string> { nickName }, Strings.UserDuplicate);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
allPlayers[nickName] = Role.Unassigned;
|
||||||
|
SendLobbyNotice(string.Format(Strings.UserJoined, nickName));
|
||||||
|
CheckState();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
private int GetSpyCount()
|
||||||
|
{
|
||||||
|
switch (NumPlayers)
|
||||||
|
{
|
||||||
|
case 5: return 2;
|
||||||
|
case 6: return 2;
|
||||||
|
case 7: return 3;
|
||||||
|
case 8: return 3;
|
||||||
|
case 9: return 3;
|
||||||
|
case 10: return 4;
|
||||||
|
}
|
||||||
|
|
||||||
|
throw new InvalidOperationException("Only 5 to 10 players supported");
|
||||||
|
}
|
||||||
|
|
||||||
|
private int GetTeamSize()
|
||||||
|
{
|
||||||
|
switch (NumPlayers)
|
||||||
|
{
|
||||||
|
case 5: return (new int[] { 2, 3, 2, 3, 3 })[CurrentMission - 1];
|
||||||
|
case 6: return (new int[] { 2, 3, 4, 3, 4 })[CurrentMission - 1];
|
||||||
|
case 7: return (new int[] { 2, 3, 3, 4, 4 })[CurrentMission - 1];
|
||||||
|
case 8: return (new int[] { 3, 4, 4, 5, 5 })[CurrentMission - 1];
|
||||||
|
case 9: return (new int[] { 3, 4, 4, 5, 5 })[CurrentMission - 1];
|
||||||
|
case 10: return (new int[] { 3, 4, 4, 5, 5 })[CurrentMission - 1];
|
||||||
|
}
|
||||||
|
|
||||||
|
throw new InvalidOperationException("Only 5 to 10 players supported");
|
||||||
|
}
|
||||||
|
|
||||||
|
private int GetNumSabotages()
|
||||||
|
{
|
||||||
|
if (CurrentMission == 4 && NumPlayers >= 7)
|
||||||
|
return 2;
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void CheckState()
|
||||||
|
{
|
||||||
|
if (string.IsNullOrEmpty(GameCreator))
|
||||||
|
return;
|
||||||
|
|
||||||
|
switch (CurrentState)
|
||||||
|
{
|
||||||
|
case State.Lobby:
|
||||||
|
if (allPlayers.Count == NumPlayers)
|
||||||
|
{
|
||||||
|
SendLobbyNotice(Strings.GameBegins);
|
||||||
|
|
||||||
|
// Assign roles
|
||||||
|
var players = new List<string>(allPlayers.Keys);
|
||||||
|
players.Shuffle();
|
||||||
|
var spies = players.Take(GetSpyCount()).ToList();
|
||||||
|
var resistants = players.Skip(GetSpyCount()).ToList();
|
||||||
|
|
||||||
|
foreach (var player in resistants)
|
||||||
|
{
|
||||||
|
allPlayers[player] = Role.Resistance;
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach (var player in spies)
|
||||||
|
{
|
||||||
|
allPlayers[player] = Role.Spy;
|
||||||
|
}
|
||||||
|
|
||||||
|
players.Shuffle();
|
||||||
|
playerOrder.AddRange(players);
|
||||||
|
SendLobbyNotice(Strings.LeaderOrder + string.Join(", ", playerOrder));
|
||||||
|
SetLeader(playerOrder[0]);
|
||||||
|
|
||||||
|
SendUsersNotice(resistants, Strings.PlayingResistance);
|
||||||
|
SendUsersNotice(spies, string.Format(Strings.PlayingSpy, string.Join(", ", spies)));
|
||||||
|
GenerateHallOfFame();
|
||||||
|
SendMissionData();
|
||||||
|
BeginGatheringTeam();
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case State.GatheringTeam:
|
||||||
|
if (TeamMembers.Count == GetTeamSize())
|
||||||
|
{
|
||||||
|
if (TeamTries >= 4)
|
||||||
|
BeginMission();
|
||||||
|
else
|
||||||
|
BeginVotingTeam();
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case State.VotingTeam:
|
||||||
|
if (playerAgreesWithTeam.Count == NumPlayers)
|
||||||
|
{
|
||||||
|
SendLobbyNotice(string.Format(Strings.ShowVotes, string.Join(", ", playerAgreesWithTeam.Select(p => (p.Value ? "+" : "-") + p.Key))));
|
||||||
|
|
||||||
|
var agrees = 0;
|
||||||
|
var disagrees = 0;
|
||||||
|
foreach (var vote in playerAgreesWithTeam)
|
||||||
|
{
|
||||||
|
if (vote.Value)
|
||||||
|
++agrees;
|
||||||
|
else
|
||||||
|
++disagrees;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (agrees > disagrees)
|
||||||
|
{
|
||||||
|
TeamTries = 0;
|
||||||
|
BeginMission();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
SendLobbyNotice(Strings.VoteFailed);
|
||||||
|
RotateLeader();
|
||||||
|
++TeamTries;
|
||||||
|
--CurrentMission;
|
||||||
|
BeginGatheringTeam();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case State.Mission:
|
||||||
|
if (playerSabotagesMission.Count == GetTeamSize())
|
||||||
|
{
|
||||||
|
var sabotages = 0;
|
||||||
|
foreach (var vote in playerAgreesWithTeam)
|
||||||
|
{
|
||||||
|
if (vote.Value)
|
||||||
|
++sabotages;
|
||||||
|
}
|
||||||
|
|
||||||
|
var gameOver = false;
|
||||||
|
if (sabotages >= GetNumSabotages())
|
||||||
|
{
|
||||||
|
++ScoreSpies;
|
||||||
|
SendLobbyNotice(string.Format(Strings.MissionFailed, sabotages, ScoreSpies, ScoreResistance));
|
||||||
|
if (ScoreSpies >= 3)
|
||||||
|
{
|
||||||
|
SendLobbyNotice(Strings.SpiesWin);
|
||||||
|
SendGameOver();
|
||||||
|
gameOver = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
++ScoreResistance;
|
||||||
|
if (sabotages == 0)
|
||||||
|
SendLobbyNotice(string.Format(Strings.MissionAccomplishedClean, ScoreSpies, ScoreResistance));
|
||||||
|
else
|
||||||
|
SendLobbyNotice(string.Format(Strings.MissionAccomplishedBarely, sabotages, ScoreSpies, ScoreResistance));
|
||||||
|
if (ScoreResistance >= 3)
|
||||||
|
{
|
||||||
|
SendLobbyNotice(Strings.ResistanceWins);
|
||||||
|
SendGameOver();
|
||||||
|
gameOver = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!gameOver)
|
||||||
|
{
|
||||||
|
RotateLeader();
|
||||||
|
BeginGatheringTeam();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
throw new NotImplementedException("BUG! Implementation incomplete, an internal state was not handled");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void SendMissionData()
|
||||||
|
{
|
||||||
|
SendLobbyNotice(Strings.MissionData1);
|
||||||
|
SendLobbyNotice(Strings.MissionData2);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void RotateLeader()
|
||||||
|
{
|
||||||
|
var currentIndex = playerOrder.IndexOf(Leader);
|
||||||
|
var newIndex = currentIndex + 1;
|
||||||
|
if (newIndex >= playerOrder.Count)
|
||||||
|
newIndex = 0;
|
||||||
|
SetLeader(playerOrder[newIndex]);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void SetLeader(string player)
|
||||||
|
{
|
||||||
|
Leader = player;
|
||||||
|
SendLobbyNotice(Strings.NewLeader + player);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void BeginGatheringTeam()
|
||||||
|
{
|
||||||
|
if (CurrentState == State.GatheringTeam)
|
||||||
|
throw new InvalidOperationException("Can't begin gathering team right now");
|
||||||
|
|
||||||
|
++CurrentMission;
|
||||||
|
CurrentState = State.GatheringTeam;
|
||||||
|
TeamMembers.Clear();
|
||||||
|
SendLobbyNotice(string.Format(Strings.BeginGatheringTeam, TeamTries + 1, GetTeamSize()));
|
||||||
|
if (TeamTries >= 4)
|
||||||
|
SendLobbyNotice(string.Format(Strings.LastTry, GetTeamSize()));
|
||||||
|
}
|
||||||
|
|
||||||
|
private void BeginVotingTeam()
|
||||||
|
{
|
||||||
|
if (CurrentState != State.GatheringTeam)
|
||||||
|
throw new InvalidOperationException("Can't begin voting team right now");
|
||||||
|
|
||||||
|
CurrentState = State.VotingTeam;
|
||||||
|
playerAgreesWithTeam.Clear();
|
||||||
|
SendLobbyNotice(string.Format(Strings.BeginVotingTeam, string.Join(", ", TeamMembers)));
|
||||||
|
SendLobbyNotice(Strings.AgreeDisagreeNotice);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void BeginMission()
|
||||||
|
{
|
||||||
|
if (CurrentState != State.VotingTeam && CurrentState != State.GatheringTeam)
|
||||||
|
throw new InvalidOperationException("Can't begin the mission right now");
|
||||||
|
|
||||||
|
TeamTries = 0;
|
||||||
|
CurrentState = State.Mission;
|
||||||
|
playerSabotagesMission.Clear();
|
||||||
|
SendLobbyNotice(string.Format(Strings.BeginMission, GetNumSabotages()));
|
||||||
|
SendUsersNotice(ResistancePlayers(), Strings.ExecuteNotice);
|
||||||
|
SendUsersNotice(SpyPlayers(), Strings.ExecuteSabotageNotice);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void SetTeamMembers(string nick, IEnumerable<string> members)
|
||||||
|
{
|
||||||
|
if (nick != Leader)
|
||||||
|
{
|
||||||
|
SendUsersNotice(new string[] { nick }, string.Format("You're not the team leader, so you can't choose team members! {0} is the team leader.", Leader));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (CurrentState != State.GatheringTeam)
|
||||||
|
{
|
||||||
|
SendUsersNotice(new string[] { nick }, "You cannot gather a team right now.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (members.Count() != GetTeamSize())
|
||||||
|
{
|
||||||
|
SendUsersNotice(new string[] { nick }, string.Format("You need to specify exactly {0} distinct members!", GetTeamSize()));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach (var member in members)
|
||||||
|
{
|
||||||
|
if (!allPlayers.ContainsKey(member))
|
||||||
|
{
|
||||||
|
SendUsersNotice(new string[] { nick }, "There's no such player: " + member);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
TeamMembers.Clear();
|
||||||
|
TeamMembers.AddRange(members);
|
||||||
|
CheckState();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void AgreeTeam(string nick)
|
||||||
|
{
|
||||||
|
if (CurrentState != State.VotingTeam)
|
||||||
|
{
|
||||||
|
SendUsersNotice(new string[] { nick }, "You cannot agree for a team right now.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (playerAgreesWithTeam.ContainsKey(nick))
|
||||||
|
{
|
||||||
|
SendUsersNotice(new string[] { nick }, "You have already decided for this team.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
SendUsersNotice(new string[] { nick }, "You have agreed with the proposed team. This decision can't be undone.");
|
||||||
|
|
||||||
|
playerAgreesWithTeam[nick] = true;
|
||||||
|
CheckState();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void DisagreeTeam(string nick)
|
||||||
|
{
|
||||||
|
if (CurrentState != State.VotingTeam)
|
||||||
|
{
|
||||||
|
SendUsersNotice(new string[] { nick }, "You cannot disagree for a team right now.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (playerAgreesWithTeam.ContainsKey(nick))
|
||||||
|
{
|
||||||
|
SendUsersNotice(new string[] { nick }, "You have already decided for this team.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
SendUsersNotice(new string[] { nick }, "You have disagreed with the proposed team. This decision can't be undone.");
|
||||||
|
|
||||||
|
playerAgreesWithTeam[nick] = false;
|
||||||
|
CheckState();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void ExecuteMission(string nick)
|
||||||
|
{
|
||||||
|
if (CurrentState != State.Mission)
|
||||||
|
{
|
||||||
|
SendUsersNotice(new string[] { nick }, "You cannot execute the mission right now.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (playerSabotagesMission.ContainsKey(nick))
|
||||||
|
{
|
||||||
|
SendUsersNotice(new string[] { nick }, "You have already decided for this mission.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!TeamMembers.Contains(nick))
|
||||||
|
{
|
||||||
|
SendUsersNotice(new string[] { nick }, "You can't decide for this mission since you're not on the team!");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
playerSabotagesMission[nick] = false;
|
||||||
|
CheckState();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void SabotageMission(string nick)
|
||||||
|
{
|
||||||
|
if (CurrentState != State.Mission)
|
||||||
|
{
|
||||||
|
SendUsersNotice(new string[] { nick }, "You cannot sabotage the mission right now.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (allPlayers[nick] == Role.Resistance)
|
||||||
|
{
|
||||||
|
SendUsersNotice(new string[] { nick }, "You cannot sabotage the mission as a resistance member!.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (playerSabotagesMission.ContainsKey(nick))
|
||||||
|
{
|
||||||
|
SendUsersNotice(new string[] { nick }, "You have already decided for this mission.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!TeamMembers.Contains(nick))
|
||||||
|
{
|
||||||
|
SendUsersNotice(new string[] { nick }, "You can't decide for this mission since you're not on the team!");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
playerSabotagesMission[nick] = true;
|
||||||
|
CheckState();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void GenerateHallOfFame()
|
||||||
|
{
|
||||||
|
hallOfFame = Strings.HallOfFame + string.Join(", ", allPlayers.Select(p => p.Key + " (" + p.Value.ToString() + ")"));
|
||||||
|
}
|
||||||
|
|
||||||
|
public string GetStatus()
|
||||||
|
{
|
||||||
|
if (CurrentState == State.Lobby)
|
||||||
|
{
|
||||||
|
var message = "A game was recently created by " + GameCreator + ". Waiting for players to join. Following players already joined: ";
|
||||||
|
var existing = string.Join(", ", GetAllPlayers());
|
||||||
|
return message + existing;
|
||||||
|
}
|
||||||
|
else if (CurrentState == State.GatheringTeam)
|
||||||
|
{
|
||||||
|
var message = "The leader, {0}, is gathering the team. A total of {1} team members are needed for mission #{2}. Score: Spies({3}), Resistance({4})";
|
||||||
|
return string.Format(message, Leader, GetTeamSize(), CurrentMission, ScoreSpies, ScoreResistance);
|
||||||
|
}
|
||||||
|
else if (CurrentState == State.VotingTeam)
|
||||||
|
{
|
||||||
|
var message = "The leader is {0}. Waiting for all players to vote for the mission team ({1}). Following players haven't voted yet: {2}. Score: Spies({3}), Resistance({4})";
|
||||||
|
var missing = string.Join(", ", allPlayers.Where(p => !this.playerAgreesWithTeam.Keys.Contains(p.Key)).Select(p => p.Key));
|
||||||
|
var team = string.Join(", ", TeamMembers);
|
||||||
|
return string.Format(message, Leader, team, missing, ScoreSpies, ScoreResistance);
|
||||||
|
}
|
||||||
|
else if (CurrentState == State.Mission)
|
||||||
|
{
|
||||||
|
var message = "The leader is {0}. The team ({1}) is executing the mission. Each team member has to decide if the mission is executed or sabotaged. Following players haven't decided yet: {2}. Score: Spies({3}), Resistance({4})";
|
||||||
|
var missing = string.Join(", ", TeamMembers.Where(p => !this.playerSabotagesMission.Keys.Contains(p)));
|
||||||
|
var team = string.Join(", ", TeamMembers);
|
||||||
|
return string.Format(message, Leader, team, missing, ScoreSpies, ScoreResistance);
|
||||||
|
}
|
||||||
|
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
|
public string GameCreator;
|
||||||
|
public string Leader;
|
||||||
|
public int CurrentMission;
|
||||||
|
public int ScoreSpies;
|
||||||
|
public int ScoreResistance;
|
||||||
|
public int NumPlayers;
|
||||||
|
public int TeamTries;
|
||||||
|
public State CurrentState;
|
||||||
|
public Dictionary<string, Role> allPlayers = new Dictionary<string, Role>();
|
||||||
|
public Dictionary<string, bool> playerAgreesWithTeam = new Dictionary<string, bool>();
|
||||||
|
public Dictionary<string, bool> playerSabotagesMission = new Dictionary<string, bool>();
|
||||||
|
public List<string> TeamMembers = new List<string>();
|
||||||
|
public List<string> playerOrder = new List<string>();
|
||||||
|
public string hallOfFame;
|
||||||
|
public IEnumerable<string> GetAllPlayers() { return allPlayers.Keys; }
|
||||||
|
public IEnumerable<string> ResistancePlayers() { return allPlayers.Where(p => p.Value == Role.Resistance).Select(p => p.Key); }
|
||||||
|
public IEnumerable<string> SpyPlayers() { return allPlayers.Where(p => p.Value == Role.Spy).Select(p => p.Key); }
|
||||||
|
}
|
||||||
|
}
|
||||||
174
Concilium/Concilium.csproj
Normal file
174
Concilium/Concilium.csproj
Normal file
@@ -0,0 +1,174 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||||
|
<PropertyGroup>
|
||||||
|
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
|
||||||
|
<Platform Condition=" '$(Platform)' == '' ">x86</Platform>
|
||||||
|
<ProductVersion>8.0.30703</ProductVersion>
|
||||||
|
<SchemaVersion>2.0</SchemaVersion>
|
||||||
|
<ProjectGuid>{2695100D-D24B-4B41-8035-D1E8ED9A87CF}</ProjectGuid>
|
||||||
|
<OutputType>Exe</OutputType>
|
||||||
|
<AppDesignerFolder>Properties</AppDesignerFolder>
|
||||||
|
<RootNamespace>Concilium</RootNamespace>
|
||||||
|
<AssemblyName>Concilium</AssemblyName>
|
||||||
|
<TargetFrameworkVersion>v4.0</TargetFrameworkVersion>
|
||||||
|
<TargetFrameworkProfile>
|
||||||
|
</TargetFrameworkProfile>
|
||||||
|
<FileAlignment>512</FileAlignment>
|
||||||
|
<ProjectTypeGuids>{60dc8134-eba5-43b8-bcc9-bb4bc16c2548};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>
|
||||||
|
<WarningLevel>4</WarningLevel>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|x86' ">
|
||||||
|
<PlatformTarget>x86</PlatformTarget>
|
||||||
|
<DebugSymbols>true</DebugSymbols>
|
||||||
|
<DebugType>full</DebugType>
|
||||||
|
<Optimize>false</Optimize>
|
||||||
|
<OutputPath>bin\Debug\</OutputPath>
|
||||||
|
<DefineConstants>TRACE;DEBUG;LOG4NET</DefineConstants>
|
||||||
|
<ErrorReport>prompt</ErrorReport>
|
||||||
|
<WarningLevel>4</WarningLevel>
|
||||||
|
<UseVSHostingProcess>true</UseVSHostingProcess>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|x86' ">
|
||||||
|
<PlatformTarget>x86</PlatformTarget>
|
||||||
|
<DebugType>pdbonly</DebugType>
|
||||||
|
<Optimize>true</Optimize>
|
||||||
|
<OutputPath>bin\Release\</OutputPath>
|
||||||
|
<DefineConstants>TRACE</DefineConstants>
|
||||||
|
<ErrorReport>prompt</ErrorReport>
|
||||||
|
<WarningLevel>4</WarningLevel>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup>
|
||||||
|
<StartupObject>Concilium.App</StartupObject>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|AnyCPU'">
|
||||||
|
<DebugSymbols>true</DebugSymbols>
|
||||||
|
<OutputPath>bin\Debug\</OutputPath>
|
||||||
|
<DefineConstants>TRACE;DEBUG;LOG4NET</DefineConstants>
|
||||||
|
<DebugType>full</DebugType>
|
||||||
|
<PlatformTarget>AnyCPU</PlatformTarget>
|
||||||
|
<CodeAnalysisLogFile>bin\Debug\Concilium.exe.CodeAnalysisLog.xml</CodeAnalysisLogFile>
|
||||||
|
<CodeAnalysisUseTypeNameInSuppression>true</CodeAnalysisUseTypeNameInSuppression>
|
||||||
|
<CodeAnalysisModuleSuppressionsFile>GlobalSuppressions.cs</CodeAnalysisModuleSuppressionsFile>
|
||||||
|
<ErrorReport>prompt</ErrorReport>
|
||||||
|
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
|
||||||
|
<CodeAnalysisRuleSetDirectories>;C:\Program Files (x86)\Microsoft Visual Studio 10.0\Team Tools\Static Analysis Tools\\Rule Sets</CodeAnalysisRuleSetDirectories>
|
||||||
|
<CodeAnalysisIgnoreBuiltInRuleSets>false</CodeAnalysisIgnoreBuiltInRuleSets>
|
||||||
|
<CodeAnalysisRuleDirectories>;C:\Program Files (x86)\Microsoft Visual Studio 10.0\Team Tools\Static Analysis Tools\FxCop\\Rules</CodeAnalysisRuleDirectories>
|
||||||
|
<CodeAnalysisIgnoreBuiltInRules>false</CodeAnalysisIgnoreBuiltInRules>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|AnyCPU'">
|
||||||
|
<OutputPath>bin\Release\</OutputPath>
|
||||||
|
<DefineConstants>TRACE</DefineConstants>
|
||||||
|
<Optimize>true</Optimize>
|
||||||
|
<DebugType>pdbonly</DebugType>
|
||||||
|
<PlatformTarget>AnyCPU</PlatformTarget>
|
||||||
|
<CodeAnalysisLogFile>bin\Release\Concilium.exe.CodeAnalysisLog.xml</CodeAnalysisLogFile>
|
||||||
|
<CodeAnalysisUseTypeNameInSuppression>true</CodeAnalysisUseTypeNameInSuppression>
|
||||||
|
<CodeAnalysisModuleSuppressionsFile>GlobalSuppressions.cs</CodeAnalysisModuleSuppressionsFile>
|
||||||
|
<ErrorReport>prompt</ErrorReport>
|
||||||
|
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
|
||||||
|
<CodeAnalysisRuleSetDirectories>;C:\Program Files (x86)\Microsoft Visual Studio 10.0\Team Tools\Static Analysis Tools\\Rule Sets</CodeAnalysisRuleSetDirectories>
|
||||||
|
<CodeAnalysisIgnoreBuiltInRuleSets>false</CodeAnalysisIgnoreBuiltInRuleSets>
|
||||||
|
<CodeAnalysisRuleDirectories>;C:\Program Files (x86)\Microsoft Visual Studio 10.0\Team Tools\Static Analysis Tools\FxCop\\Rules</CodeAnalysisRuleDirectories>
|
||||||
|
<CodeAnalysisIgnoreBuiltInRules>false</CodeAnalysisIgnoreBuiltInRules>
|
||||||
|
</PropertyGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<Reference Include="IrcDotNet">
|
||||||
|
<HintPath>..\packages\IrcDotNet.0.5.0\lib\net40\IrcDotNet.dll</HintPath>
|
||||||
|
</Reference>
|
||||||
|
<Reference Include="log4net">
|
||||||
|
<HintPath>.\log4net.dll</HintPath>
|
||||||
|
</Reference>
|
||||||
|
<Reference Include="Newtonsoft.Json">
|
||||||
|
<HintPath>.\Newtonsoft.Json.dll</HintPath>
|
||||||
|
</Reference>
|
||||||
|
<Reference Include="SmartIrc4Net">
|
||||||
|
<HintPath>.\SmartIrc4Net.dll</HintPath>
|
||||||
|
</Reference>
|
||||||
|
<Reference Include="System" />
|
||||||
|
<Reference Include="System.Data" />
|
||||||
|
<Reference Include="System.Drawing" />
|
||||||
|
<Reference Include="System.ServiceModel" />
|
||||||
|
<Reference Include="System.Web" />
|
||||||
|
<Reference Include="System.Web.ApplicationServices" />
|
||||||
|
<Reference Include="System.Web.Services" />
|
||||||
|
<Reference Include="System.Xml" />
|
||||||
|
<Reference Include="Microsoft.CSharp" />
|
||||||
|
<Reference Include="System.Core" />
|
||||||
|
<Reference Include="System.Xml.Linq" />
|
||||||
|
<Reference Include="System.Data.DataSetExtensions" />
|
||||||
|
<Reference Include="System.Xaml">
|
||||||
|
<RequiredTargetFramework>4.0</RequiredTargetFramework>
|
||||||
|
</Reference>
|
||||||
|
<Reference Include="WindowsBase" />
|
||||||
|
<Reference Include="PresentationCore" />
|
||||||
|
<Reference Include="PresentationFramework" />
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<Compile Include="App.cs" />
|
||||||
|
<Compile Include="Bot\BotFeatureAttribute.cs" />
|
||||||
|
<Compile Include="Bot\BotFeatureBase.cs" />
|
||||||
|
<Compile Include="Bot\Features\FortuneFeature.cs" />
|
||||||
|
<Compile Include="Bot\Features\GoogleFeature.cs" />
|
||||||
|
<Compile Include="Bot\Features\JokeFeature.cs" />
|
||||||
|
<Compile Include="Bot\Features\MafiaFeature.cs" />
|
||||||
|
<Compile Include="Bot\Features\RssFeature.cs" />
|
||||||
|
<Compile Include="Bot\Features\TheResistanceFeature.cs" />
|
||||||
|
<Compile Include="Bot\Features\UserMonitorFeature.cs" />
|
||||||
|
<Compile Include="Bot\IBotFeature.cs" />
|
||||||
|
<Compile Include="Bot\IrcBot.cs" />
|
||||||
|
<Compile Include="Bot\IrcClientExtensions.cs" />
|
||||||
|
<Compile Include="Bot\PredicateLogic.cs" />
|
||||||
|
<Compile Include="Bot\Resistance.cs">
|
||||||
|
<SubType>Code</SubType>
|
||||||
|
</Compile>
|
||||||
|
<Compile Include="Helpers\CmdLineToArgvW.cs" />
|
||||||
|
<Compile Include="Bot\Concilium.cs">
|
||||||
|
<SubType>Code</SubType>
|
||||||
|
</Compile>
|
||||||
|
<Compile Include="Bot\Mafia.cs" />
|
||||||
|
<Compile Include="Bot\InvalidCommandParametersException.cs" />
|
||||||
|
<Compile Include="Helpers\ConsoleHelpers.cs" />
|
||||||
|
<Compile Include="Helpers\ListExtensions.cs" />
|
||||||
|
<Compile Include="Helpers\Log.cs" />
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<Compile Include="Helpers\StringExtensions.cs" />
|
||||||
|
<Compile Include="Properties\AssemblyInfo.cs">
|
||||||
|
<SubType>Code</SubType>
|
||||||
|
</Compile>
|
||||||
|
<Compile Include="Properties\Resources.Designer.cs">
|
||||||
|
<AutoGen>True</AutoGen>
|
||||||
|
<DesignTime>True</DesignTime>
|
||||||
|
<DependentUpon>Resources.resx</DependentUpon>
|
||||||
|
</Compile>
|
||||||
|
<Compile Include="Properties\Settings.Designer.cs">
|
||||||
|
<AutoGen>True</AutoGen>
|
||||||
|
<DependentUpon>Settings.settings</DependentUpon>
|
||||||
|
<DesignTimeSharedInput>True</DesignTimeSharedInput>
|
||||||
|
</Compile>
|
||||||
|
<EmbeddedResource Include="Properties\Resources.resx">
|
||||||
|
<Generator>ResXFileCodeGenerator</Generator>
|
||||||
|
<LastGenOutput>Resources.Designer.cs</LastGenOutput>
|
||||||
|
</EmbeddedResource>
|
||||||
|
<None Include="app.config" />
|
||||||
|
<None Include="packages.config" />
|
||||||
|
<None Include="Properties\Settings.settings">
|
||||||
|
<Generator>SettingsSingleFileGenerator</Generator>
|
||||||
|
<LastGenOutput>Settings.Designer.cs</LastGenOutput>
|
||||||
|
</None>
|
||||||
|
<AppDesigner Include="Properties\" />
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<WCFMetadata Include="Service References\" />
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup />
|
||||||
|
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
||||||
|
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
|
||||||
|
Other similar extension points exist, see Microsoft.Common.targets.
|
||||||
|
<Target Name="BeforeBuild">
|
||||||
|
</Target>
|
||||||
|
<Target Name="AfterBuild">
|
||||||
|
</Target>
|
||||||
|
-->
|
||||||
|
</Project>
|
||||||
12
Concilium/Concilium.csproj.user
Normal file
12
Concilium/Concilium.csproj.user
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||||
|
<PropertyGroup>
|
||||||
|
<ProjectView>ProjectFiles</ProjectView>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|x86'">
|
||||||
|
<EnableUnmanagedDebugging>true</EnableUnmanagedDebugging>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|AnyCPU'">
|
||||||
|
<EnableUnmanagedDebugging>false</EnableUnmanagedDebugging>
|
||||||
|
</PropertyGroup>
|
||||||
|
</Project>
|
||||||
55
Concilium/Helpers/CmdLineToArgvW.cs
Normal file
55
Concilium/Helpers/CmdLineToArgvW.cs
Normal file
@@ -0,0 +1,55 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.ComponentModel;
|
||||||
|
using System.Runtime.InteropServices;
|
||||||
|
|
||||||
|
namespace Concilium.Helpers
|
||||||
|
{
|
||||||
|
public static class CmdLineToArgvW
|
||||||
|
{
|
||||||
|
// The previous examples on this page used incorrect
|
||||||
|
// pointer logic and were removed.
|
||||||
|
|
||||||
|
public static string[] SplitArgs(string unsplitArgumentLine)
|
||||||
|
{
|
||||||
|
int numberOfArgs;
|
||||||
|
IntPtr ptrToSplitArgs;
|
||||||
|
string[] splitArgs;
|
||||||
|
|
||||||
|
ptrToSplitArgs = CommandLineToArgvW(unsplitArgumentLine, out numberOfArgs);
|
||||||
|
|
||||||
|
// CommandLineToArgvW returns NULL upon failure.
|
||||||
|
if (ptrToSplitArgs == IntPtr.Zero)
|
||||||
|
throw new ArgumentException("Unable to split argument.", new Win32Exception());
|
||||||
|
|
||||||
|
// Make sure the memory ptrToSplitArgs to is freed, even upon failure.
|
||||||
|
try
|
||||||
|
{
|
||||||
|
splitArgs = new string[numberOfArgs];
|
||||||
|
|
||||||
|
// ptrToSplitArgs is an array of pointers to null terminated Unicode strings.
|
||||||
|
// Copy each of these strings into our split argument array.
|
||||||
|
for (int i = 0; i < numberOfArgs; i++)
|
||||||
|
splitArgs[i] = Marshal.PtrToStringUni(
|
||||||
|
Marshal.ReadIntPtr(ptrToSplitArgs, i * IntPtr.Size));
|
||||||
|
|
||||||
|
return splitArgs;
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
// Free memory obtained by CommandLineToArgW.
|
||||||
|
LocalFree(ptrToSplitArgs);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[DllImport("shell32.dll", SetLastError = true)]
|
||||||
|
static extern IntPtr CommandLineToArgvW(
|
||||||
|
[MarshalAs(UnmanagedType.LPWStr)] string lpCmdLine,
|
||||||
|
out int pNumArgs);
|
||||||
|
|
||||||
|
[DllImport("kernel32.dll")]
|
||||||
|
static extern IntPtr LocalFree(IntPtr hMem);
|
||||||
|
}
|
||||||
|
}
|
||||||
29
Concilium/Helpers/ConsoleHelpers.cs
Normal file
29
Concilium/Helpers/ConsoleHelpers.cs
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Runtime.InteropServices;
|
||||||
|
|
||||||
|
namespace Concilium.Helpers
|
||||||
|
{
|
||||||
|
// A delegate type to be used as the handler routine
|
||||||
|
// for SetConsoleCtrlHandler.
|
||||||
|
public delegate bool HandlerRoutine(CtrlTypes CtrlType);
|
||||||
|
|
||||||
|
// An enumerated type for the control messages
|
||||||
|
// sent to the handler routine.
|
||||||
|
public enum CtrlTypes
|
||||||
|
{
|
||||||
|
CTRL_C_EVENT = 0,
|
||||||
|
CTRL_BREAK_EVENT,
|
||||||
|
CTRL_CLOSE_EVENT,
|
||||||
|
CTRL_LOGOFF_EVENT = 5,
|
||||||
|
CTRL_SHUTDOWN_EVENT
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class ConsoleHelpers
|
||||||
|
{
|
||||||
|
[DllImport("Kernel32")]
|
||||||
|
public static extern bool SetConsoleCtrlHandler(HandlerRoutine Handler, bool Add);
|
||||||
|
}
|
||||||
|
}
|
||||||
24
Concilium/Helpers/ListExtensions.cs
Normal file
24
Concilium/Helpers/ListExtensions.cs
Normal file
@@ -0,0 +1,24 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
|
||||||
|
namespace Concilium.Helpers
|
||||||
|
{
|
||||||
|
public static class ListExtensions
|
||||||
|
{
|
||||||
|
public static void Shuffle<T>(this IList<T> list)
|
||||||
|
{
|
||||||
|
Random rng = new Random();
|
||||||
|
int n = list.Count;
|
||||||
|
while (n > 1)
|
||||||
|
{
|
||||||
|
n--;
|
||||||
|
int k = rng.Next(n + 1);
|
||||||
|
T value = list[k];
|
||||||
|
list[k] = list[n];
|
||||||
|
list[n] = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
18
Concilium/Helpers/Log.cs
Normal file
18
Concilium/Helpers/Log.cs
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
using System.IO;
|
||||||
|
using System.Collections;
|
||||||
|
using log4net;
|
||||||
|
|
||||||
|
namespace Concilium.Helpers
|
||||||
|
{
|
||||||
|
internal class Log
|
||||||
|
{
|
||||||
|
private Log()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public static ILog Get()
|
||||||
|
{
|
||||||
|
return LogManager.GetLogger("CONCILIUM");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
28
Concilium/Helpers/StringExtensions.cs
Normal file
28
Concilium/Helpers/StringExtensions.cs
Normal file
@@ -0,0 +1,28 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Text.RegularExpressions;
|
||||||
|
|
||||||
|
namespace Concilium.Helpers
|
||||||
|
{
|
||||||
|
public static class StringExtensions
|
||||||
|
{
|
||||||
|
public static List<string> ReverseFormat(this string str, string template)
|
||||||
|
{
|
||||||
|
string pattern = "^" + Regex.Replace(template, @"\{[0-9]+\}", "(.*?)") + "$";
|
||||||
|
|
||||||
|
Regex r = new Regex(pattern);
|
||||||
|
Match m = r.Match(str);
|
||||||
|
|
||||||
|
List<string> ret = new List<string>();
|
||||||
|
|
||||||
|
for (int i = 1; i < m.Groups.Count; i++)
|
||||||
|
{
|
||||||
|
ret.Add(m.Groups[i].Value);
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
BIN
Concilium/Newtonsoft.Json.dll
Normal file
BIN
Concilium/Newtonsoft.Json.dll
Normal file
Binary file not shown.
BIN
Concilium/Newtonsoft.Json.pdb
Normal file
BIN
Concilium/Newtonsoft.Json.pdb
Normal file
Binary file not shown.
7631
Concilium/Newtonsoft.Json.xml
Normal file
7631
Concilium/Newtonsoft.Json.xml
Normal file
File diff suppressed because it is too large
Load Diff
BIN
Concilium/PasteHtml.dll
Normal file
BIN
Concilium/PasteHtml.dll
Normal file
Binary file not shown.
BIN
Concilium/PasteHtml.pdb
Normal file
BIN
Concilium/PasteHtml.pdb
Normal file
Binary file not shown.
57
Concilium/Properties/AssemblyInfo.cs
Normal file
57
Concilium/Properties/AssemblyInfo.cs
Normal file
@@ -0,0 +1,57 @@
|
|||||||
|
#define LOG4NET
|
||||||
|
|
||||||
|
using System.Reflection;
|
||||||
|
using System.Resources;
|
||||||
|
using System.Runtime.CompilerServices;
|
||||||
|
using System.Runtime.InteropServices;
|
||||||
|
using System.Windows;
|
||||||
|
|
||||||
|
// General Information about an assembly is controlled through the following
|
||||||
|
// set of attributes. Change these attribute values to modify the information
|
||||||
|
// associated with an assembly.
|
||||||
|
[assembly: AssemblyTitle("Concilium")]
|
||||||
|
[assembly: AssemblyDescription("")]
|
||||||
|
[assembly: AssemblyConfiguration("")]
|
||||||
|
[assembly: AssemblyCompany("")]
|
||||||
|
[assembly: AssemblyProduct("Concilium")]
|
||||||
|
[assembly: AssemblyCopyright("Copyright © 2012")]
|
||||||
|
[assembly: AssemblyTrademark("")]
|
||||||
|
[assembly: AssemblyCulture("")]
|
||||||
|
|
||||||
|
// Setting ComVisible to false makes the types in this assembly not visible
|
||||||
|
// to COM components. If you need to access a type in this assembly from
|
||||||
|
// COM, set the ComVisible attribute to true on that type.
|
||||||
|
[assembly: ComVisible(false)]
|
||||||
|
|
||||||
|
//In order to begin building localizable applications, set
|
||||||
|
//<UICulture>CultureYouAreCodingWith</UICulture> in your .csproj file
|
||||||
|
//inside a <PropertyGroup>. For example, if you are using US english
|
||||||
|
//in your source files, set the <UICulture> to en-US. Then uncomment
|
||||||
|
//the NeutralResourceLanguage attribute below. Update the "en-US" in
|
||||||
|
//the line below to match the UICulture setting in the project file.
|
||||||
|
|
||||||
|
//[assembly: NeutralResourcesLanguage("en-US", UltimateResourceFallbackLocation.Satellite)]
|
||||||
|
|
||||||
|
|
||||||
|
[assembly: ThemeInfo(
|
||||||
|
ResourceDictionaryLocation.None, //where theme specific resource dictionaries are located
|
||||||
|
//(used if a resource is not found in the page,
|
||||||
|
// or application resource dictionaries)
|
||||||
|
ResourceDictionaryLocation.SourceAssembly //where the generic resource dictionary is located
|
||||||
|
//(used if a resource is not found in the page,
|
||||||
|
// app, or any theme specific resource dictionaries)
|
||||||
|
)]
|
||||||
|
|
||||||
|
|
||||||
|
// Version information for an assembly consists of the following four values:
|
||||||
|
//
|
||||||
|
// Major Version
|
||||||
|
// Minor Version
|
||||||
|
// Build Number
|
||||||
|
// Revision
|
||||||
|
//
|
||||||
|
// You can specify all the values or you can default the Build and Revision Numbers
|
||||||
|
// by using the '*' as shown below:
|
||||||
|
// [assembly: AssemblyVersion("1.0.*")]
|
||||||
|
[assembly: AssemblyVersion("1.0.0.0")]
|
||||||
|
[assembly: AssemblyFileVersion("1.0.0.0")]
|
||||||
63
Concilium/Properties/Resources.Designer.cs
generated
Normal file
63
Concilium/Properties/Resources.Designer.cs
generated
Normal file
@@ -0,0 +1,63 @@
|
|||||||
|
//------------------------------------------------------------------------------
|
||||||
|
// <auto-generated>
|
||||||
|
// This code was generated by a tool.
|
||||||
|
// Runtime Version:4.0.30319.269
|
||||||
|
//
|
||||||
|
// Changes to this file may cause incorrect behavior and will be lost if
|
||||||
|
// the code is regenerated.
|
||||||
|
// </auto-generated>
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
namespace Concilium.Properties {
|
||||||
|
using System;
|
||||||
|
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// A strongly-typed resource class, for looking up localized strings, etc.
|
||||||
|
/// </summary>
|
||||||
|
// This class was auto-generated by the StronglyTypedResourceBuilder
|
||||||
|
// class via a tool like ResGen or Visual Studio.
|
||||||
|
// To add or remove a member, edit your .ResX file then rerun ResGen
|
||||||
|
// with the /str option, or rebuild your VS project.
|
||||||
|
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")]
|
||||||
|
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
|
||||||
|
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
|
||||||
|
internal class Resources {
|
||||||
|
|
||||||
|
private static global::System.Resources.ResourceManager resourceMan;
|
||||||
|
|
||||||
|
private static global::System.Globalization.CultureInfo resourceCulture;
|
||||||
|
|
||||||
|
[global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
|
||||||
|
internal Resources() {
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Returns the cached ResourceManager instance used by this class.
|
||||||
|
/// </summary>
|
||||||
|
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
|
||||||
|
internal static global::System.Resources.ResourceManager ResourceManager {
|
||||||
|
get {
|
||||||
|
if (object.ReferenceEquals(resourceMan, null)) {
|
||||||
|
global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("Concilium.Properties.Resources", typeof(Resources).Assembly);
|
||||||
|
resourceMan = temp;
|
||||||
|
}
|
||||||
|
return resourceMan;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Overrides the current thread's CurrentUICulture property for all
|
||||||
|
/// resource lookups using this strongly typed resource class.
|
||||||
|
/// </summary>
|
||||||
|
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
|
||||||
|
internal static global::System.Globalization.CultureInfo Culture {
|
||||||
|
get {
|
||||||
|
return resourceCulture;
|
||||||
|
}
|
||||||
|
set {
|
||||||
|
resourceCulture = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
117
Concilium/Properties/Resources.resx
Normal file
117
Concilium/Properties/Resources.resx
Normal file
@@ -0,0 +1,117 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<root>
|
||||||
|
<!--
|
||||||
|
Microsoft ResX Schema
|
||||||
|
|
||||||
|
Version 2.0
|
||||||
|
|
||||||
|
The primary goals of this format is to allow a simple XML format
|
||||||
|
that is mostly human readable. The generation and parsing of the
|
||||||
|
various data types are done through the TypeConverter classes
|
||||||
|
associated with the data types.
|
||||||
|
|
||||||
|
Example:
|
||||||
|
|
||||||
|
... ado.net/XML headers & schema ...
|
||||||
|
<resheader name="resmimetype">text/microsoft-resx</resheader>
|
||||||
|
<resheader name="version">2.0</resheader>
|
||||||
|
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
|
||||||
|
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
|
||||||
|
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
|
||||||
|
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
|
||||||
|
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
|
||||||
|
<value>[base64 mime encoded serialized .NET Framework object]</value>
|
||||||
|
</data>
|
||||||
|
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
||||||
|
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
|
||||||
|
<comment>This is a comment</comment>
|
||||||
|
</data>
|
||||||
|
|
||||||
|
There are any number of "resheader" rows that contain simple
|
||||||
|
name/value pairs.
|
||||||
|
|
||||||
|
Each data row contains a name, and value. The row also contains a
|
||||||
|
type or mimetype. Type corresponds to a .NET class that support
|
||||||
|
text/value conversion through the TypeConverter architecture.
|
||||||
|
Classes that don't support this are serialized and stored with the
|
||||||
|
mimetype set.
|
||||||
|
|
||||||
|
The mimetype is used for serialized objects, and tells the
|
||||||
|
ResXResourceReader how to depersist the object. This is currently not
|
||||||
|
extensible. For a given mimetype the value must be set accordingly:
|
||||||
|
|
||||||
|
Note - application/x-microsoft.net.object.binary.base64 is the format
|
||||||
|
that the ResXResourceWriter will generate, however the reader can
|
||||||
|
read any of the formats listed below.
|
||||||
|
|
||||||
|
mimetype: application/x-microsoft.net.object.binary.base64
|
||||||
|
value : The object must be serialized with
|
||||||
|
: System.Serialization.Formatters.Binary.BinaryFormatter
|
||||||
|
: and then encoded with base64 encoding.
|
||||||
|
|
||||||
|
mimetype: application/x-microsoft.net.object.soap.base64
|
||||||
|
value : The object must be serialized with
|
||||||
|
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
|
||||||
|
: and then encoded with base64 encoding.
|
||||||
|
|
||||||
|
mimetype: application/x-microsoft.net.object.bytearray.base64
|
||||||
|
value : The object must be serialized into a byte array
|
||||||
|
: using a System.ComponentModel.TypeConverter
|
||||||
|
: and then encoded with base64 encoding.
|
||||||
|
-->
|
||||||
|
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
|
||||||
|
<xsd:element name="root" msdata:IsDataSet="true">
|
||||||
|
<xsd:complexType>
|
||||||
|
<xsd:choice maxOccurs="unbounded">
|
||||||
|
<xsd:element name="metadata">
|
||||||
|
<xsd:complexType>
|
||||||
|
<xsd:sequence>
|
||||||
|
<xsd:element name="value" type="xsd:string" minOccurs="0" />
|
||||||
|
</xsd:sequence>
|
||||||
|
<xsd:attribute name="name" type="xsd:string" />
|
||||||
|
<xsd:attribute name="type" type="xsd:string" />
|
||||||
|
<xsd:attribute name="mimetype" type="xsd:string" />
|
||||||
|
</xsd:complexType>
|
||||||
|
</xsd:element>
|
||||||
|
<xsd:element name="assembly">
|
||||||
|
<xsd:complexType>
|
||||||
|
<xsd:attribute name="alias" type="xsd:string" />
|
||||||
|
<xsd:attribute name="name" type="xsd:string" />
|
||||||
|
</xsd:complexType>
|
||||||
|
</xsd:element>
|
||||||
|
<xsd:element name="data">
|
||||||
|
<xsd:complexType>
|
||||||
|
<xsd:sequence>
|
||||||
|
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||||
|
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
|
||||||
|
</xsd:sequence>
|
||||||
|
<xsd:attribute name="name" type="xsd:string" msdata:Ordinal="1" />
|
||||||
|
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
|
||||||
|
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
|
||||||
|
</xsd:complexType>
|
||||||
|
</xsd:element>
|
||||||
|
<xsd:element name="resheader">
|
||||||
|
<xsd:complexType>
|
||||||
|
<xsd:sequence>
|
||||||
|
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||||
|
</xsd:sequence>
|
||||||
|
<xsd:attribute name="name" type="xsd:string" use="required" />
|
||||||
|
</xsd:complexType>
|
||||||
|
</xsd:element>
|
||||||
|
</xsd:choice>
|
||||||
|
</xsd:complexType>
|
||||||
|
</xsd:element>
|
||||||
|
</xsd:schema>
|
||||||
|
<resheader name="resmimetype">
|
||||||
|
<value>text/microsoft-resx</value>
|
||||||
|
</resheader>
|
||||||
|
<resheader name="version">
|
||||||
|
<value>2.0</value>
|
||||||
|
</resheader>
|
||||||
|
<resheader name="reader">
|
||||||
|
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||||
|
</resheader>
|
||||||
|
<resheader name="writer">
|
||||||
|
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||||
|
</resheader>
|
||||||
|
</root>
|
||||||
26
Concilium/Properties/Settings.Designer.cs
generated
Normal file
26
Concilium/Properties/Settings.Designer.cs
generated
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
//------------------------------------------------------------------------------
|
||||||
|
// <auto-generated>
|
||||||
|
// This code was generated by a tool.
|
||||||
|
// Runtime Version:4.0.30319.269
|
||||||
|
//
|
||||||
|
// Changes to this file may cause incorrect behavior and will be lost if
|
||||||
|
// the code is regenerated.
|
||||||
|
// </auto-generated>
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
namespace Concilium.Properties {
|
||||||
|
|
||||||
|
|
||||||
|
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
|
||||||
|
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "10.0.0.0")]
|
||||||
|
internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase {
|
||||||
|
|
||||||
|
private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings())));
|
||||||
|
|
||||||
|
public static Settings Default {
|
||||||
|
get {
|
||||||
|
return defaultInstance;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
7
Concilium/Properties/Settings.settings
Normal file
7
Concilium/Properties/Settings.settings
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
<?xml version='1.0' encoding='utf-8'?>
|
||||||
|
<SettingsFile xmlns="uri:settings" CurrentProfile="(Default)">
|
||||||
|
<Profiles>
|
||||||
|
<Profile Name="(Default)" />
|
||||||
|
</Profiles>
|
||||||
|
<Settings />
|
||||||
|
</SettingsFile>
|
||||||
BIN
Concilium/SmartIrc4Net.dll
Normal file
BIN
Concilium/SmartIrc4Net.dll
Normal file
Binary file not shown.
BIN
Concilium/SmartIrc4Net.pdb
Normal file
BIN
Concilium/SmartIrc4Net.pdb
Normal file
Binary file not shown.
8
Concilium/app.config
Normal file
8
Concilium/app.config
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
<?xml version="1.0"?>
|
||||||
|
<configuration>
|
||||||
|
<system.net>
|
||||||
|
<settings>
|
||||||
|
<httpWebRequest useUnsafeHeaderParsing="true" />
|
||||||
|
</settings>
|
||||||
|
</system.net>
|
||||||
|
<startup><supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.0"/></startup></configuration>
|
||||||
BIN
Concilium/log4net.dll
Normal file
BIN
Concilium/log4net.dll
Normal file
Binary file not shown.
BIN
Concilium/log4net.pdb
Normal file
BIN
Concilium/log4net.pdb
Normal file
Binary file not shown.
30192
Concilium/log4net.xml
Normal file
30192
Concilium/log4net.xml
Normal file
File diff suppressed because it is too large
Load Diff
5
Concilium/packages.config
Normal file
5
Concilium/packages.config
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<packages>
|
||||||
|
<package id="IrcDotNet" version="0.5.0" targetFramework="net40" />
|
||||||
|
<package id="NetIrc2" version="1.0.0.0" targetFramework="net40" />
|
||||||
|
</packages>
|
||||||
BIN
packages/IrcDotNet.0.5.0/IrcDotNet.0.5.0.nupkg
vendored
Normal file
BIN
packages/IrcDotNet.0.5.0/IrcDotNet.0.5.0.nupkg
vendored
Normal file
Binary file not shown.
21
packages/IrcDotNet.0.5.0/LICENSE.md
vendored
Normal file
21
packages/IrcDotNet.0.5.0/LICENSE.md
vendored
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
# The MIT License
|
||||||
|
|
||||||
|
*Copyright (c) 2011-2015 Alex Regueiro*
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
in the Software without restriction, including without limitation the rights
|
||||||
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
copies of the Software, and to permit persons to whom the Software is
|
||||||
|
furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in
|
||||||
|
all copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
|
THE SOFTWARE.
|
||||||
BIN
packages/IrcDotNet.0.5.0/lib/net40/IrcDotNet.dll
vendored
Normal file
BIN
packages/IrcDotNet.0.5.0/lib/net40/IrcDotNet.dll
vendored
Normal file
Binary file not shown.
3672
packages/IrcDotNet.0.5.0/lib/net40/IrcDotNet.xml
vendored
Normal file
3672
packages/IrcDotNet.0.5.0/lib/net40/IrcDotNet.xml
vendored
Normal file
File diff suppressed because it is too large
Load Diff
BIN
packages/IrcDotNet.0.5.0/lib/net45/IrcDotNet.dll
vendored
Normal file
BIN
packages/IrcDotNet.0.5.0/lib/net45/IrcDotNet.dll
vendored
Normal file
Binary file not shown.
3672
packages/IrcDotNet.0.5.0/lib/net45/IrcDotNet.xml
vendored
Normal file
3672
packages/IrcDotNet.0.5.0/lib/net45/IrcDotNet.xml
vendored
Normal file
File diff suppressed because it is too large
Load Diff
BIN
packages/NetIrc2.1.0.0.0/NetIrc2.1.0.0.0.nupkg
vendored
Normal file
BIN
packages/NetIrc2.1.0.0.0/NetIrc2.1.0.0.0.nupkg
vendored
Normal file
Binary file not shown.
1467
packages/NetIrc2.1.0.0.0/lib/NetIrc2.XML
vendored
Normal file
1467
packages/NetIrc2.1.0.0.0/lib/NetIrc2.XML
vendored
Normal file
File diff suppressed because it is too large
Load Diff
BIN
packages/NetIrc2.1.0.0.0/lib/NetIrc2.chm
vendored
Normal file
BIN
packages/NetIrc2.1.0.0.0/lib/NetIrc2.chm
vendored
Normal file
Binary file not shown.
BIN
packages/NetIrc2.1.0.0.0/lib/NetIrc2.dll
vendored
Normal file
BIN
packages/NetIrc2.1.0.0.0/lib/NetIrc2.dll
vendored
Normal file
Binary file not shown.
BIN
packages/NetIrc2.1.0.0.0/lib/NetIrc2.pdb
vendored
Normal file
BIN
packages/NetIrc2.1.0.0.0/lib/NetIrc2.pdb
vendored
Normal file
Binary file not shown.
4
packages/repositories.config
Normal file
4
packages/repositories.config
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<repositories>
|
||||||
|
<repository path="..\Concilium\packages.config" />
|
||||||
|
</repositories>
|
||||||
Reference in New Issue
Block a user