/// Copyright 2010 - 2013, Blizzardo1 using System; using System.Collections.Generic; using System.Collections.ObjectModel; using System.Diagnostics; using System.IO; using System.Linq; using System.Threading; using System.Xml.Serialization; using Meebey.SmartIrc4net; using ErrorEventArgs = Meebey.SmartIrc4net.ErrorEventArgs; using App = System.Windows.Forms; namespace Blizzeta5 { public enum Permissions { Owner = 0, Administrator = 1, Operator = 2, User = 3, Guest = 4 } [XmlType("Server")] public class Server { #region File Paths public static readonly string StartupPath = Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().Location); public static readonly string DriversPath = string.Format("{0}\\Drivers", StartupPath); public static readonly string CmdPath = string.Format("{0}\\Modules", StartupPath); public static readonly string LogsPath = string.Format("{0}\\Logs", StartupPath); #endregion PluginLoader RuntimeDrivers; public Dictionary OpenChannels = new Dictionary(); //public static List ThreadTracker = new List(); public List Targets = new List(); private string _nick; private string _nspass, _owner; private int _port; private string _realname; private string _server; private string _username; private string _dbgchan; public Server() { Self = this; RuntimeDrivers = new PluginLoader(DriversPath, "Core"); } #region Properties //[XmlIgnore] public readonly IrcClient Client = new IrcClient(); private bool _isLogging; //[XmlAttribute("server")] public string IrcServer { get { return _server; } set { _server = value; } } //[XmlAttribute("nick")] public string Nick { get { return _nick; } set { _nick = value; } } //[XmlAttribute("realname")] public string Realname { get { return _realname; } set { _realname = value; } } //[XmlAttribute("port")] public int Port { get { return _port; } set { _port = value; } } //[XmlAttribute("nickservpass")] public string NsPass { get { return _nspass; } set { _nspass = value; } } //[XmlAttribute("username")] public string UserName { get { return _username; } set { _username = value; } } //[XmlAttribute("owner")] public string Owner { get { return _owner; } set { _owner = value; } } //[XmlAttribute("ignoreajoin")] public bool IgnoreAjoin { get; set; } //[XmlIgnore] public bool IgnoreChannel { get; set; } //[XmlAttribute("IsLogging")] public bool IsLogging { get { return _isLogging; } set { _isLogging = value; } } //[XmlAttribute("debugchan")] public string DebugChannel { get { return _dbgchan; } set { _dbgchan = value; } } //[XmlIgnore] public static Server Self { get; set; } public Blizzeta[] Channels { get; set; } #endregion private Blizzeta_Gui.ThreadTracker tt = new Blizzeta_Gui.ThreadTracker(); public static bool IsNull(object o) { return (o == null); } public struct BanList { public string Channel; public string Mask; } public List BannedList = new List(); public void Setup(string server, int port, string nick, string username, string realname, string nickServPassword, string owner, string[] channels, string[] keys) { _server = server; _port = port; _nick = nick; _realname = realname; _username = username; _nspass = nickServPassword; _owner = owner; Channels = new Blizzeta[channels.Length]; for (int i = 0; i < channels.Length; i++) Channels[i] = new Blizzeta(channels[i]) { Key = keys[i] }; Settings.servers.Add(this); //Settings._servers = new Server[4]; //Settings._servers[0] = this; //Settings.SerializeDataFile(Settings._servers); } public void TransportChannels() { foreach (var chan in Channels) { OpenChannels.Add(chan.Channel, chan); } } [STAThread()] public void Begin() { AddHandlers(); Client.SendDelay = 200; Client.AutoRetry = true; Client.ActiveChannelSyncing = true; IAsyncResult back = null; Action a = new Action(delegate { App.Application.Run(tt); }); if (!IsNull(tt)) { AsyncCallback call = new AsyncCallback((ar) => { }); back = a.BeginInvoke(call, null); } pc("Connecting to {0}...", ConsoleColor.Yellow, _server); Client.Connect(_server, _port); Client.Login(_nick, _realname, 8, _username, _nspass); Client.RfcMode(_nick, "+B"); TransportChannels(); foreach (var b in OpenChannels) { b.Value.Server = this; SendPrivmsg(_owner, string.Format("Joining {0}", b.Key)); Join(b.Key, b.Value.ChannelPassword); } SendPublicMessage(DebugChannel, string.Format("Using {0} as Debugging Channel", DebugChannel)); // Loop Client.Listen(); // End Loop pc("Disconnected!", ConsoleColor.DarkGreen); a.EndInvoke(back); } public Blizzeta GetChannel(string channel) { foreach (var chan in OpenChannels.Where(chan => chan.Key == channel)) { return chan.Value; } return new Blizzeta(); } public void Join(string channel, string key) { var b = new Blizzeta(channel) {ChannelPassword = key, Server = this}; SendPrivmsg(_owner, string.Format("Joining {0}", b.Channel)); Client.RfcJoin(b.Channel, b.ChannelPassword); if (!OpenChannels.ContainsKey(b.Channel)) OpenChannels.Add(b.Channel, b); } public void Part(string channel, string reason) { if (OpenChannels.ContainsKey(channel)) OpenChannels.Remove(channel); Client.RfcPart(channel, reason); } public string HidePassword(string password) { const char passChar = '*'; return password.Aggregate(string.Empty, (current, c) => current + passChar); } public void SetLogging(bool plug, string nick) { _isLogging = plug; Client.RfcPrivmsg(nick, string.Format("Logging is now {0}", _isLogging ? "enabled" : "disabled")); } private void AddHandlers() { Client.OnAutoConnectError += client_OnAutoConnectError; Client.OnAway += client_OnAway; Client.OnConnected += client_OnConnected; Client.OnConnecting += client_OnConnecting; Client.OnConnectionError += client_OnConnectionError; Client.OnCtcpReply += client_OnCtcpReply; Client.OnCtcpRequest += client_OnCtcpRequest; Client.OnDisconnected += client_OnDisconnected; Client.OnDisconnecting += client_OnDisconnecting; Client.OnError += client_OnError; Client.OnErrorMessage += client_OnErrorMessage; Client.OnInvite += client_OnInvite; Client.OnList += client_OnList; Client.OnMotd += client_OnMotd; Client.OnNames += client_OnNames; Client.OnNickChange += client_OnNickChange; Client.OnNowAway += client_OnNowAway; Client.OnPing += client_OnPing; Client.OnPong += client_OnPong; Client.OnQueryAction += client_OnQueryAction; Client.OnQueryMessage += client_OnQueryMessage; Client.OnQueryNotice += client_OnQueryNotice; Client.OnReadLine += client_OnReadLine; Client.OnRegistered += client_OnRegistered; Client.OnUnAway += client_OnUnAway; Client.OnWho += client_OnWho; Client.OnWriteLine += client_OnWriteLine; Client.OnBan += client_OnBan; Client.OnChannelAction += client_OnChannelAction; Client.OnChannelActiveSynced += client_OnChannelActiveSynced; Client.OnChannelMessage += client_OnChannelMessage; Client.OnChannelModeChange += client_OnChannelModeChange; Client.OnChannelNotice += client_OnChannelNotice; Client.OnChannelPassiveSynced += client_OnChannelPassiveSynced; Client.OnDehalfop += client_OnDehalfop; Client.OnDeop += client_OnDeop; Client.OnDevoice += client_OnDevoice; Client.OnHalfop += client_OnHalfop; Client.OnJoin += client_OnJoin; Client.OnKick += client_OnKick; Client.OnModeChange += client_OnModeChange; Client.OnOp += client_OnOp; Client.OnPart += client_OnPart; Client.OnQuit += client_OnQuit; Client.OnRawMessage += client_OnRawMessage; Client.OnTopic += client_OnTopic; Client.OnTopicChange += client_OnTopicChange; Client.OnUnban += client_OnUnban; Client.OnUserModeChange += client_OnUserModeChange; Client.OnVoice += client_OnVoice; } public static void Raw(string rawmsg) { Debug.WriteLine(rawmsg); } public void Log(string nick, string message) { string format = string.Format("[{0:HH:mm:ss}] <{1}> {2}\r\n", DateTime.Now, nick, message); Debug.WriteLine(format); File.AppendAllText(string.Format("{0}\\log{1:MMddyyyy}.l", Environment.CurrentDirectory, DateTime.Now), format); } public void AddTarget(string name) { string[] contents = ReadFile("targets.zz"); var writer = new StreamWriter("targets.zz"); foreach (string s in contents) { writer.WriteLine(s); } writer.WriteLine(name); writer.Flush(); writer.Close(); } public void RemoveTarget(string name) { var writer = new StreamWriter("targets.zz"); string[] reg = ReadFile("targets.zz"); var ls = new List(); ls.AddRange(reg); int target = ls.BinarySearch(name); ls.RemoveAt(target); foreach (string s in ls.ToArray()) { writer.WriteLine(s); } writer.Flush(); writer.Close(); } public string[] ReadFile(string filename) { return File.ReadAllLines(filename); } public void OpenTargets() { // Since we assume our Target Repository is empty, we need to add what we got. if (!File.Exists("targets.zz")) { File.Create("targets.zz"); } string[] zTargets = ReadFile("targets.zz"); foreach (string s in zTargets) { Client.RfcPrivmsg(_owner, s); } } public void ReloadDriver() { if (RuntimeDrivers.Reload()) pc("Reloaded Runtime Drivers!", ConsoleColor.Green); else pc("Runtime Drivers threw an error reloading!", ConsoleColor.Red); } /// /// Print with Formattable ConsoleColor /// /// The Format as {#} /// Your Color to use /// The Parameters specified to your Format public static void pc(string format, ConsoleColor color, params object[] parameters) { Console.ForegroundColor = color; //Console.SetCursorPosition(0, Console.WindowWidth - 1); Console.WriteLine(format, parameters); Console.ResetColor(); } /// /// Print Command With Parsable Settings /// /// The Command Style Set /// The Delimeter to begin the Command /// The Delimeter to end the Command /// The Channel to read from /// public void pcmd(string[] command, char beginDelimeter, char endDelimeter, string channel, string target, bool Private = false) { string c = command[0]; string e = command[command.Length - 1]; if (c.StartsWith(beginDelimeter.ToString()) && e.EndsWith(endDelimeter.ToString())) { string str = string.Empty; var Parameters = new List(); for (int i = 1; i < command.Length; i++) { string s = command[i]; Parameters.Add(s.Trim(beginDelimeter, endDelimeter)); } string cmd = (command[0]).Trim(beginDelimeter, endDelimeter); Run(cmd, Parameters.ToArray(), channel, target, false, Private); } } public void pipe(string[] command, string channel, string target) { string c = command[0]; List loo = new List(); for (int i = 1; i < command.Length; i++) { loo.Add(command[i]); } string cmd = c; if (cmd != null) Run(cmd, loo.ToArray(), channel, target, true); else SendPublicMessage(channel, string.Format("Command {0} has not been found!", c)); } public void Driver(string command, object sender, object eventargs) { try { var sc = new ScriptContext(); var t = (new Thread(new ThreadStart(delegate { sc.server = this; var noMod = new List {sender, eventargs}; sc.Arguments = noMod; if (!(eventargs is EventArgs)) if (eventargs != null) sc.channel = GetChannel(((IrcEventArgs) eventargs).Data.Channel); sc.nick = _owner; try { IProvider provider = RuntimeDrivers.RequestProvider(command); provider.Load(ref sc); } catch (Exception ex) { pc("Error in Driver {0}: {1}", ConsoleColor.Red, command, ex); } })) { Name = command }); if(!IsNull(tt)) tt.AddThread(t); t.Start(); while (t.IsAlive) { } t.Join(); t.Abort(); if(!IsNull(tt)) tt.RemoveThread(t); t = null; } catch (Exception ex) { pc(ex.ToString(), ConsoleColor.Red); GC.Collect(); } } public object Driver(string command, string nick, params object[] args) { try { var sc = new ScriptContext(); var t = (new Thread(new ThreadStart(delegate { sc.server = this; sc.Arguments = args; sc.nick = nick; IProvider provider = RuntimeDrivers.RequestProvider(command); provider.Load(ref sc); //sc.Result = Shell.RunScript(command, sc); })) {Name = command}); if(!IsNull(tt)) tt.AddThread(t); t.Start(); while (t.IsAlive) { Thread.Sleep(1); } t.Join(); t.Abort(); if (!t.IsAlive) { if(!IsNull(tt)) tt.RemoveThread(t); if (sc.Result != null) return sc.Result; } } catch (Exception ex) { pc(ex.ToString(), ConsoleColor.Red); } return null; } public void Run(string command, object[] commandSet, string destination, string target, bool pipe = false, bool pm = false) { string args = string.Empty; Guid g = Guid.NewGuid(); var sc = new ScriptContext(); var se = new ScriptEngine(); Thread t = (new Thread(new ThreadStart(delegate { try { sc.server = this; var noMod = new List(); if (commandSet.Length > 0) for (int i = 0; i < commandSet.Length; i++) { // pc("[Argument {0}] {1}", ConsoleColor.Magenta, i, commandSet[i]); args += string.Format("[{0}]; ", commandSet[i]); noMod.Add(commandSet[i]); } //else //pc("[No Arguments]", ConsoleColor.DarkMagenta); sc.channel = GetChannel(destination); sc.nick = target; sc.Arguments = noMod; args = args.TrimEnd(' '); string cmdlet = string.Format("{0}\\{1}.cs", CmdPath, command); var cmdi = se.GetInterface(cmdlet); if (cmdi == null) { pc("cmdi is null!", ConsoleColor.Red); SendPublicMessage(destination, "Command Interface : null. Reset ScriptInterface."); } else { pc("[{0:HH:mm:ss} {1}] {2}", ConsoleColor.Green, DateTime.Now, destination, target); pc("Name: {0} - Help: {1} - Usage: {2} - More: {3} - Version: {4} - Permission: {5}", ConsoleColor.DarkGreen, cmdi.Name, cmdi.Help, cmdi.Usage, cmdi.More, cmdi.Version, cmdi.Permission); if (cmdi.IsPublic) { if (uac.GetPermission(target, this) <= cmdi.Permission) se.Run(cmdlet, ref sc); else SendPrivmsg(target, string.Format("You do not have permission to execute the command {0}", command)); } else if (pipe) { if (uac.GetPermission(target, this) <= cmdi.Permission) se.Run(cmdlet, ref sc); } else if (pm) { if (uac.GetPermission(target, this) <= cmdi.Permission) se.Run(cmdlet, ref sc); else SendPrivmsg(target, string.Format("You do not have permission to execute the command {0}", command)); } else { SendPublicMessage(destination, string.Format("The command \"{0}\" can only be used privately!", command)); } } } catch (Exception ex) { pc("{0}", ConsoleColor.Red, ex); SendPublicMessage(_dbgchan, string.Format("{0} tried to do {1} in {2}, but errors happened: {3}", target, command, destination, ex.Message)); return; } finally { SendPublicMessage(_dbgchan, string.Format("Command: {0}; Arguments: [{1}]; Callee: [{2}]; Destination: \"{3}\"; Fingerprint: [{4}]", command, (args.Length > 0 ? args : "{{ null }}"), target, destination, g)); } })) { Name = string.Format("USER_CMD__{0}_{1}_{2}", command, target, g) }); if(!IsNull(tt)) tt.AddThread(t); t.Start(); if (!t.IsAlive) if(!IsNull(tt)) tt.RemoveThread(t); } public void SendErrorToFile(Exception ex, string Nick) { if (!Directory.Exists(LogsPath)) Directory.CreateDirectory(LogsPath); var d = DateTime.Now; var r = d.ToString("yyyyMMddHHmmssfft"); var clientmsg = string.Format("Something has terribly gone wrong. Please report this to {0}! Your new Fingerprint is {1}", _owner, r); var servermsg = string.Format("Something has terribly gone wrong. Gathering UserInfo:\nNick: {0}\nFingerPrint: {1}\nTime Of incident: {2}\nException: {3}", Nick, r, d.ToString("dddd MMMM dd, yyyy :: HH:mm:ss"), ex); SendPrivmsg(Nick, clientmsg); OpenWriteLog(servermsg, string.Format(LogsPath + "\\{0}.blog", r)); } public void OpenWriteLog(string Message, string FileName, params object[] Params) { var w = new StreamWriter(FileName); w.WriteLine(Message, Params); w.Flush(); w.Close(); } public void SendPublicMessage(string Channel, string Message) { Client.SendMessage(SendType.Message, Channel, Message); } public void SendPublicAction(string Channel, string Action) { Client.SendMessage(SendType.Action, Channel, Action); } public void SendNotice(string Whom, string Message) { Client.SendMessage(SendType.Notice, Whom, Message); } public void SendPrivmsg(string Whom, string Message) { Client.SendMessage(SendType.Message, Whom, Message); } #region handlers private void client_OnAway(object sender, AwayEventArgs e) { Driver("OnAway", sender, e); } private void client_OnAutoConnectError(object sender, AutoConnectErrorEventArgs e) { Driver("OnAutoConnectError", sender, e); } private void client_OnCtcpRequest(object sender, CtcpEventArgs e) { Driver("OnCtcpRequest", sender, e); } private void client_OnCtcpReply(object sender, CtcpEventArgs e) { Driver("OnCtcpReply", sender, e); } private void client_OnConnectionError(object sender, EventArgs e) { Driver("OnConnectionError", sender, e); } private void client_OnConnecting(object sender, EventArgs e) { Driver("OnConnecting", sender, e); } private void client_OnConnected(object sender, EventArgs e) { Driver("OnConnected", sender, e); } private void client_OnDisconnecting(object sender, EventArgs e) { Driver("OnDisconnecting", sender, e); } private void client_OnDisconnected(object sender, EventArgs e) { Driver("OnDisconnected", sender, e); } private void client_OnErrorMessage(object sender, IrcEventArgs e) { Driver("OnErrorMessage", sender, e); } private void client_OnError(object sender, ErrorEventArgs e) { Driver("OnError", sender, e); } private void client_OnInvite(object sender, InviteEventArgs e) { Driver("OnInvite", sender, e); } private void client_OnList(object sender, ListEventArgs e) { Driver("OnList", sender, e); } private void client_OnNowAway(object sender, IrcEventArgs e) { Driver("OnNowAway", sender, e); } private void client_OnNickChange(object sender, NickChangeEventArgs e) { Driver("OnNickChange", sender, e); } private void client_OnNames(object sender, NamesEventArgs e) { Driver("OnNames", sender, e); } private void client_OnMotd(object sender, MotdEventArgs e) { Driver("OnMotd", sender, e); } private void client_OnQueryNotice(object sender, IrcEventArgs e) { Driver("OnQueryNotice", sender, e); } private void client_OnQueryMessage(object sender, IrcEventArgs e) { Driver("OnQueryMessage", sender, e); } private void client_OnQueryAction(object sender, ActionEventArgs e) { Driver("OnQueryAction", sender, e); } private void client_OnPong(object sender, PongEventArgs e) { Driver("OnPong", sender, e); } private void client_OnPing(object sender, PingEventArgs e) { Driver("OnPing", sender, e); } private void client_OnRegistered(object sender, EventArgs e) { Driver("OnRegistered", sender, e); } private void client_OnReadLine(object sender, ReadLineEventArgs e) { Driver("OnReadLine", sender, e); } private void client_OnUnAway(object sender, IrcEventArgs e) { Driver("OnUnaway", sender, e); } private void client_OnWho(object sender, WhoEventArgs e) { //driver("onwho", sender, e); var u = new User { Host = e.WhoInfo.Host, Ident = e.WhoInfo.Ident, IsAway = e.WhoInfo.IsAway, IsIrcOp = e.WhoInfo.IsIrcOp, IsRegistered = e.WhoInfo.IsRegistered, Nick = e.WhoInfo.Nick }; try { Blizzeta b = GetChannel(e.WhoInfo.Channel); //Console.WriteLine("==> Adding {0} from {1} to Userlist", u.Nick, b.Name); b.Userlist.Add(e.WhoInfo.Nick, u); //Console.WriteLine("UserList Count {0}", b.Userlist.Count); } catch (Exception) { //pc(ex.Message, ConsoleColor.Red); try { //pc("Creating new Instance for {0}...", ConsoleColor.Cyan, e.WhoInfo.Channel); OpenChannels.Add(e.WhoInfo.Channel, new Blizzeta(e.WhoInfo.Channel)); //pc("Attempting to restore User {0} to List for {1}", ConsoleColor.Green, u.Nick, e.WhoInfo.Channel); GetChannel(e.WhoInfo.Channel).Userlist.Add(e.WhoInfo.Nick, u); } catch (Exception) { //pc(exx.Message, ConsoleColor.Red); } } } private void client_OnWriteLine(object sender, WriteLineEventArgs e) { Driver("OnWriteLine", sender, e); } public void Whois(string name) { Console.WriteLine("Sending WHOIS to Server..."); Client.WriteLine("WHOIS " + name); } private void client_OnVoice(object sender, VoiceEventArgs e) { Driver("OnVoice", sender, e); } private void client_OnUserModeChange(object sender, IrcEventArgs e) { Driver("OnUserModeChange", sender, e); } private void client_OnUnban(object sender, UnbanEventArgs e) { Driver("OnUnban", sender, e); } private void client_OnTopicChange(object sender, TopicChangeEventArgs e) { Driver("OnTopicChange", sender, e); } private void client_OnTopic(object sender, TopicEventArgs e) { Driver("OnTopic", sender, e); } private void client_OnQuit(object sender, QuitEventArgs e) { /*Moved to Blizzeta.cs*/ //Blizzeta b = GetChannel(e.Data.Channel); //try //{ // if (b != null) // b.Userlist.Remove(e.Who); //} //catch (Exception ex) //{ // Console.WriteLine(ex.Message); // SendPublicMessage(e.Data.Channel, ex.Message); //} } private void client_OnPart(object sender, PartEventArgs e) { Driver("OnPart", sender, e); } private void client_OnOp(object sender, OpEventArgs e) { Driver("OnOp", sender, e); } private void client_OnModeChange(object sender, IrcEventArgs e) { Driver("OnModeChange", sender, e); } private void client_OnKick(object sender, KickEventArgs e) { Driver("OnKick", sender, e); } private void client_OnJoin(object sender, JoinEventArgs e) { Driver("OnJoin", sender, e); } private void client_OnHalfop(object sender, HalfopEventArgs e) { Driver("OnHalfOp", sender, e); } private void client_OnDevoice(object sender, DevoiceEventArgs e) { Driver("OnDevoice", sender, e); } private void client_OnDeop(object sender, DeopEventArgs e) { Driver("OnDeop", sender, e); } private void client_OnDehalfop(object sender, DehalfopEventArgs e) { Driver("OnDeHalfop", sender, e); } private void client_OnChannelPassiveSynced(object sender, IrcEventArgs e) { Driver("OnChannelActiveSynced", sender, e); } private void client_OnChannelNotice(object sender, IrcEventArgs e) { Driver("OnChannelNotice", sender, e); } private void client_OnChannelModeChange(object sender, IrcEventArgs e) { Driver("OnChannelModeChange", sender, e); } private void client_OnChannelMessage(object sender, IrcEventArgs e) { Driver("OnChannelMessage", sender, e); } private void client_OnChannelActiveSynced(object sender, IrcEventArgs e) { Driver("OnChannelActiveSynced", sender, e); } private void client_OnChannelAction(object sender, ActionEventArgs e) { Driver("OnChannelAction", sender, e); } private void client_OnBan(object sender, BanEventArgs e) { Driver("OnBan", sender, e); } private void client_OnRawMessage(object sender, IrcEventArgs e) { Driver("OnRawMessage", sender, e); } #endregion public struct User { public string Host; public string Ident; public bool IsAway; public bool IsIrcOp; public bool IsRegistered; public string Nick; } } }