private void TryProcessUnknown() { string name; using (MySqlDataReader MainReader = DbWorker.ExecuteReader("SELECT `Name` FROM `Subs` WHERE `SubID` = @SubID LIMIT 1", new MySqlParameter("SubID", SubID))) { if (!MainReader.Read()) { return; } name = DbWorker.GetString("Name", MainReader); } using (MySqlDataReader Reader = DbWorker.ExecuteReader("SELECT `Name`, `Key`, `Value` FROM `SubsInfo` INNER JOIN `KeyNamesSubs` ON `SubsInfo`.`Key` = `KeyNamesSubs`.`ID` WHERE `SubID` = @SubID", new MySqlParameter("SubID", SubID))) { while (Reader.Read()) { if (!DbWorker.GetString("Name", Reader).StartsWith("website", StringComparison.Ordinal)) { MakeHistory("removed_key", Reader.GetUInt32("Key"), DbWorker.GetString("Value", Reader)); } } } DbWorker.ExecuteNonQuery("DELETE FROM `Subs` WHERE `SubID` = @SubID", new MySqlParameter("@SubID", SubID)); DbWorker.ExecuteNonQuery("DELETE FROM `SubsInfo` WHERE `SubID` = @SubID", new MySqlParameter("@SubID", SubID)); DbWorker.ExecuteNonQuery("DELETE FROM `StoreSubs` WHERE `SubID` = @SubID", new MySqlParameter("@SubID", SubID)); // TODO MakeHistory("deleted_sub", 0, name); }
public void ReloadImportant(CommandHandler.CommandArguments command = null) { using (MySqlDataReader Reader = DbWorker.ExecuteReader("SELECT `AppID` FROM `ImportantApps` WHERE `Announce` = 1")) { ImportantApps.Clear(); while (Reader.Read()) { ImportantApps.Add(Reader.GetUInt32("AppID")); } } using (MySqlDataReader Reader = DbWorker.ExecuteReader("SELECT `SubID` FROM `ImportantSubs`")) { ImportantSubs.Clear(); while (Reader.Read()) { ImportantSubs.Add(Reader.GetUInt32("SubID")); } } if (command == null) { Log.WriteInfo("IRC Proxy", "Loaded {0} important apps and {1} packages", ImportantApps.Count, ImportantSubs.Count); } else { CommandHandler.ReplyToCommand(command, "{0}{1}{2}: Reloaded {3} important apps and {4} packages", Colors.OLIVE, command.Nickname, Colors.NORMAL, ImportantApps.Count, ImportantSubs.Count); } }
public static void OnMarketingMessage(SteamUser.MarketingMessageCallback callback) { foreach (var message in callback.Messages) { // TODO: Move this query outside this loop using (MySqlDataReader Reader = DbWorker.ExecuteReader("SELECT `ID` FROM `MarketingMessages` WHERE `ID` = @ID", new MySqlParameter("ID", message.ID))) { if (Reader.Read()) { continue; } } if (message.Flags == EMarketingMessageFlags.None) { IRC.SendMain("New marketing message:{0} {1}", Colors.DARK_BLUE, message.URL); } else { IRC.SendMain("New marketing message:{0} {1} {2}({3})", Colors.DARK_BLUE, message.URL, Colors.DARK_GRAY, message.Flags.ToString().Replace("Platform", string.Empty)); } DbWorker.ExecuteNonQuery("INSERT INTO `MarketingMessages` (`ID`, `Flags`) VALUES (@ID, @Flags)", new MySqlParameter("@ID", message.ID), new MySqlParameter("@Flags", message.Flags) ); } }
private void GetLastChangeNumber() { // If we're in a full run, request all changes from #1 if (Settings.IsFullRun) { PreviousChange = 1; return; } using (MySqlDataReader Reader = DbWorker.ExecuteReader("SELECT `ChangeID` FROM `Changelists` ORDER BY `ChangeID` DESC LIMIT 1")) { if (Reader.Read()) { PreviousChange = Reader.GetUInt32("ChangeID"); Log.WriteInfo("Steam", "Previous changelist was {0}", PreviousChange); } } if (PreviousChange == 0) { Log.WriteWarn("Steam", "Looks like there are no changelists in the database."); Log.WriteWarn("Steam", "If you want to fill up your database first, restart with \"FullRun\" setting set to 1."); } }
private static void OnCommandApp(CommandArguments command) { if (command.Message.Length == 0) { ReplyToCommand(command, "Usage:{0} !app <appid or partial game name>", Colors.OLIVE); return; } uint appID; if (uint.TryParse(command.Message, out appID)) { var apps = new List <uint>(); apps.Add(appID); var jobID = Steam.Instance.Apps.PICSGetAccessTokens(apps, Enumerable.Empty <uint>()); SteamProxy.Instance.IRCRequests.Add(new SteamProxy.IRCRequest { JobID = jobID, Target = appID, Type = SteamProxy.IRCRequestType.TYPE_APP, Command = command }); } else { string name = string.Format("%{0}%", command.Message); using (MySqlDataReader Reader = DbWorker.ExecuteReader("SELECT `AppID` FROM `Apps` WHERE `Apps`.`StoreName` LIKE @Name OR `Apps`.`Name` LIKE @Name ORDER BY `LastUpdated` DESC LIMIT 1", new MySqlParameter("Name", name))) { if (Reader.Read()) { appID = Reader.GetUInt32("AppID"); var apps = new List <uint>(); apps.Add(appID); var jobID = Steam.Instance.Apps.PICSGetAccessTokens(apps, Enumerable.Empty <uint>()); SteamProxy.Instance.IRCRequests.Add(new SteamProxy.IRCRequest { JobID = jobID, Target = appID, Type = SteamProxy.IRCRequestType.TYPE_APP, Command = command }); } else { ReplyToCommand(command, "{0}{1}{2}: Nothing was found matching your request", Colors.OLIVE, command.Nickname, Colors.NORMAL); } } } }
private static uint GetKeyNameID(string keyName) { using (MySqlDataReader Reader = DbWorker.ExecuteReader("SELECT `ID` FROM `KeyNamesSubs` WHERE `Name` = @KeyName LIMIT 1", new MySqlParameter("KeyName", keyName))) { if (Reader.Read()) { return(Reader.GetUInt32("ID")); } } return(0); }
private static void OnCommandPlayers(CommandArguments command) { if (command.Message.Length == 0) { ReplyToCommand(command, "Usage:{0} !players <appid or partial game name>", Colors.OLIVE); return; } uint appID; if (uint.TryParse(command.Message, out appID)) { var jobID = Steam.Instance.UserStats.GetNumberOfCurrentPlayers(appID); SteamProxy.Instance.IRCRequests.Add(new SteamProxy.IRCRequest { JobID = jobID, Target = appID, Command = command }); } else { string name = string.Format("%{0}%", command.Message); using (MySqlDataReader Reader = DbWorker.ExecuteReader("SELECT `AppID` FROM `Apps` LEFT JOIN `AppsTypes` ON `Apps`.`AppType` = `AppsTypes`.`AppType` WHERE `AppsTypes`.`Name` IN ('game', 'application') AND (`Apps`.`StoreName` LIKE @Name OR `Apps`.`Name` LIKE @Name) ORDER BY `LastUpdated` DESC LIMIT 1", new MySqlParameter("Name", name))) { if (Reader.Read()) { appID = Reader.GetUInt32("AppID"); var jobID = Steam.Instance.UserStats.GetNumberOfCurrentPlayers(appID); SteamProxy.Instance.IRCRequests.Add(new SteamProxy.IRCRequest { JobID = jobID, Target = appID, Command = command }); } else { ReplyToCommand(command, "{0}{1}{2}: Nothing was found matching your request", Colors.OLIVE, command.Nickname, Colors.NORMAL); } } } }
private void TryProcessUnknown() { string AppName; using (MySqlDataReader MainReader = DbWorker.ExecuteReader("SELECT `Name` FROM `Apps` WHERE `AppID` = @AppID LIMIT 1", new MySqlParameter("AppID", AppID))) { if (!MainReader.Read()) { return; } AppName = DbWorker.GetString("Name", MainReader); } bool historyChanged = false; using (MySqlDataReader Reader = DbWorker.ExecuteReader("SELECT `Name`, `Key`, `Value` FROM `AppsInfo` INNER JOIN `KeyNames` ON `AppsInfo`.`Key` = `KeyNames`.`ID` WHERE `AppID` = @AppID", new MySqlParameter("AppID", AppID))) { while (Reader.Read()) { if (!DbWorker.GetString("Name", Reader).StartsWith("website", StringComparison.Ordinal)) { MakeHistory("removed_key", Reader.GetUInt32("Key"), DbWorker.GetString("Value", Reader)); historyChanged = true; } } } DbWorker.ExecuteNonQuery("DELETE FROM `Apps` WHERE `AppID` = @AppID", new MySqlParameter("@AppID", AppID)); DbWorker.ExecuteNonQuery("DELETE FROM `AppsInfo` WHERE `AppID` = @AppID", new MySqlParameter("@AppID", AppID)); DbWorker.ExecuteNonQuery("DELETE FROM `Store` WHERE `AppID` = @AppID", new MySqlParameter("@AppID", AppID)); if (!AppName.StartsWith(SteamDB.UNKNOWN_APP, StringComparison.Ordinal)) { MakeHistory("deleted_app", 0, AppName); historyChanged = true; } // TODO: This is a dirty hack so we somehow track these app changes if (!historyChanged && !Settings.IsFullRun) { MakeHistory("removed_key", GetKeyNameID("root_change_number"), "0", "0"); } }
public static string GetAppName(uint appID, bool returnEmptyOnFailure = false) { using (MySqlDataReader reader = DbWorker.ExecuteReader("SELECT `Name`, `StoreName`, `LastKnownName` FROM `Apps` WHERE `AppID` = @AppID", new MySqlParameter("AppID", appID))) { if (reader.Read()) { string name = DbWorker.GetString("Name", reader); //string nameStore = DbWorker.GetString("StoreName", reader); string nameLast = DbWorker.GetString("LastKnownName", reader); if (!string.IsNullOrEmpty(nameLast) && !name.Equals(nameLast)) { return(string.Format("{0} {1}({2}){3}", name, Colors.DARK_GRAY, nameLast, Colors.NORMAL)); } return(name); } } return(returnEmptyOnFailure ? string.Empty : string.Format("AppID {0}", appID)); }
public void OnNumberOfPlayers(SteamUserStats.NumberOfPlayersCallback callback, JobID jobID) { var request = IRCRequests.Find(r => r.JobID == jobID); if (request == null) { return; } IRCRequests.Remove(request); if (callback.Result != EResult.OK) { CommandHandler.ReplyToCommand(request.Command, "{0}{1}{2}: Unable to request player count: {3}", Colors.OLIVE, request.Command.Nickname, Colors.NORMAL, callback.Result); } else if (request.Target == 0) { CommandHandler.ReplyToCommand(request.Command, "{0}{1}{2}: {3}{4:N0}{5} people praising lord Gaben right now, influence:{6} {7}", Colors.OLIVE, request.Command.Nickname, Colors.NORMAL, Colors.OLIVE, callback.NumPlayers, Colors.NORMAL, Colors.DARK_BLUE, SteamDB.GetGraphURL(0)); } else { string graphUrl = string.Empty; string name = GetAppName(request.Target); using (MySqlDataReader Reader = DbWorker.ExecuteReader("SELECT `AppID` FROM `ImportantApps` WHERE (`Graph` = 1 OR `MaxPlayers` > 0) AND `AppID` = @AppID", new MySqlParameter("AppID", request.Target))) { if (Reader.Read()) { graphUrl = string.Format("{0} -{1} {2}", Colors.NORMAL, Colors.DARK_BLUE, SteamDB.GetGraphURL(request.Target)); } } CommandHandler.ReplyToCommand(request.Command, "{0}{1}{2}: People playing {3}{4}{5} right now: {6}{7:N0}{8} -{9} {10}{11}", Colors.OLIVE, request.Command.Nickname, Colors.NORMAL, Colors.OLIVE, name, Colors.NORMAL, Colors.GREEN, callback.NumPlayers, Colors.NORMAL, Colors.DARK_BLUE, SteamDB.GetAppURL(request.Target), graphUrl); } }
public static string GetPackageName(uint subID, bool returnEmptyOnFailure = false) { using (MySqlDataReader Reader = DbWorker.ExecuteReader("SELECT `Name`, `StoreName` FROM `Subs` WHERE `SubID` = @SubID", new MySqlParameter("SubID", subID))) { if (Reader.Read()) { string name = DbWorker.GetString("Name", Reader); if (name.StartsWith("Steam Sub", StringComparison.Ordinal)) { string nameStore = DbWorker.GetString("StoreName", Reader); if (!string.IsNullOrEmpty(nameStore)) { name = string.Format("{0} {1}({2}){3}", name, Colors.DARK_GRAY, nameStore, Colors.NORMAL); } } return(name); } } return(returnEmptyOnFailure ? string.Empty : string.Format("SubID {0}", subID)); }
public static void Process(uint appID, uint changeNumber, KeyValue depots) { foreach (KeyValue depot in depots.Children) { // Ignore these for now, parent app should be updated too anyway if (depot["depotfromapp"].Value != null) { ////Log.WriteDebug("Depot Processor", "Ignoring depot {0} with depotfromapp value {1} (parent {2})", depot.Name, depot["depotfromapp"].AsString(), AppID); continue; } uint depotID; if (!uint.TryParse(depot.Name, out depotID)) { // Ignore keys that aren't integers, for example "branches" continue; } lock (ManifestJobs) { if (ManifestJobs.Find(r => r.DepotID == depotID) != null) { // If we already have this depot in our job list, ignore it continue; } } ulong manifestID; if (depot["manifests"]["public"].Value == null || !ulong.TryParse(depot["manifests"]["public"].Value, out manifestID)) { #if false Log.WriteDebug("Depot Processor", "Failed to public branch for depot {0} (parent {1}) - {2}", DepotID, AppID); // If there is no public manifest for this depot, it still could have some sort of open beta var branch = depot["manifests"].Children.SingleOrDefault(x => x.Name != "local"); if (branch == null || !ulong.TryParse(branch.Value, out ManifestID)) { continue; } #endif continue; } var request = new ManifestJob { ChangeNumber = changeNumber, ParentAppID = appID, DepotID = depotID, ManifestID = manifestID, DepotName = depot["name"].AsString() }; // Check if manifestid in our database is equal using (MySqlDataReader Reader = DbWorker.ExecuteReader("SELECT `ManifestID` FROM `Depots` WHERE `DepotID` = @DepotID AND `Files` != '' LIMIT 1", new MySqlParameter("DepotID", depotID))) { if (Reader.Read()) { request.PreviousManifestID = Reader.GetUInt64("ManifestID"); if (request.PreviousManifestID == manifestID && Settings.Current.FullRun < 2) { continue; } } } lock (ManifestJobs) { ManifestJobs.Add(request); } request.Server = CDNServers[new Random().Next(CDNServers.Count)]; request.JobID = Steam.Instance.Apps.GetCDNAuthToken(depotID, request.Server); } }
private static void DownloadManifest(ManifestJob request) { DepotManifest depotManifest = null; string lastError = string.Empty; // CDN is very random, just keep trying for (var i = 0; i <= 5; i++) { try { depotManifest = CDNClient.DownloadManifest(request.DepotID, request.ManifestID, request.Server, request.DepotKey, request.CDNToken); break; } catch (Exception e) { lastError = e.Message; } } if (depotManifest == null) { Log.WriteError("Depot Processor", "Failed to download depot manifest for depot {0} (jobs still in queue: {1}) ({2}: {3})", request.DepotID, ManifestJobs.Count - 1, request.Server, lastError); if (SteamProxy.Instance.ImportantApps.Contains(request.ParentAppID)) { IRC.SendMain("Important depot update: {0}{1}{2} -{3} failed to download depot manifest", Colors.OLIVE, request.DepotName, Colors.NORMAL, Colors.RED); } return; } if (SteamProxy.Instance.ImportantApps.Contains(request.ParentAppID)) { IRC.SendMain("Important depot update: {0}{1}{2} -{3} {4}", Colors.OLIVE, request.DepotName, Colors.NORMAL, Colors.DARK_BLUE, SteamDB.GetDepotURL(request.DepotID, "history")); } var sortedFiles = depotManifest.Files.OrderBy(f => f.FileName, StringComparer.OrdinalIgnoreCase); bool shouldHistorize = false; var filesNew = new List <DepotFile>(); var filesOld = new Dictionary <string, DepotFile>(); foreach (var file in sortedFiles) { System.Text.Encoding.UTF8.GetString(file.FileHash); var depotFile = new DepotFile { Name = file.FileName.Replace('\\', '/'), Size = file.TotalSize, Chunks = file.Chunks.Count, Flags = (int)file.Flags }; // TODO: Ideally we would check if filehash is not empty if (!file.Flags.HasFlag(EDepotFileFlag.Directory)) { depotFile.Hash = string.Concat(Array.ConvertAll(file.FileHash, x => x.ToString("X2"))); } filesNew.Add(depotFile); } using (MySqlDataReader Reader = DbWorker.ExecuteReader("SELECT `Files` FROM `Depots` WHERE `DepotID` = @DepotID LIMIT 1", new MySqlParameter("DepotID", request.DepotID))) { if (Reader.Read()) { string files = Reader.GetString("Files"); if (!string.IsNullOrEmpty(files)) { shouldHistorize = true; var _filesOld = JsonConvert.DeserializeObject <List <DepotFile> >(files); filesOld = _filesOld.ToDictionary(x => x.Name); } } } DbWorker.ExecuteNonQuery("UPDATE `Depots` SET `Files` = @Files WHERE `DepotID` = @DepotID", new MySqlParameter("@DepotID", request.DepotID), new MySqlParameter("@Files", JsonConvert.SerializeObject(filesNew, new JsonSerializerSettings { DefaultValueHandling = DefaultValueHandling.Ignore })) ); if (shouldHistorize) { var filesAdded = new List <string>(); foreach (var file in filesNew) { if (filesOld.ContainsKey(file.Name)) { var oldFile = filesOld[file.Name]; if (oldFile.Size != file.Size) { MakeHistory(request, file.Name, "modified", oldFile.Size, file.Size); } else if (file.Hash != null && oldFile.Hash != null && !file.Hash.Equals(oldFile.Hash)) { MakeHistory(request, file.Name, "modified", oldFile.Size, file.Size); } filesOld.Remove(file.Name); } else { // We want to historize modifications first, and only then deletions and additions filesAdded.Add(file.Name); } } foreach (var file in filesOld) { MakeHistory(request, file.Value.Name, "removed"); } foreach (string file in filesAdded) { MakeHistory(request, file, "added"); } } lock (ManifestJobs) { Log.WriteDebug("Depot Processor", "DepotID: Processed {0} (jobs still in queue: {1})", request.DepotID, ManifestJobs.Count - 1); } }
private void TryProcess(SteamApps.PICSProductInfoCallback.PICSProductInfo productInfo) { string packageName = string.Empty; var apps = new Dictionary <uint, string>(); using (MySqlDataReader Reader = DbWorker.ExecuteReader("SELECT `Name`, `Value` FROM `SubsInfo` INNER JOIN `KeyNamesSubs` ON `SubsInfo`.`Key` = `KeyNamesSubs`.`ID` WHERE `SubID` = @SubID", new MySqlParameter("@SubID", SubID))) { while (Reader.Read()) { CurrentData.Add(DbWorker.GetString("Name", Reader), DbWorker.GetString("Value", Reader)); } } using (MySqlDataReader Reader = DbWorker.ExecuteReader("SELECT `Name` FROM `Subs` WHERE `SubID` = @SubID LIMIT 1", new MySqlParameter("@SubID", SubID))) { if (Reader.Read()) { packageName = DbWorker.GetString("Name", Reader); } } using (MySqlDataReader Reader = DbWorker.ExecuteReader("SELECT `AppID`, `Type` FROM `SubsApps` WHERE `SubID` = @SubID", new MySqlParameter("@SubID", SubID))) { while (Reader.Read()) { apps.Add(Reader.GetUInt32("AppID"), Reader.GetString("Type")); } } var kv = productInfo.KeyValues.Children.FirstOrDefault(); if (kv["name"].Value != null) { if (string.IsNullOrEmpty(packageName)) { DbWorker.ExecuteNonQuery("INSERT INTO `Subs` (`SubID`, `Name`) VALUES (@SubID, @Name) ON DUPLICATE KEY UPDATE `Name` = @Name", new MySqlParameter("@SubID", SubID), new MySqlParameter("@Name", kv["name"].Value) ); MakeHistory("created_sub"); MakeHistory("created_info", DATABASE_NAME_TYPE, string.Empty, kv["name"].Value); } else if (!packageName.Equals(kv["name"].Value)) { DbWorker.ExecuteNonQuery("UPDATE `Subs` SET `Name` = @Name WHERE `SubID` = @SubID", new MySqlParameter("@SubID", SubID), new MySqlParameter("@Name", kv["name"].Value) ); MakeHistory("modified_info", DATABASE_NAME_TYPE, packageName, kv["name"].Value); } } foreach (KeyValue section in kv.Children) { string sectionName = section.Name.ToLower(); if (string.IsNullOrEmpty(sectionName) || sectionName.Equals("packageid") || sectionName.Equals("name")) { // Ignore common keys continue; } if (sectionName.Equals("appids") || sectionName.Equals("depotids")) { string type = sectionName.Replace("ids", string.Empty); // Remove "ids", so we get app from appids and depot from depotids uint typeID = (uint)(type.Equals("app") ? 0 : 1); // TODO: Remove legacy 0/1 and replace with type foreach (KeyValue childrenApp in section.Children) { uint appID = uint.Parse(childrenApp.Value); // Is this appid already in this package? if (apps.ContainsKey(appID)) { // Is this appid's type the same? if (apps[appID] != type) { DbWorker.ExecuteNonQuery("UPDATE `SubsApps` SET `Type` = @Type WHERE `SubID` = @SubID AND `AppID` = @AppID", new MySqlParameter("@SubID", SubID), new MySqlParameter("@AppID", appID), new MySqlParameter("@Type", type) ); MakeHistory("added_to_sub", typeID, apps[appID].Equals("app") ? "0" : "1", childrenApp.Value); } apps.Remove(appID); } else { DbWorker.ExecuteNonQuery("INSERT INTO `SubsApps` (`SubID`, `AppID`, `Type`) VALUES(@SubID, @AppID, @Type) ON DUPLICATE KEY UPDATE `Type` = @Type", new MySqlParameter("@SubID", SubID), new MySqlParameter("@AppID", appID), new MySqlParameter("@Type", type) ); MakeHistory("added_to_sub", typeID, string.Empty, childrenApp.Value); AppProcessor.MakeHistory(appID, ChangeNumber, "added_to_sub", typeID, string.Empty, SubID.ToString()); if (SteamProxy.Instance.ImportantApps.Contains(appID)) { IRC.SendMain("Important app {0}{1}{2} was added to package {3}{4}{5} -{6} {7}", Colors.OLIVE, SteamProxy.GetAppName(appID), Colors.NORMAL, Colors.OLIVE, packageName, Colors.NORMAL, Colors.DARK_BLUE, SteamDB.GetPackageURL(SubID, "history") ); } } } } else if (sectionName.Equals("extended")) { string keyName; foreach (KeyValue children in section.Children) { if (children.Children.Count > 0) { Log.WriteError("Sub Processor", "SubID {0} has childen in extended section", SubID); } keyName = string.Format("{0}_{1}", sectionName, children.Name); ProcessKey(keyName, children.Name, children.Value); } } else if (section.Children.Count > 0) { sectionName = string.Format("root_{0}", sectionName); ProcessKey(sectionName, sectionName, DbWorker.JsonifyKeyValue(section), true); } else if (!string.IsNullOrEmpty(section.Value)) { string keyName = string.Format("root_{0}", sectionName); ProcessKey(keyName, sectionName, section.Value); } } foreach (string keyName in CurrentData.Keys) { if (!keyName.StartsWith("website", StringComparison.Ordinal)) { uint ID = GetKeyNameID(keyName); DbWorker.ExecuteNonQuery("DELETE FROM `SubsInfo` WHERE `SubID` = @SubID AND `Key` = @KeyNameID", new MySqlParameter("@SubID", SubID), new MySqlParameter("@KeyNameID", ID) ); MakeHistory("removed_key", ID, CurrentData[keyName]); } } foreach (var app in apps) { DbWorker.ExecuteNonQuery("DELETE FROM `SubsApps` WHERE `SubID` = @SubID AND `AppID` = @AppID AND `Type` = @Type", new MySqlParameter("@SubID", SubID), new MySqlParameter("@AppID", app.Key), new MySqlParameter("@Type", app.Value) ); uint typeID = (uint)(app.Value.Equals("app") ? 0 : 1); // TODO: Remove legacy 0/1 and replace with type MakeHistory("removed_from_sub", typeID, app.Key.ToString()); AppProcessor.MakeHistory(app.Key, ChangeNumber, "removed_from_sub", typeID, SubID.ToString()); if (SteamProxy.Instance.ImportantApps.Contains(app.Key)) { IRC.SendMain("Important app {0}{1}{2} was removed from package {3}{4}{5} -{6} {7}", Colors.OLIVE, SteamProxy.GetAppName(app.Key), Colors.NORMAL, Colors.OLIVE, packageName, Colors.NORMAL, Colors.DARK_BLUE, SteamDB.GetPackageURL(SubID, "history") ); } } #if DEBUG if (kv["name"].Value == null) { if (string.IsNullOrEmpty(packageName)) // We don't have the package in our database yet { // Don't do anything then Log.WriteError("Sub Processor", "Got a package without a name, and we don't have it in our database: {0}", SubID); } else { ////MakeHistory("deleted_sub", "0", packageName, "", true); Log.WriteError("Sub Processor", "Got a package without a name, but we have it in our database: {0}", SubID); } } #endif }
private void TryProcess(SteamApps.PICSProductInfoCallback.PICSProductInfo productInfo) { using (MySqlDataReader Reader = DbWorker.ExecuteReader("SELECT `Name`, `Value` FROM `AppsInfo` INNER JOIN `KeyNames` ON `AppsInfo`.`Key` = `KeyNames`.`ID` WHERE `AppID` = @AppID", new MySqlParameter("AppID", AppID))) { while (Reader.Read()) { CurrentData.Add(DbWorker.GetString("Name", Reader), DbWorker.GetString("Value", Reader)); } } string appName = string.Empty; string appType = "0"; using (MySqlDataReader Reader = DbWorker.ExecuteReader("SELECT `Name`, `AppType` FROM `Apps` WHERE `AppID` = @AppID LIMIT 1", new MySqlParameter("AppID", AppID))) { if (Reader.Read()) { appName = DbWorker.GetString("Name", Reader); appType = DbWorker.GetString("AppType", Reader); } } if (productInfo.KeyValues["common"]["name"].Value != null) { string newAppType = "0"; string currentType = productInfo.KeyValues["common"]["type"].AsString().ToLower(); using (MySqlDataReader Reader = DbWorker.ExecuteReader("SELECT `AppType` FROM `AppsTypes` WHERE `Name` = @Type LIMIT 1", new MySqlParameter("Type", currentType))) { if (Reader.Read()) { newAppType = DbWorker.GetString("AppType", Reader); } else { // TODO: Create it? Log.WriteError("App Processor", "AppID {0} - unknown app type: {1}", AppID, currentType); // TODO: This is debuggy just so we are aware of new app types IRC.SendAnnounce("Unknown app type \"{0}\" for appid {1}, cc Alram and xPaw", currentType, AppID); } } if (string.IsNullOrEmpty(appName) || appName.StartsWith(SteamDB.UNKNOWN_APP, StringComparison.Ordinal)) { DbWorker.ExecuteNonQuery("INSERT INTO `Apps` (`AppID`, `AppType`, `Name`) VALUES (@AppID, @Type, @AppName) ON DUPLICATE KEY UPDATE `Name` = @AppName, `AppType` = @Type", new MySqlParameter("@AppID", AppID), new MySqlParameter("@Type", newAppType), new MySqlParameter("@AppName", productInfo.KeyValues["common"]["name"].Value) ); MakeHistory("created_app"); MakeHistory("created_info", DATABASE_NAME_TYPE, string.Empty, productInfo.KeyValues["common"]["name"].Value); // TODO: Testy testy if (!Settings.IsFullRun && Settings.Current.ChatRooms.Count > 0 && !appName.StartsWith("SteamApp", StringComparison.Ordinal) && !appName.StartsWith("ValveTest", StringComparison.Ordinal)) { Steam.Instance.Friends.SendChatRoomMessage(Settings.Current.ChatRooms[0], EChatEntryType.ChatMsg, string.Format( ":retreat: New {0} was published: {1}\nSteamDB: {2}\nSteam: http://store.steampowered.com/app/{3}/", currentType, productInfo.KeyValues["common"]["name"].AsString(), SteamDB.GetAppURL(AppID), AppID ) ); } } else if (!appName.Equals(productInfo.KeyValues["common"]["name"].Value)) { string newAppName = productInfo.KeyValues["common"]["name"].AsString(); DbWorker.ExecuteNonQuery("UPDATE `Apps` SET `Name` = @AppName WHERE `AppID` = @AppID", new MySqlParameter("@AppID", AppID), new MySqlParameter("@AppName", newAppName) ); MakeHistory("modified_info", DATABASE_NAME_TYPE, appName, newAppName); // TODO: Testy testy if (!Settings.IsFullRun && Settings.Current.ChatRooms.Count > 0 && !string.Equals(appName, newAppName, StringComparison.OrdinalIgnoreCase) && !newAppName.StartsWith("SteamApp", StringComparison.Ordinal) && !newAppName.StartsWith("ValveTest", StringComparison.Ordinal)) { Steam.Instance.Friends.SendChatRoomMessage(Settings.Current.ChatRooms[0], EChatEntryType.ChatMsg, string.Format( ":retreat: {0} name was changed - {1}\n« {2}\n» {3}", currentType, SteamDB.GetAppURL(AppID, "history"), appName, newAppName ) ); } } if (appType.Equals("0")) { DbWorker.ExecuteNonQuery("UPDATE `Apps` SET `AppType` = @Type WHERE `AppID` = @AppID", new MySqlParameter("@AppID", AppID), new MySqlParameter("@Type", newAppType) ); MakeHistory("created_info", DATABASE_APPTYPE, string.Empty, newAppType); } else if (!appType.Equals(newAppType)) { DbWorker.ExecuteNonQuery("UPDATE `Apps` SET `AppType` = @Type WHERE `AppID` = @AppID", new MySqlParameter("@AppID", AppID), new MySqlParameter("@Type", newAppType) ); MakeHistory("modified_info", DATABASE_APPTYPE, appType, newAppType); } } // If we are full running, process depots too bool depotsSectionModified = Settings.IsFullRun && productInfo.KeyValues["depots"].Children.Count > 0; foreach (KeyValue section in productInfo.KeyValues.Children) { string sectionName = section.Name.ToLower(); if (sectionName == "appid" || sectionName == "public_only") { continue; } if (sectionName == "change_number") // Carefully handle change_number { sectionName = "root_change_number"; // TODO: Remove this key, move it to Apps table itself ProcessKey(sectionName, "change_number", productInfo.ChangeNumber.ToString()); //section.AsString()); } else if (sectionName == "common" || sectionName == "extended") { string keyName; foreach (KeyValue keyvalue in section.Children) { keyName = string.Format("{0}_{1}", sectionName, keyvalue.Name); if (keyName.Equals("common_type") || keyName.Equals("common_gameid") || keyName.Equals("common_name") || keyName.Equals("extended_order")) { // Ignore common keys that are either duplicated or serve no real purpose continue; } if (keyvalue.Children.Count > 0) { if (keyName.Equals("common_languages")) { ProcessKey(keyName, keyvalue.Name, string.Join(",", keyvalue.Children.Select(x => x.Name))); } else { ProcessKey(keyName, keyvalue.Name, DbWorker.JsonifyKeyValue(keyvalue), true); } } else if (!string.IsNullOrEmpty(keyvalue.Value)) { ProcessKey(keyName, keyvalue.Name, keyvalue.Value); } } } else { sectionName = string.Format("root_{0}", sectionName); if (ProcessKey(sectionName, sectionName, DbWorker.JsonifyKeyValue(section), true) && sectionName.Equals("root_depots")) { depotsSectionModified = true; } } } foreach (string keyName in CurrentData.Keys) { if (!keyName.StartsWith("website", StringComparison.Ordinal)) { uint ID = GetKeyNameID(keyName); DbWorker.ExecuteNonQuery("DELETE FROM AppsInfo WHERE `AppID` = @AppID AND `Key` = @KeyNameID", new MySqlParameter("@AppID", AppID), new MySqlParameter("@KeyNameID", ID) ); MakeHistory("removed_key", ID, CurrentData[keyName]); } } if (productInfo.KeyValues["common"]["name"].Value == null) { if (string.IsNullOrEmpty(appName)) // We don't have the app in our database yet { DbWorker.ExecuteNonQuery("INSERT INTO `Apps` (`AppID`, `Name`) VALUES (@AppID, @AppName) ON DUPLICATE KEY UPDATE `AppType` = `AppType`", new MySqlParameter("@AppID", AppID), new MySqlParameter("@AppName", string.Format("{0} {1}", SteamDB.UNKNOWN_APP, AppID)) ); } else if (!appName.StartsWith(SteamDB.UNKNOWN_APP, StringComparison.Ordinal)) // We do have the app, replace it with default name { DbWorker.ExecuteNonQuery("UPDATE `Apps` SET `Name` = @AppName, `AppType` = 0 WHERE `AppID` = @AppID", new MySqlParameter("@AppID", AppID), new MySqlParameter("@AppName", string.Format("{0} {1}", SteamDB.UNKNOWN_APP, AppID)) ); MakeHistory("deleted_app", 0, appName); } } if (depotsSectionModified) { DepotProcessor.Process(AppID, ChangeNumber, productInfo.KeyValues["depots"]); } }