protected override void __evt_CTCP(NetworkCTCPEventArgs args) { switch (args.CTCP) { case "FINGER": Transfer("NOTICE " + args.SourceInfo.Nick + " :" + _Protocol.Separator + "FINGER" + " I am a bot, don't finger me"); return; case "TIME": Transfer("NOTICE " + args.SourceInfo.Nick + " :" + _Protocol.Separator + "TIME " + DateTime.Now.ToString()); return; case "PING": Transfer("NOTICE " + args.SourceInfo.Nick + " :" + _Protocol.Separator + "PING" + args.Message.Substring( args.Message.IndexOf(_Protocol.Separator + "PING") + 5)); return; case "VERSION": Transfer("NOTICE " + args.SourceInfo.Nick + " :" + _Protocol.Separator + "VERSION " + Configuration.System.Version + " http://meta.wikimedia.org/wiki/wm-bot"); return; } Syslog.DebugLog("Ignoring unknown CTCP from " + args.Source + ": " + args.CTCP + args.Message); }
/// <summary> /// Load all global users of bot /// </summary> private static void GlobalLoad() { string[] dba = File.ReadAllLines(Variables.ConfigurationDirectory + Path.DirectorySeparatorChar + "admins"); lock (globalUsers) { globalUsers.Clear(); foreach (string x in dba) { if (x.Contains(Configuration.System.Separator)) { string[] info = x.Split(Char.Parse(Configuration.System.Separator)); string level = info[1]; string name = info[0]; SystemUser user = new SystemUser(level, name); if (info.Length > 3) { user.UserName = info[3]; user.Password = info[2]; } globalUsers.Add(user); Syslog.DebugLog("Registered global user (" + level + "): " + name, 2); } } } }
private void Exec() { while (this.IsActive && Core.IsRunning) { try { this.Disconnect(); this.Connect(); while (!this.IsWorking && !this.Protocol.IsDisconnected) { // we need to wait for the irc handler to connect to irc Thread.Sleep(100); } // now we can finally join all channels Join(); // then we just sleep while (this.Network.IsConnected) { Thread.Sleep(2000); } // in case we got disconnected, we log it and restart the procedure Syslog.WarningLog("Disconnected from irc network on " + Nick); Thread.Sleep(20000); } catch (ThreadAbortException) { Syslog.DebugLog("Terminated primary thread for instance " + Nick); return; } catch (IOException fail) { if (this.IsActive) { Syslog.ErrorLog("Failure of primary thread of instance " + Nick + " attempting to recover"); Core.HandleException(fail); } else { return; } } catch (Exception fail) { Core.HandleException(fail); if (this.IsActive) { Syslog.ErrorLog("Failure of primary thread of instance " + Nick + " attempting to recover"); } else { return; } Thread.Sleep(20000); } } Core.ThreadManager.UnregisterThread(Thread.CurrentThread); }
protected override void __evt_FinishChannelParseUser(NetworkChannelDataEventArgs args) { Channel channel = Core.GetChannel(args.ChannelName); Syslog.DebugLog("Finished parsing of user list for channel: " + args.ChannelName); if (channel != null) { channel.HasFreshUserList = true; } }
private void Exec() { try { Thread.Sleep(8000); if (unwritten.PendingRows.Count == 0 && File.Exists(Variables.ConfigurationDirectory + Path.DirectorySeparatorChar + "unwrittensql.xml")) { File.Delete(Variables.ConfigurationDirectory + Path.DirectorySeparatorChar + "unwrittensql.xml"); } while (Core.IsRunning) { if (unwritten.PendingRows.Count > 0) { int count; Syslog.WarningLog("Performing recovery of " + unwritten.PendingRows.Count + " MySQL rows"); Recovering = true; List <SerializedRow> rows = new List <SerializedRow>(); lock (unwritten.PendingRows) { count = unwritten.PendingRows.Count; rows.AddRange(unwritten.PendingRows); unwritten.PendingRows.Clear(); } int recovered = 0; foreach (SerializedRow row in rows) { if (InsertRow(row.table, row.row)) { recovered++; } else { Syslog.DebugLog("Failed to recover 1 row", 2); } } Syslog.WarningLog("Recovery finished, recovered " + recovered + " of total " + count); Recovering = false; FlushRows(); Thread.Sleep(200000); if (unwritten.PendingRows.Count == 0 && File.Exists(Variables.ConfigurationDirectory + Path.DirectorySeparatorChar + "unwrittensql.xml")) { File.Delete(Variables.ConfigurationDirectory + Path.DirectorySeparatorChar + "unwrittensql.xml"); } } Thread.Sleep(200); } } catch (Exception fail) { Core.HandleException(fail); Syslog.ErrorLog("Recovery thread for Mysql is down"); } }
/// <summary> /// Creates a new instance /// </summary> /// <param name="name"></param> /// <param name="port"></param> /// <returns></returns> public static Instance CreateInstance(string name, int port = 0) { Syslog.DebugLog("Creating instance " + name + " with port " + port); Instance instance = new Instance(name, port); if (Instances.ContainsKey(name)) { throw new Exception("Can't load instance " + name + " because this instance is already running"); } Instances.Add(name, instance); return(instance); }
/// <summary> /// Return true if user is present in channel /// </summary> /// <param name="name"></param> /// <returns></returns> public bool ContainsUser(string name) { this.RefetchChannel(); if (this.IrcChannel != null) { return(this.IrcChannel.ContainsUser(name)); } else { Syslog.DebugLog("IrcChannel is NULL: " + Name); } return(false); }
public static void UnregisterCommand(GenericCommand command) { lock (commands) { if (!commands.ContainsKey(command.Name)) { throw new WmibException("There is no such a command in pool: " + command.Name); } commands.Remove(command.Name); Syslog.DebugLog("Unregistered command: " + command.Name); } }
public static void UnregisterAlias(string name) { lock (aliases) { if (!aliases.ContainsKey(name)) { throw new WmibException("There is no such an alias in pool: " + name); } aliases.Remove(name); Syslog.DebugLog("Unregistered alias: " + name); } }
/// <summary> /// Load a global list /// </summary> public static void Global() { if (!File.Exists(Variables.ConfigurationDirectory + Path.DirectorySeparatorChar + "admins")) { // Create db Syslog.Log("Creating user file for admins"); File.WriteAllText(Variables.ConfigurationDirectory + Path.DirectorySeparatorChar + "admins", ""); } GlobalLoad(); Syslog.DebugLog("Registering fs watcher for global user list"); fs.Path = Variables.ConfigurationDirectory; fs.Changed += GlobalChanged; fs.Created += GlobalChanged; fs.Filter = "admins"; fs.EnableRaisingEvents = true; }
public bool Authenticate(bool wait = true) { if (!String.IsNullOrEmpty(Configuration.IRC.LoginPw)) { Syslog.DebugLog("Sending password to nickserv"); this.Send("PRIVMSG nickserv :identify " + Configuration.IRC.LoginNick + " " + Configuration.IRC.LoginPw); if (wait) { Thread.Sleep(4000); } } else { Syslog.DebugLog("Not sending password to nickserv"); } return(true); }
/// <summary> /// Load a binary module /// </summary> /// <param name="path"></param> /// <returns></returns> public static bool LoadAllModulesInLibrary(string path) { try { if (File.Exists(path)) { Assembly library = Assembly.LoadFrom(path); if (library == null) { Syslog.WarningLog("Unable to load " + path + " because the file can't be read"); return(false); } Type[] types = library.GetTypes(); foreach (Type type in types) { if (type.IsSubclassOf(typeof(Module))) { // For recall later _moduleTypes.Add(type); if (ShouldCreateModuleOnStartup(type)) { CreateModule(type); } else { Syslog.DebugLog("Not registering module (type " + type.Name + ") because it's not in a module list"); } } } return(true); } Syslog.Log("Unable to load " + path + " because the file can't be read", true); } catch (Exception fail) { Core.HandleException(fail); } return(false); }
public static void ConnectAllIrcInstances() { foreach (Instance instance in Instances.Values) { // connect it to irc instance.Init(); } // now we need to wait for all instances to connect Syslog.Log("Waiting for all instances to connect to irc"); bool IsOk = false; while (!IsOk) { foreach (Instance instance in Instances.Values) { if (!instance.IsWorking) { Syslog.DebugLog("Waiting for " + instance.Nick, 2); Thread.Sleep(1000); IsOk = false; break; } Syslog.DebugLog("Connected to " + instance.Nick, 6); IsOk = true; } } // wait for all instances to join their channels Syslog.Log("Waiting for all instances to join channels"); IsOk = false; while (!IsOk) { foreach (Instance instance in Instances.Values) { if (!instance.ChannelsJoined) { Thread.Sleep(100); IsOk = false; break; } IsOk = true; } } Syslog.Log("All instances joined their channels"); }
public static void RegisterCommand(GenericCommand command) { lock (commands) { if (commands.ContainsKey(command.Name)) { throw new WmibException("This command is already registered: " + command.Name); } if (command.Module != null) { Syslog.DebugLog("Module " + command.Module + " registered a new command: " + command.Name); } else { Syslog.DebugLog("Registering a new command: " + command.Name); } commands.Add(command.Name, command); } }
public static void KillThread(Thread t) { if (t == null) { return; } Syslog.DebugLog("Killing thread: " + t.Name); if (t == KernelThread) { Syslog.DebugLog("Refusing to kill kernel thread"); return; } if (t.ThreadState == ThreadState.Running || t.ThreadState == ThreadState.WaitSleepJoin) { t.Abort(); } else { Syslog.DebugLog("Refusing to kill thread in status: " + t.ThreadState); } UnregisterThread(t); }
/// <summary> /// This is a private handler for channel joining, never call it directly, use Join() for that /// </summary> private void JoinAll() { try { if (this.ChannelsJoined == false) { while (!this.IsWorking) { if (!this.IsActive || !Core.IsRunning) { Core.ThreadManager.UnregisterThread(Thread.CurrentThread); return; } Syslog.DebugLog("JOIN THREAD: Waiting for " + Nick + " to finish connection to IRC server", 6); Thread.Sleep(1000); } if (Configuration.System.DebugChan != null) { this.Network.Join(Configuration.System.DebugChan); } foreach (Channel channel in ChannelList) { if (channel.Name.Length > 0 && channel.Name != Configuration.System.DebugChan) { Syslog.DebugLog("Joining " + channel.Name + " on " + Nick); this.Network.Join(channel.Name, channel.Password); Thread.Sleep(1000); } } this.ChannelsJoined = true; } } catch (Exception fail) { Core.HandleException(fail); } Core.ThreadManager.UnregisterThread(Thread.CurrentThread); }
public static void RegisterAlias(string name, string target, string module = null) { lock (aliases) { if (aliases.ContainsKey(name)) { throw new WmibException("This alias is already registered: " + name); } if (module != null) { Syslog.DebugLog("Module " + module + " registered alias " + name + " for command " + target); } else { Syslog.DebugLog("Registered alias " + name + " for command " + target); } if (!commands.ContainsKey(target)) { Syslog.WarningLog("Alias " + name + " points to command " + target + " which doesn't exist"); } aliases.Add(name, target); } }
/// <summary> /// Remove all refs /// </summary> public void Remove() { if (IsRemoved) { Syslog.DebugLog("Channel is already removed"); return; } SystemUsers = null; lock (ExtensionData) { ExtensionData.Clear(); } lock (ExtensionObjects) { ExtensionObjects.Clear(); } SharedDB = null; SharedChans.Clear(); SharedLinkedChan.Clear(); if (Configuration.Channels.Contains(this)) { Configuration.Channels.Remove(this); } }
/// <summary> /// Processes the terminal parameters /// </summary> /// <param name='args'> /// What user has provided in terminal /// </param> private static void ParseArgs(string[] args) { int i = 0; List <string> parameters = new List <string>(args); foreach (string item in parameters) { i++; if (item == "--nocolors") { Configuration.System.Colors = false; continue; } if (item == "--traffic") { Configuration.Network.Logging = true; } if (item == "-h" || item == "--help") { Console.WriteLine("This is a wikimedia bot binary\n\n" + "Parameters:\n" + " --nocolors: Disable colors in system logs\n" + " -h [--help]: Display help\n" + " --pid file: Write a pid to a file\n" + " --modules: Try to load all module files and list all modules that are available, separated by comma\n" + " --traffic: Enable traffic logs\n" + " --security: Will load a security subsystem and serialize all roles and print them to standard output\n" + " this can be used to create a custom security configuration if you store the output\n" + " to configuration/security.xml and restart the bot\n" + " -v: Increases verbosity\n\n" + "This software is open source, licensed under GPLv3"); Environment.Exit(0); } if (item == "--modules") { ExtensionHandler.DumpMods(); Environment.Exit(0); } if (item == "--security") { Syslog.IsQuiet = true; if (Configuration.Load() != 0) { Syslog.IsQuiet = false; Syslog.WriteNow("Error while loading the config file, exiting", true); Environment.Exit(-2); } ExtensionHandler.SearchMods(); Security.Init(); Console.WriteLine(Security.Dump()); Environment.Exit(0); } if (item == "--pid") { if (parameters.Count <= i) { Console.WriteLine("You didn't provide a name for pid file"); Environment.Exit(0); } File.WriteAllText(parameters[i], Process.GetCurrentProcess().Id.ToString()); } if (item.StartsWith("-v", StringComparison.InvariantCulture)) { foreach (char x in item) { if (x == 'v') { Configuration.System.SelectedVerbosity++; } } } } if (Configuration.System.SelectedVerbosity >= 1) { Syslog.DebugLog("System verbosity: " + Configuration.System.SelectedVerbosity); } }
/// <summary> /// Insert row /// </summary> /// <param name="table"></param> /// <param name="row"></param> /// <returns></returns> public override bool InsertRow(string table, Row row) { StringBuilder sql = new StringBuilder(); lock (DatabaseLock) { try { if (!IsConnected) { Syslog.DebugLog("Postponing request to insert a row into database which is not connected"); lock (unwritten.PendingRows) { unwritten.PendingRows.Add(new SerializedRow(table, row)); } FlushRows(); return(false); } MySqlCommand mySqlCommand = Connection.CreateCommand(); sql.Append("INSERT INTO "); sql.Append(table); sql.Append(" VALUES ("); foreach (Row.Value value in row.Values) { switch (value.Type) { case DataType.Boolean: case DataType.Integer: sql.Append(value.Data); sql.Append(", "); break; case DataType.Varchar: case DataType.Text: case DataType.Date: sql.Append("'"); sql.Append(MySqlHelper.EscapeString(value.Data)); sql.Append("', "); break; } } if (sql.ToString().EndsWith(", ")) { sql.Remove(sql.Length - 2, 2); } sql.Append(");"); mySqlCommand.CommandText = sql.ToString(); mySqlCommand.ExecuteNonQuery(); return(true); } catch (MySqlException me) { ErrorBuffer = me.Message; Syslog.Log("Error while storing a row to DB " + me, true); Syslog.DebugLog("SQL: " + sql); lock (unwritten.PendingRows) { unwritten.PendingRows.Add(new SerializedRow(table, row)); } FlushRows(); return(false); } } }
public override bool InsertRow(string table, Row row) { StringBuilder sql = new StringBuilder(); lock (DatabaseLock) { try { if (!IsConnected) { Syslog.DebugLog("Postponing request to insert a row into database which is not connected"); //lock(unwritten.PendingRows) //{ // unwritten.PendingRows.Add(new SerializedRow(table, row)); //} //FlushRows(); return(false); } Npgsql.NpgsqlCommand s = new Npgsql.NpgsqlCommand(); s.Connection = this.connection; sql.Append("INSERT INTO "); sql.Append(table); // let's check if there are headers bool headers = true; string header = ""; foreach (Row.Value value in row.Values) { if (value.Column == null) { headers = false; break; } header += value.Column + ", "; } if (header.EndsWith(", ")) { header = header.Substring(0, header.Length - 2); } if (headers) { sql.Append(" (" + header + ")"); } sql.Append(" VALUES ("); int cv = 0; foreach (Row.Value value in row.Values) { sql.Append(":v" + cv.ToString() + ", "); switch (value.Type) { case DataType.Boolean: s.Parameters.Add(new Npgsql.NpgsqlParameter("v" + cv.ToString(), NpgsqlTypes.NpgsqlDbType.Boolean)); s.Parameters[cv].Value = bool.Parse(value.Data); break; case DataType.Integer: s.Parameters.Add(new Npgsql.NpgsqlParameter("v" + cv.ToString(), NpgsqlTypes.NpgsqlDbType.Integer)); s.Parameters[cv].Value = int.Parse(value.Data); break; case DataType.Varchar: s.Parameters.Add(new Npgsql.NpgsqlParameter("v" + cv.ToString(), NpgsqlTypes.NpgsqlDbType.Varchar)); s.Parameters[cv].Value = value.Data; break; case DataType.Text: s.Parameters.Add(new Npgsql.NpgsqlParameter("v" + cv.ToString(), NpgsqlTypes.NpgsqlDbType.Text)); s.Parameters[cv].Value = value.Data; break; case DataType.Date: s.Parameters.Add(new Npgsql.NpgsqlParameter("v" + cv.ToString(), NpgsqlTypes.NpgsqlDbType.Timestamp)); s.Parameters[cv].Value = DateTime.Parse(value.Data); break; } cv++; } if (sql.ToString().EndsWith(", ")) { sql.Remove(sql.Length - 2, 2); } sql.Append(");"); s.CommandText = sql.ToString(); SystemHooks.OnSQL(LocalName, sql.ToString()); s.ExecuteNonQuery(); return(true); } catch (Npgsql.NpgsqlException me) { ErrorBuffer = me.Message; Syslog.Log("Error while storing a row to DB " + me, true); Syslog.DebugLog("SQL: " + sql.ToString()); HandleError(sql.ToString()); /*lock(unwritten.PendingRows) * { * unwritten.PendingRows.Add(new SerializedRow(table, row)); * } * FlushRows(); * * */ return(false); } } }
/// <summary> /// Load config of bot /// </summary> public static int Load() { if (Directory.Exists(Variables.ConfigurationDirectory) == false) { Directory.CreateDirectory(Variables.ConfigurationDirectory); } if (!File.Exists(Variables.ConfigurationDirectory + Path.DirectorySeparatorChar + Paths.ConfigFile)) { Console.WriteLine("Error: unable to find config file in configuration/" + Paths.ConfigFile); Console.WriteLine("You can get a configuration file here: https://github.com/benapetr/wikimedia-bot/blob/master/configuration/wmib.conf"); return(2); } ConfigurationData = File2Dict(); IRC.Username = RetrieveConfig("username"); IRC.NetworkHost = RetrieveConfig("network"); IRC.NickName = RetrieveConfig("nick"); IRC.LoginNick = RetrieveConfig("nick"); IRC.Hostname = RetrieveConfig("host", "wikimedia/bot/wm-bot"); System.DebugChan = RetrieveConfig("debug"); System.MaxGrantableRoleLevel = RetrieveConfig("maximal_grantable_role_level", System.MaxGrantableRoleLevel); System.ModulesToLoad = RetrieveConfig("modules", ""); Network.BouncerPort = RetrieveConfig("bouncerp", Network.BouncerPort); WebPages.WebpageURL = RetrieveConfig("web", ""); IRC.LoginPw = RetrieveConfig("password", ""); IRC.Interval = RetrieveConfig("interval", IRC.Interval); MySQL.MysqlPw = RetrieveConfig("mysql_pw"); MySQL.Mysqldb = RetrieveConfig("mysql_db", MySQL.Mysqldb); MySQL.MysqlUser = RetrieveConfig("mysql_user"); MySQL.MysqlPort = RetrieveConfig("mysql_port", MySQL.MysqlPort); MySQL.MysqlHost = RetrieveConfig("mysql_host"); WebPages.Css = RetrieveConfig("style_html_file", ""); Network.SystemPort = RetrieveConfig("system_port", Network.SystemPort); Postgres.DBNM = RetrieveConfig("pg_name"); Postgres.Host = RetrieveConfig("pg_host"); Postgres.Pass = RetrieveConfig("pg_pass"); Postgres.Unwritten = RetrieveConfig("pg_unwritten_log", Postgres.Unwritten); Postgres.Port = RetrieveConfig("pg_port", Postgres.Port); Postgres.User = RetrieveConfig("pg_user"); if (string.IsNullOrEmpty(IRC.LoginNick)) { Console.WriteLine("Error there is no login for bot (nick key is missing?)"); return(1); } if (string.IsNullOrEmpty(IRC.NetworkHost)) { Console.WriteLine("Error irc server is wrong (network key is missing?)"); return(4); } if (string.IsNullOrEmpty(IRC.NickName)) { Console.WriteLine("Error there is no username for bot"); return(6); } System.prefix = RetrieveConfig("system_prefix", System.prefix); IRC.UsingBouncer = bool.Parse(RetrieveConfig("serverIO", "false")); Syslog.Log("Loading instances"); Instance.PrimaryInstance = Instance.CreateInstance(IRC.NickName, Network.BouncerPort); int CurrentInstance = 0; while (CurrentInstance < 20) { if (!ConfigurationData.ContainsKey("instancename" + CurrentInstance)) { break; } string InstanceName = ConfigurationData["instancename" + CurrentInstance]; Syslog.DebugLog("Instance found: " + InstanceName); if (IRC.UsingBouncer) { Syslog.DebugLog("Using bouncer, looking for instance port"); if (!ConfigurationData.ContainsKey("instanceport" + CurrentInstance)) { Syslog.WriteNow("Instance " + InstanceName + " has invalid port, not using", true); continue; } int port = int.Parse(ConfigurationData["instanceport" + CurrentInstance]); Instance.CreateInstance(InstanceName, port); } else { Instance.CreateInstance(InstanceName); } CurrentInstance++; } if (!File.Exists(Paths.GetChannelFile())) { Console.WriteLine("Error there is no channel file (" + Paths.GetChannelFile() + ") to load channels from"); return(20); } List <string> channels = new List <string>(File.ReadAllLines(Paths.GetChannelFile())); foreach (string x in channels) { string name = x.Replace(" ", ""); if (!string.IsNullOrEmpty(name)) { lock (Channels) { Channels.Add(new Channel(name)); } } } if (!string.IsNullOrEmpty(Configuration.System.DebugChan) && !channels.Contains(Configuration.System.DebugChan)) { lock (Channels) { Channels.Add(new Channel(Configuration.System.DebugChan)); } Syslog.DebugLog("Debug channel was missing in channel list (fixed by join)"); } Syslog.Log("Channels were all loaded, linking databases"); // Now when all chans are loaded let's link them together lock (Channels) { foreach (Channel channel in Channels) { channel.InitializeShares(); } } Syslog.Log("Channel db's working"); if (!Directory.Exists(Paths.DumpDir)) { Directory.CreateDirectory(Paths.DumpDir); } return(0); }
public void ThreadExec(object data) { try { this.connection = (TcpClient)data; Syslog.DebugLog("Incoming connection from: " + connection.Client.RemoteEndPoint); this.connection.NoDelay = true; this.networkStream = connection.GetStream(); this.streamReader = new StreamReader(networkStream); this.streamWriter = new StreamWriter(networkStream); // login Write("Enter username:"******"Enter password:"******"Invalid user or password, bye"); return; } if (!Security.IsGloballyApproved(user, "terminal")) { Disconnect("No permissions, bye"); return; } Write("Successfuly logged in to wm-bot, I have " + SessionList.Count.ToString() + " users logged in"); while (connection.Connected && !streamReader.EndOfStream && Core.IsRunning) { string text = streamReader.ReadLine(); string command = text; List <string> list = new List <string>(); string parameters = ""; if (command.Contains(" ")) { parameters = command.Substring(command.IndexOf(" ") + 1); command = command.Substring(0, command.IndexOf(" ")); if (parameters.Contains(" ")) { list.AddRange(parameters.Split(' ')); } } switch (command.ToLower()) { case "exit": case "quit": Disconnect("Good bye"); return; case "info": string result = "Uptime: " + Core.getUptime() + " Version: " + Configuration.System.Version + "\n\nBuffer information:\nUnwritten lines (file storage): " + StorageWriter.Count + "\n"; // we flush it early so that we can see where it gets stuck in case of a dead lock Write(result); result = ""; if (Core.DB != null) { result += "Unwritten rows (MySQL): " + Core.DB.CacheSize() + "\n"; } result += "\nThreads:\n"; foreach (Thread thread in Core.ThreadManager.ThreadList) { result += "Thread: " + FormatToSpecSize(thread.Name, 20) + " status: " + FormatToSpecSize(thread.ThreadState.ToString(), 20) + " id: " + FormatToSpecSize(thread.ManagedThreadId.ToString(), 8) + "\n"; } Write(result); Write("Instances:"); result = ""; Syslog.DebugLog("Retrieving information for user " + username + " in system"); foreach (Instance instance in Instance.Instances.Values) { Syslog.DebugLog("Retrieving information for user " + username + " of instance " + instance.Nick, 2); result += instance.Nick + " channels: " + instance.ChannelCount + " connected: " + instance.IsConnected + " working: " + instance.IsWorking + " queue: " + instance.QueueSize() + "\n"; } Write(result); break; case "help": Write("Commands:\n" + "exit - shutdown connection\n" + "verbosity++\nverbosity--\n" + "info - print information about system\n" + "halt - shutdown bot\n" + "reauth [instance] - resend password to nickserv\n" + "traffic-on - turn on traffic logs\n" + "traffic-off - turn off traffic logs\n" + "send [instance] [text] - deliver a RAW text to IRC server on a given bot\n" + "kill [instance] - disconnect selected instance\n" + "conn [instance] - connect instance\n"); break; case "halt": Disconnect("Shutting down"); Core.Kill(); return; case "reauth": if (Instance.Instances.ContainsKey(parameters)) { Instance.Instances[parameters].Protocol.Authenticate(false); Write("Sent a password to nickserv on " + parameters); break; } Write("Unknown instance: " + parameters); break; case "traffic-on": Configuration.Network.Logging = true; Write("Dumping traffic into datafile"); break; case "verbosity++": Configuration.System.SelectedVerbosity++; break; case "verbosity--": Configuration.System.SelectedVerbosity--; break; case "traffic-off": Configuration.Network.Logging = false; Write("Disabled traffic"); break; case "kill": if (Instance.Instances.ContainsKey(parameters)) { Instance.Instances[parameters].ShutDown(); Write("Killed: " + parameters); break; } Write("Unknown instance: " + parameters); break; case "conn": if (Instance.Instances.ContainsKey(parameters)) { if (Instance.Instances[parameters].IsConnected) { Write("Refusing to connect instance which is already connected: " + parameters); break; } Instance.Instances[parameters].Init(); Write("Initializing: " + parameters); int curr = 0; while (curr < 10 && !Instance.Instances[parameters].IsWorking) { curr++; Thread.Sleep(1000); } if (!Instance.Instances[parameters].IsWorking) { Write("Failed to initialize instance (timeout)"); break; } Write("Joining channels"); Instance.Instances[parameters].ChannelsJoined = false; Instance.Instances[parameters].Join(); curr = 0; while (curr < Instance.Instances[parameters].ChannelCount && !Instance.Instances[parameters].ChannelsJoined) { curr++; Thread.Sleep(6000); } if (!Instance.Instances[parameters].ChannelsJoined) { Write("Failed to rejoin all channels in time"); break; } Write("Instance is online: " + parameters); break; } Write("Unknown instance: " + parameters); break; case "send": if (!parameters.Contains(" ")) { Write("This command requires 2 parameters"); break; } string to = parameters.Substring(0, parameters.IndexOf(" ")); if (Instance.Instances.ContainsKey(to)) { if (!Instance.Instances[to].IsConnected) { Write("Refusing to send data using instance which is not connected: " + to); break; } Instance.Instances[to].Network.Transfer(parameters.Substring(parameters.IndexOf(" ") + 1)); break; } Write("I have no such instance dude"); break; default: Write("Unknown command, try help"); break; } } } catch (Exception fail) { Core.HandleException(fail); } Disconnect(); }
/// <summary> /// Debug log /// </summary> /// <param name="text"></param> /// <param name="verbosity"></param> public void DebugLog(string text, int verbosity = 1) { Syslog.DebugLog(Name + ": " + text, verbosity); }
/// <summary> /// This will disable bot and close this process /// </summary> public static void Kill() { try { if (!IsRunning) { Syslog.DebugLog("Attempt to kill bot while it's already being killed", 2); return; } _Status = Status.ShuttingDown; Instance.Kill(); StorageWriter.IsRunning = false; Thread modules = new Thread(Terminate) { Name = "KERNEL: Core helper shutdown thread" }; modules.Start(); Syslog.WriteNow("Giving grace time for all modules to finish ok"); int kill = 0; while (kill < 20) { kill++; if (ExtensionHandler.ExtensionList.Count == 0) { Syslog.WriteNow("KERNEL: Modules are all down"); if (WriterThread.ThreadState == ThreadState.Running || WriterThread.ThreadState == ThreadState.WaitSleepJoin) { Syslog.WriteNow("KERNEL: Writer thread didn't shut down gracefully, waiting 2 seconds", true); Thread.Sleep(2000); if (WriterThread.ThreadState == ThreadState.Running || WriterThread.ThreadState == ThreadState.WaitSleepJoin) { Syslog.WriteNow("KERNEL: Writer thread didn't shut down gracefully, killing", true); WriterThread.Abort(); } else { Syslog.WriteNow("KERNEL: Writer thread is shut down", true); } } else { Syslog.WriteNow("KERNEL: Writer thread is down ok"); } break; } Thread.Sleep(1000); } if (ExtensionHandler.ExtensionList.Count == 0) { Syslog.WriteNow("KERNEL: Giving a grace time to other threads to finish"); Thread.Sleep(200); Syslog.WriteNow("KERNEL: Terminated (ok)"); Environment.Exit(0); } } catch (Exception fail) { HandleException(fail); } Syslog.WriteNow("There was problem shutting down " + ExtensionHandler.ExtensionList.Count + " modules, terminating process"); Syslog.WriteNow("KERNEL: Terminated (error)"); Process.GetCurrentProcess().Kill(); }
public override void DebugLog(string Text, int Verbosity) { Syslog.DebugLog(Text, Verbosity); }
/// <summary> /// Join channel /// </summary> public static void AddChannel(CommandParams parameters) { if (!String.IsNullOrEmpty(parameters.Parameters)) { while (!IRC.FinishedJoining) { Syslog.Log("Postponing request to join " + parameters.Parameters + " because bot is still loading", true); Thread.Sleep(2000); } List <string> pm = new List <string>(parameters.Parameters.Trim().Split(' ')); if (pm.Count > 2 || pm.Count == 0) { IRC.DeliverMessage("Invalid number of parameters, please provide up to 2 parameters (name, password)", parameters.SourceChannel); return; } string channel_name = pm[0]; string password = null; if (pm.Count > 1) { password = pm[1]; } if (!Core.ValidFile(channel_name) || !channel_name.StartsWith("#")) { IRC.DeliverMessage(messages.Localize("InvalidName", parameters.SourceChannel.Language, new List <string> { channel_name }), parameters.SourceChannel); return; } lock (Configuration.Channels) { foreach (Channel cu in Configuration.Channels) { if (channel_name == cu.Name) { IRC.DeliverMessage(messages.Localize("ChannelIn", parameters.SourceChannel.Language), parameters.SourceChannel); return; } } } bool existing = Channel.ConfigExists(channel_name); Channel channel = new Channel(channel_name) { Password = password }; lock (Configuration.Channels) { Configuration.Channels.Add(channel); } IRC.DeliverMessage("Attempting to join " + channel_name + " using " + channel.PrimaryInstance.Nick, parameters.SourceChannel.Name); Configuration.Save(); Syslog.DebugLog("Sending join " + channel_name); channel.PrimaryInstance.Network.Join(channel_name, password); Channel Chan = Core.GetChannel(channel_name); if (!existing) { Chan.SystemUsers.AddUser("admin", Security.EscapeUser(parameters.User.Nick) + "!.*@" + Security.EscapeUser(parameters.User.Host)); } if (Chan.Extension_GetConfig("generic.founder") == null) { Chan.Extension_SetConfig("generic.founder", parameters.User.ToString()); Chan.Extension_SetConfig("generic.owner", parameters.User.ToString()); } else { Chan.Extension_SetConfig("generic.owner", parameters.User.ToString()); } Chan.Extension_SetConfig("generic.joindate", DateTime.Now.ToString()); Chan.SaveConfig(); return; } IRC.DeliverMessage(messages.Localize("InvalidName", parameters.SourceChannel.Language), parameters.SourceChannel); return; }
private bool _Connect() { Syslog.Log("Connecting instance " + this.IRCNetwork.Nickname + " to irc server " + Server + "..."); if (!Configuration.IRC.UsingBouncer) { networkStream = new TcpClient(Server, 6667).GetStream(); } else { Syslog.Log(this.IRCNetwork.Nickname + " is using personal bouncer port " + BouncerPort.ToString()); networkStream = new TcpClient(BouncerHost, BouncerPort).GetStream(); } Connected = true; streamReader = new StreamReader(networkStream, System.Text.Encoding.UTF8); streamWriter = new StreamWriter(networkStream); bool Auth = true; if (Configuration.IRC.UsingBouncer) { this.Send("CONTROL: STATUS"); Syslog.Log("CACHE: Waiting for buffer (network bouncer) of instance " + this.IRCNetwork.Nickname); while (true) { string response = streamReader.ReadLine(); this.TrafficLog(response, true); if (response == "CONTROL: TRUE") { Syslog.DebugLog("Resumming previous session on " + this.IRCNetwork.Nickname); Auth = false; IRCNetwork.IsConnected = true; ChannelsJoined = true; IsWorking = true; // this here is a nasty hack to make libirc think that we just joined all the channels // we should be already on foreach (Instance xx in Instance.Instances.Values) { foreach (Channel channel in xx.ChannelList) { channel.PrimaryInstance.Network.MakeChannel(channel.Name); } } break; } else if (response.StartsWith(":")) { Backlog.Add(response); } else if (response == "CONTROL: FALSE") { Syslog.DebugLog("Bouncer is not connected, starting new session on " + IRCNetwork.Nickname); if (!this.connectBnc()) { return(false); } break; } } } Messages.protocol = this; if (Auth) { NetworkInit(); } if (!this.ManualThreads) { this.TKeep = new Thread(_Ping); this.TKeep.Name = "Instance:" + this.Server + "/pinger"; Core.ThreadManager.RegisterThread(TKeep); TKeep.Start(); } if (!this.ManualThreads) { TDeliveryQueue = new System.Threading.Thread(Messages.Run); TDeliveryQueue.Name = "Instance:" + this.Server + "/queue"; Core.ThreadManager.RegisterThread(TDeliveryQueue); TDeliveryQueue.Start(); } return(true); }