/// <summary> /// Write a message /// </summary> /// <param name="time"></param> /// <param name="Message"></param> /// <param name="MessageType"></param> public static void Display(DateTime time, string Message, Syslog.Type MessageType) { if (Configuration.System.Colors) { Console.ForegroundColor = ConsoleColor.Blue; } Console.Write("LOG "); if (Configuration.System.Colors) { Console.ForegroundColor = ConsoleColor.Green; } Console.Write("[{0}]", time); if (MessageType == Syslog.Type.Warning) { if (Configuration.System.Colors) { Console.ForegroundColor = ConsoleColor.Yellow; } Console.Write(" [WARNING]"); } else if (MessageType == Syslog.Type.Error) { if (Configuration.System.Colors) { Console.ForegroundColor = ConsoleColor.Red; } Console.Write(" [ERROR]"); } else { if (Configuration.System.Colors) { Console.ForegroundColor = ConsoleColor.DarkCyan; } Console.Write(" [INFO]"); } if (Configuration.System.Colors) { Console.ResetColor(); } Console.WriteLine(": " + Message); }
/// <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> /// Write a message to terminal /// </summary> /// <param name="Message"></param> /// <param name="MessageType"></param> public static void Write(string Message, Syslog.Type MessageType) { Message message = new Message(Message, DateTime.Now, MessageType); lock (messages) { messages.Add(message); } }
/// <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); } } }
private static void Configure(CommandParams parameters) { if (string.IsNullOrEmpty(parameters.Parameters)) { return; } if (parameters.Parameters.Contains("=") && !parameters.Parameters.EndsWith("=", System.StringComparison.InvariantCulture)) { string name = parameters.Parameters.Substring(0, parameters.Parameters.IndexOf("=", System.StringComparison.InvariantCulture)); string value = parameters.Parameters.Substring(parameters.Parameters.IndexOf("=", System.StringComparison.InvariantCulture) + 1); bool _temp_a; switch (name) { case "ignore-unknown": if (bool.TryParse(value, out _temp_a)) { parameters.SourceChannel.IgnoreUnknown = _temp_a; IRC.DeliverMessage(messages.Localize("configuresave", parameters.SourceChannel.Language, new List <string> { value, name }), parameters.SourceChannel); parameters.SourceChannel.SaveConfig(); return; } IRC.DeliverMessage(messages.Localize("configure-va", parameters.SourceChannel.Language, new List <string> { name, value }), parameters.SourceChannel); return; case "respond-wait": int _temp_b; if (int.TryParse(value, out _temp_b)) { if (_temp_b > 1 && _temp_b < 364000) { parameters.SourceChannel.RespondWait = _temp_b; IRC.DeliverMessage(messages.Localize("configuresave", parameters.SourceChannel.Language, new List <string> { value, name }), parameters.SourceChannel); parameters.SourceChannel.SaveConfig(); return; } } IRC.DeliverMessage(messages.Localize("configure-va", parameters.SourceChannel.Language, new List <string> { name, value }), parameters.SourceChannel); return; case "respond-message": if (bool.TryParse(value, out _temp_a)) { parameters.SourceChannel.RespondMessage = _temp_a; IRC.DeliverMessage(messages.Localize("configuresave", parameters.SourceChannel.Language, new List <string> { value, name }), parameters.SourceChannel); parameters.SourceChannel.SaveConfig(); return; } IRC.DeliverMessage(messages.Localize("configure-va", parameters.SourceChannel.Language, new List <string> { name, value }), parameters.SourceChannel); return; case "suppress-warnings": if (bool.TryParse(value, out _temp_a)) { parameters.SourceChannel.SuppressWarnings = _temp_a; IRC.DeliverMessage(messages.Localize("configuresave", parameters.SourceChannel.Language, new List <string> { value, name }), parameters.SourceChannel); parameters.SourceChannel.SaveConfig(); return; } IRC.DeliverMessage(messages.Localize("configure-va", parameters.SourceChannel.Language, new List <string> { name, value }), parameters.SourceChannel); return; } bool exist = false; foreach (Module curr in ExtensionHandler.ExtensionList) { try { if (curr.IsWorking && curr.Hook_SetConfig(parameters.SourceChannel, parameters.User, name, value)) { exist = true; } } catch (Exception fail) { Syslog.Log("Error on Hook_SetConfig module " + curr.Name); Core.HandleException(fail, curr.Name); } } if (!parameters.SourceChannel.SuppressWarnings && !exist) { IRC.DeliverMessage(messages.Localize("configure-wrong", parameters.SourceChannel.Language), parameters.SourceChannel); } return; } if (!parameters.Parameters.Contains(" ")) { switch (parameters.Parameters) { case "ignore-unknown": IRC.DeliverMessage(messages.Localize("Responses-Conf", parameters.SourceChannel.Language, new List <string> { parameters.Parameters, parameters.SourceChannel.IgnoreUnknown.ToString() }), parameters.SourceChannel); return; case "respond-message": IRC.DeliverMessage(messages.Localize("Responses-Conf", parameters.SourceChannel.Language, new List <string> { parameters.Parameters, parameters.SourceChannel.RespondMessage.ToString() }), parameters.SourceChannel); return; case "suppress-warnings": IRC.DeliverMessage(messages.Localize("Responses-Conf", parameters.SourceChannel.Language, new List <string> { parameters.Parameters, parameters.SourceChannel.SuppressWarnings.ToString() }), parameters.SourceChannel); return; } bool exist = false; foreach (Module curr in ExtensionHandler.ExtensionList) { try { if (curr.IsWorking && curr.Hook_GetConfig(parameters.SourceChannel, parameters.User, parameters.Parameters)) { exist = true; } } catch (Exception fail) { Syslog.Log("Error on Hook_GetConfig module " + curr.Name); Core.HandleException(fail); } } if (exist) { return; } } if (!parameters.SourceChannel.SuppressWarnings) { IRC.DeliverMessage(messages.Localize("configure-wrong", parameters.SourceChannel.Language), parameters.SourceChannel); } }
/// <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(); }
/// <summary> /// Part a channel /// </summary> /// <param name="channel">Channel object</param> /// <param name="user">User</param> /// <param name="host">Host</param> /// <param name="message">Message</param> /// <param name="origin">The channel from which this request was sent</param> public static void PartChannel(Channel channel, string user, string host, string message, string origin = "NULL") { try { if (origin == "NULL") { origin = channel.Name; } if (channel.Name == Configuration.System.DebugChan && (message == Configuration.System.CommandPrefix + "part" || message == Configuration.System.CommandPrefix + "drop")) { IRC.DeliverMessage("Cowardly refusing to part this channel, because I love it :3", channel); return; } if (message == Configuration.System.CommandPrefix + "drop") { if (channel.SystemUsers.IsApproved(user, host, "drop")) { while (!IRC.FinishedJoining) { Syslog.Log("Postponing request to part " + channel.Name + " because bot is still loading", true); Thread.Sleep(2000); } channel.PrimaryInstance.Network.Transfer("PART " + channel.Name + " :" + "dropped by " + user + " from " + origin); Syslog.Log("Dropped " + channel.Name + " dropped by " + user + " from " + origin); Thread.Sleep(100); try { File.Delete(Variables.ConfigurationDirectory + Path.DirectorySeparatorChar + channel.Name + ".xml"); } catch (Exception fail) { Syslog.ErrorLog("Failed to delete configuration file of " + channel.Name); Core.HandleException(fail); } foreach (Module module in ExtensionHandler.ExtensionList) { try { if (module.IsWorking) { module.Hook_ChannelDrop(channel); } } catch (Exception fail) { Syslog.Log("MODULE: exception at Hook_ChannelDrop in " + module.Name, true); Core.HandleException(fail, module.Name); } } lock (Configuration.Channels) { channel.Remove(); } Configuration.Save(); return; } IRC.DeliverMessage(messages.Localize("PermissionDenied", channel.Language), origin); return; } if (message == Configuration.System.CommandPrefix + "part") { if (channel.SystemUsers.IsApproved(user, host, "part")) { while (!IRC.FinishedJoining) { Syslog.Log("Postponing request to part " + channel.Name + " because bot is still loading", true); Thread.Sleep(2000); } channel.PrimaryInstance.Network.Transfer("PART " + channel.Name + " :" + "removed by " + user + " from " + origin); Syslog.Log("Removed " + channel.Name + " removed by " + user + " from " + origin); Thread.Sleep(100); lock (Configuration.Channels) { channel.Remove(); if (origin != channel.Name) { IRC.DeliverMessage("Successfully parted channel: " + channel.Name, origin); } } channel.SaveConfig(); Configuration.Save(); return; } IRC.DeliverMessage(messages.Localize("PermissionDenied", channel.Language), origin); } } catch (Exception fail) { Core.HandleException(fail); } }
/// <summary> /// Save config /// </summary> public void SaveConfig() { string fn = GetConfigFilePath(); try { XmlDocument data = new XmlDocument(); XmlNode xmlnode = data.CreateElement("channel"); InsertData("talkmode", Suppress.ToString(), ref data, ref xmlnode); InsertData("langcode", Language, ref data, ref xmlnode); InsertData("respond_message", RespondMessage.ToString(), ref data, ref xmlnode); InsertData("ignore-unknown", IgnoreUnknown.ToString(), ref data, ref xmlnode); InsertData("suppress-warnings", SuppressWarnings.ToString(), ref data, ref xmlnode); InsertData("respond_wait", RespondWait.ToString(), ref data, ref xmlnode); InsertData("sharedinfo", SharedDB, ref data, ref xmlnode); if (!String.IsNullOrEmpty(this.Password)) { InsertData("password", Password, ref data, ref xmlnode); } InsertData("defaultbot", DefaultInstance, ref data, ref xmlnode); if (!(SharedLinkedChan.Count < 1)) { foreach (Channel current in SharedLinkedChan) { InsertData("name", current.Name, ref data, ref xmlnode, "sharedch"); } } if (!(Infobot_IgnoredNames.Count < 1)) { foreach (string curr in Infobot_IgnoredNames) { InsertData("name", curr, ref data, ref xmlnode, "ignored"); } } if (ExtensionData.Count > 0) { foreach (KeyValuePair <string, string> item in ExtensionData) { InsertData(item.Key, item.Value, ref data, ref xmlnode, "extension"); } } lock (this.SystemUsers.Users) { foreach (SystemUser user in this.SystemUsers.Users) { XmlAttribute name = data.CreateAttribute("regex"); name.Value = user.Name; XmlAttribute kk = data.CreateAttribute("role"); kk.Value = user.Role; XmlNode db = data.CreateElement("user"); db.Attributes.Append(name); db.Attributes.Append(kk); xmlnode.AppendChild(db); } } if (File.Exists(fn)) { Core.BackupData(fn); if (!File.Exists(Configuration.TempName(fn))) { Syslog.WarningLog("Unable to create backup file for " + Name); } } data.AppendChild(xmlnode); data.Save(fn); if (File.Exists(Configuration.TempName(fn))) { File.Delete(Configuration.TempName(fn)); } } catch (Exception) { Core.RecoverFile(fn, Name); } }
/// <summary> /// Writes the message immediately to console with no thread sync /// </summary> /// <returns> /// The now. /// </returns> /// <param name='Message'> /// If set to <c>true</c> message. /// </param> /// <param name='MessageType'> /// If set to <c>true</c> message type. /// </param> public static bool WriteNow(string Message, Syslog.Type MessageType) { Logging.Display(DateTime.Now, Message, MessageType); SystemHooks.SystemLog(Message, MessageType); return true; }
public void LoadConfig() { string conf_file = GetConfigFilePath(); Core.RecoverFile(conf_file, Name); try { XmlDocument data = new XmlDocument(); if (!File.Exists(conf_file)) { SaveConfig(); return; } data.Load(conf_file); foreach (XmlNode xx in data.ChildNodes[0].ChildNodes) { switch (xx.Name) { case "user": this.SystemUsers.InsertUser(xx); continue; case "extension": if (ExtensionData.ContainsKey(xx.Attributes[0].Value)) { ExtensionData[xx.Attributes[0].Value] = xx.Attributes[1].Value; } else { ExtensionData.Add(xx.Attributes[0].Value, xx.Attributes[1].Value); } continue; case "ignored": Infobot_IgnoredNames.Add(xx.Attributes[1].Value); continue; case "sharedch": SharedChans.Add(xx.Attributes[1].Value); continue; } switch (xx.Attributes[0].Value) { case "talkmode": Suppress = bool.Parse(xx.Attributes[1].Value); break; case "langcode": Language = xx.Attributes[1].Value; break; case "respond_message": RespondMessage = bool.Parse(xx.Attributes[1].Value); break; case "ignore-unknown": IgnoreUnknown = bool.Parse(xx.Attributes[1].Value); break; case "suppress-warnings": SuppressWarnings = bool.Parse(xx.Attributes[1].Value); break; case "respond_wait": RespondWait = int.Parse(xx.Attributes[1].Value); break; case "sharedinfo": SharedDB = xx.Attributes[1].Value; break; case "defaultbot": DefaultInstance = xx.Attributes[1].Value; break; case "password": Password = xx.Attributes[1].Value; break; } } } catch (Exception fail) { Syslog.Log("Unable to load the config of " + Name, true); Core.HandleException(fail); } }
/// <summary> /// This is called when the file is changed /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private static void GlobalChanged(object sender, EventArgs e) { Syslog.Log("Global user list has been changed"); GlobalLoad(); }
/// <summary> /// Load all roles /// </summary> public static void Init() { Core.RecoverFile(Configuration.Paths.Security); if (File.Exists(Configuration.Paths.Security)) { DumpableDict dict = new DumpableDict(); XmlSerializer xmlSerializer = new XmlSerializer(dict.GetType()); using (StreamReader reader = new StreamReader(Variables.ConfigurationDirectory + Path.DirectorySeparatorChar + "security.xml")) { dict = (DumpableDict)xmlSerializer.Deserialize(reader); } // first we need to create all roles in the file, that is important foreach (DumpableDict.RoleInfo ri in dict.Roles) { Roles.Add(ri.Name, new Role(ri.Level)); } foreach (DumpableDict.RoleInfo ri in dict.Roles) { // now give this role all permissions and roles it had foreach (string permission in ri.Permissions) { Roles[ri.Name].Grant(permission); } foreach (string role in ri.Roles) { if (!Roles.ContainsKey(role)) { Syslog.WarningLog("There is no role " + role + " that could be granted to " + ri.Name + " skipping it"); } Roles[ri.Name].Grant(Roles[role]); } } return; } // let's assume there is no role definition file, so we create some initial, built-in roles Roles.Add("null", new Role(0)); Roles.Add("trusted", new Role(100)); Roles.Add("operator", new Role(1000)); Roles.Add("admin", new Role(20000)); Roles.Add("root", new Role(65535)); Roles["trusted"].Grant("trust"); // trusted users can add users to trust list Roles["trusted"].Grant("trustadd"); Roles["trusted"].Grant("trustdel"); Roles["operator"].Grant(Roles["trusted"]); Roles["operator"].Grant("join"); Roles["admin"].Grant("admin"); Roles["admin"].Grant("drop"); Roles["admin"].Grant("suppress"); Roles["admin"].Grant("unsuppress"); Roles["admin"].Grant("part"); Roles["admin"].Grant(Roles["operator"]); // admins have all privileges as trusted users Roles["admin"].Grant(Roles["trusted"]); Roles["root"].Grant("root"); foreach (Module module in ExtensionHandler.ExtensionList) { try { module.RegisterPermissions(); } catch (Exception fail) { Core.HandleException(fail, module.Name); } } }
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); }
public void ErrorLog(string text) { Syslog.ErrorLog(Name + ": " + text); }
public static void SystemLog(string Message, Syslog.Type MessageType) { }
/// <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> /// 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; }
/// <summary> /// System log /// </summary> /// <param name="text"></param> /// <param name="warning"></param> public void Log(string text, bool warning = false) { Syslog.Log(Name + ": " + text, warning); }
protected override void __evt_PRIVMSG(NetworkPRIVMSGEventArgs args) { if (Configuration.IgnoredHostmasks.Contains(args.SourceInfo.Host)) { // messages from this user are ignored return; } if (args.ChannelName == null) { // private message // store which instance this message was from so that we can send it using same instance lock (Instance.TargetBuffer) { if (!Instance.TargetBuffer.ContainsKey(args.SourceInfo.Nick)) { Instance.TargetBuffer.Add(args.SourceInfo.Nick, this.instance); } else { Instance.TargetBuffer[args.SourceInfo.Nick] = this.instance; } } string modules = ""; bool respond = !Commands.Trusted(args.Message, args.SourceInfo.Nick, args.SourceInfo.Host); if (!respond) { modules += "@trusted "; } foreach (Module module in ExtensionHandler.ExtensionList) { if (module.IsWorking) { try { if (module.Hook_OnPrivateFromUser(args.Message, args.SourceInfo)) { respond = false; modules += module.Name + " "; } } catch (Exception fail) { Core.HandleException(fail); } } } if (respond) { IRC.DeliverMessage("Hi, I am a robot, this command was not understood." + " Please bear in mind that every message you send" + " to me will be logged for debugging purposes. See" + " documentation for the bot at http://meta.wikimedia.org/wiki" + "/wm-bot for explanation of the bot's commands.", args.SourceInfo, libirc.Defs.Priority.Low); Syslog.Log("Ignoring private message: (" + args.SourceInfo.Nick + ") " + args.Message, false); } else { modules = Core.Trim(modules); Syslog.Log("Private message: (handled by " + modules + " from " + args.SourceInfo.Nick + ") " + args.Message, false); } } else { if (args.ChannelName == Configuration.System.DebugChan && this.instance != Instance.PrimaryInstance) { return; } if (args.IsAct) { Core.GetAction(args.Message, args.ChannelName, args.SourceInfo.Host, args.SourceInfo.Nick); return; } Core.GetMessage(args.ChannelName, args.SourceInfo.Nick, args.SourceInfo.Host, args.Message); } }
/// <summary> /// Start /// </summary> public virtual void Load() { Syslog.Log("Module " + Name + " is missing core thread, terminated", true); RestartOnModuleCrash = false; IsWorking = false; }
private static void Restart(CommandParams parameters) { IRC.DeliverMessage("System is shutting down, requested by " + parameters.User.Nick + " from " + parameters.SourceChannel.Name, Configuration.System.DebugChan, libirc.Defs.Priority.High); Syslog.Log("System is shutting down, requested by " + parameters.User.Nick + " from " + parameters.SourceChannel.Name); Core.Kill(); }
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> /// Initializes a new instance of the class. /// </summary> /// <param name='text'> /// Text. /// </param> /// <param name='time'> /// Time. /// </param> /// <param name='MT'> /// M. /// </param> public Message(string text, DateTime time, Syslog.Type MT) { this.Text = text; this.Time = time; this._Type = MT; }
private void ThreadExec() { try { if (!this._Connect()) { this.KillSelf("Unable to connect to remote"); return; } // why is this?? if (!IRCNetwork.IsConnected) { IRCNetwork.IsConnected = true; } while (!streamReader.EndOfStream && IsConnected) { string text; if (Backlog.Count > 0) { lock (Backlog) { text = Backlog[0]; Backlog.RemoveAt(0); } } else { text = streamReader.ReadLine(); } if (Configuration.IRC.UsingBouncer && text[0] == 'C' && text.StartsWith("CONTROL: ")) { if (text == "CONTROL: DC") { Syslog.Log("CACHE: Lost connection to remote on " + this.IRCNetwork.Nickname); this.ChannelsJoined = false; this.IsWorking = false; this.KillSelf("Lost connection to remote"); return; } } text = this.RawTraffic(text); this.TrafficLog(text, true); libirc.ProcessorIRC processor = new libirc.ProcessorIRC(IRCNetwork, text, ref LastPing); processor.ProfiledResult(); LastPing = processor.pong; } }catch (ThreadAbortException) { KillSelf("Thread aborted"); }catch (System.Net.Sockets.SocketException ex) { this.KillSelf(ex.Message); }catch (System.IO.IOException ex) { this.KillSelf(ex.Message); } catch (Exception fail) { Core.HandleException(fail); this.KillSelf(fail.Message); } }
/// <summary> /// The entry point of the program, where the program control starts and ends. /// </summary> /// <param name='args'> /// The command-line arguments. /// </param> private static void Main(string[] args) { try { Configuration.System.UpTime = DateTime.Now; Core.KernelThread = Thread.CurrentThread; Core.KernelThread.Name = "Kernel"; Configuration.System.Version += " [libirc v. " + libirc.Defs.Version.ToString() + "]"; Thread logger = new Thread(Logging.Exec) { Name = "Logger" }; Core.ThreadManager.RegisterThread(logger); ParseArgs(args); Syslog.WriteNow(Configuration.System.Version); Syslog.WriteNow("Loading..."); logger.Start(); Console.CancelKeyPress += SigInt; messages.LoadLD(); if (Configuration.Load() != 0) { Syslog.WriteNow("Error while loading the config file, exiting", true); Environment.Exit(-2); } Terminal.Init(); Core.Help.CreateHelp(); Core.WriterThread = new Thread(StorageWriter.Exec); Core.ThreadManager.RegisterThread(Core.WriterThread); Core.WriterThread.Name = "Writer"; Core.WriterThread.Start(); if (WMIBMySQL.IsAvailable) { Syslog.Log("Initializing MySQL"); Core.MysqlDB = new WMIBMySQL(); } else { Syslog.Log("Mysql is not configured, not using"); } if (PostgreSQL.IsAvailable) { Syslog.Log("Opening connection to PostgreDB"); Core.PostgreDB = new PostgreSQL(); Core.PostgreDB.Connect(); } else { Syslog.Log("Postgres is not configured, not using"); } // let's use postgre as default if (Core.PostgreDB != null) { Syslog.Log("Using Postgres as a default SQL provider"); Core.DB = Core.PostgreDB; } else if (Core.MysqlDB != null) { Syslog.Log("Using MySQL as a default SQL"); Core.DB = Core.MysqlDB; } // register all commands Commands.InitAdminCommands(); Syslog.Log("Loading modules"); ExtensionHandler.SearchMods(); Security.Init(); Security.Global(); Syslog.Log("Connecting"); IRC.Connect(); #if __MonoCS__ UnixSignal[] signals = { new UnixSignal(Signum.SIGINT), new UnixSignal(Signum.SIGTERM), new UnixSignal(Signum.SIGQUIT), new UnixSignal(Signum.SIGHUP) }; #endif while (Core.IsRunning) { #if __MonoCS__ int index = UnixSignal.WaitAny(signals, -1); Signum signal = signals [index].Signum; switch (signal) { case Signum.SIGINT: SigInt(null, null); goto exit; case Signum.SIGTERM: Syslog.WriteNow("SIGTERM - Shutting down", true); Core.Kill(); goto exit; } #endif Thread.Sleep(200); } #if __MonoCS__ exit: #endif // memory cleanup if (Core.DB != null) { ((WMIBMySQL)Core.DB).Dispose(); } } catch (Exception fatal) { Syslog.WriteNow("bot crashed, bellow is debugging information", Syslog.Type.Error); Console.WriteLine("------------------------------------------------------------------------"); Console.WriteLine("Description: " + fatal.Message); Console.WriteLine("Stack trace: " + fatal.StackTrace); Environment.Exit(-2); } }
public override void DebugLog(string Text, int Verbosity) { Syslog.DebugLog(Text, Verbosity); }
/// <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); 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 JSON() { try { string URL = "https://labsconsole.wikimedia.org/wiki/Special:Ask/-5B-5BResource-20Type::instance-5D-5D/-3FInstance-20Name/-3FInstance-20Type/-3FProject/-3FImage-20Id/-3FFQDN/-3FLaunch-20Time/-3FPuppet-20Class/-3FModification-20date/-3FInstance-20Host/-3FNumber-20of-20CPUs/-3FRAM-20Size/-3FAmount-20of-20Storage/limit%3D500/format%3Djson"; string temp = Path.GetTempFileName(); if (Download(URL, temp)) { List <Instance> deleted = new List <Instance>(); lock (Instances) { deleted.AddRange(Instances); } StreamReader a = File.OpenText(temp); JsonTextReader b = new JsonTextReader(a); string name = "{unknown}"; string host = "{unknown}"; string ip = "{unknown}"; string project = "{unknown}"; string resource = "{unknown}"; string image = "{unknown}"; string Ram = "{unknown}"; string NumberOfCpu = "{unknown}"; string ModifyTime = "{unknown}"; string Storage = "{unknown}"; string FullUrl = "{unknown}"; string fqdn = "{unknown}"; string LaunchTime = "{unknown}"; string type = "{unknown}"; while (b.Read()) { if (b.TokenType == JsonToken.PropertyName) { if (b.Value == null) { DebugLog("null at value"); continue; } string value = b.Value.ToString(); if (value.StartsWith("Nova Resource:")) { value = value.Substring("Nova Resource:".Length); if (resource != "{unknown}") { Instance instance = getInstance(resource); if (instance != null) { if (deleted.Contains(instance)) { deleted.Remove(instance); } deleteInstance(instance); } try { IPAddress[] addresslist = Dns.GetHostAddresses(resource); if (addresslist.Length > 0) { ip = addresslist[0].ToString(); } } catch (Exception) { DebugLog("can't resolve" + resource, 8); } instance = new Instance(resource, name, host, ip, type, true) { fqdn = fqdn, FullUrl = FullUrl, ImageID = image, LaunchTime = LaunchTime, ModifyTime = ModifyTime, NumberOfCpu = NumberOfCpu, Project = project, Ram = Ram, Storage = Storage }; lock (Instances) { Instances.Add(instance); } name = "{unknown}"; host = "{unknown}"; ip = "{unknown}"; project = "{unknown}"; resource = "{unknown}"; image = "{unknown}"; Ram = "{unknown}"; NumberOfCpu = "{unknown}"; ModifyTime = "{unknown}"; Storage = "{unknown}"; FullUrl = "{unknown}"; fqdn = "{unknown}"; LaunchTime = "{unknown}"; type = "{unknown}"; } resource = value; } switch (b.Value.ToString()) { case "Instance Name": name = getValue(ref b); break; case "Instance Type": type = getValue(ref b); break; case "Project": project = getValue(ref b); break; case "Image Id": image = getValue(ref b); break; case "FQDN": fqdn = getValue(ref b); break; case "Launch Time": continue; case "Puppet Class": break; case "Modification date": ModifyTime = getValue(ref b); break; case "Instance Host": host = getValue(ref b); break; case "Number of CPUs": NumberOfCpu = getValue(ref b); break; case "RAM Size": Ram = getValue(ref b); break; case "Amount of Storage": Storage = getValue(ref b); break; case "fullurl": FullUrl = getValue(ref b); break; } } } File.Delete(temp); foreach (Instance x in deleted) { deleteInstance(x); } } else { Syslog.Log("Labs: Failed to download db file", true); } URL = "https://labsconsole.wikimedia.org/wiki/Special:Ask/-5B-5BResource-20Type::project-5D-5D/-3F/-3FMember/-3FDescription/mainlabel%3D-2D/searchlabel%3Dprojects/offset%3D0/limit%3D500/format%3Djson"; temp = Path.GetTempFileName(); if (Download(URL, temp)) { StreamReader a = File.OpenText(temp); JsonTextReader b = new JsonTextReader(a); string name = "{unknown}"; List <Nova> projectlist2 = new List <Nova>(); List <string> members = new List <string>(); string description = "{unknown}"; while (b.Read()) { if (b.Value == null) { continue; } //Console.WriteLine(b.Value.ToString()); string value = b.Value.ToString(); if (value.StartsWith("Nova Resource:")) { value = value.Substring("Nova Resource:".Length); if (name != "{unknown}") { Nova project = null; foreach (Nova x in projectlist2) { if (x.Name == value) { project = x; break; } } if (project == null) { project = new Nova(name); } project.users.AddRange(members); if (!(description == "" && project.Description == "")) { project.Description = description; } else if (project.Description == "") { project.Description = "there is no description for this item"; } description = ""; if (!projectlist2.Contains(project)) { projectlist2.Add(project); } members.Clear(); } name = value; } if (value.StartsWith("User:"******"Description") { description = getValue(ref b, true); } } File.Delete(temp); lock (ProjectList) { ProjectList.Clear(); ProjectList.AddRange(projectlist2); } lock (Instances) { foreach (Instance i in Instances) { Nova nova = getProject(i.Project); if (nova != null) { i.project = nova; lock (nova.instances) { if (!nova.instances.Contains(i)) { nova.instances.Add(i); } } } } } } else { Syslog.Log("Failed to download db file", true); } OK = true; LastUpdate = DateTime.Now; } catch (Exception t) { Syslog.Log(t.Data + t.StackTrace); Core.HandleException(t, "Labs"); } }