protected override async Task ProcessData() { ChangeNumber = ProductInfo.ChangeNumber; if (Settings.IsFullRun) { await DbConnection.ExecuteAsync("INSERT INTO `Changelists` (`ChangeID`) VALUES (@ChangeNumber) ON DUPLICATE KEY UPDATE `Date` = `Date`", new { ProductInfo.ChangeNumber }); await DbConnection.ExecuteAsync("INSERT INTO `ChangelistsApps` (`ChangeID`, `AppID`) VALUES (@ChangeNumber, @AppID) ON DUPLICATE KEY UPDATE `AppID` = `AppID`", new { AppID, ProductInfo.ChangeNumber }); } await ProcessKey("root_changenumber", "changenumber", ChangeNumber.ToString()); var app = (await DbConnection.QueryAsync <App>("SELECT `Name`, `AppType` FROM `Apps` WHERE `AppID` = @AppID LIMIT 1", new { AppID })).SingleOrDefault(); var isPublicOnly = false; var newAppName = ProductInfo.KeyValues["common"]["name"].AsString(); var newAppType = EAppType.Invalid; if (newAppName != null) { var currentType = ProductInfo.KeyValues["common"]["type"].AsString().ToLowerInvariant(); newAppType = Utils.GetAppType(currentType); var modifiedNameOrType = false; if (string.IsNullOrEmpty(app.Name) || app.Name.StartsWith(SteamDB.UnknownAppName, StringComparison.Ordinal)) { await DbConnection.ExecuteAsync("INSERT INTO `Apps` (`AppID`, `AppType`, `Name`, `LastKnownName`) VALUES (@AppID, @Type, @AppName, @AppName) ON DUPLICATE KEY UPDATE `Name` = VALUES(`Name`), `LastKnownName` = VALUES(`LastKnownName`), `AppType` = VALUES(`AppType`)", new { AppID, Type = (int)newAppType, AppName = newAppName } ); await MakeHistory("created_app"); await MakeHistory("created_info", SteamDB.DatabaseNameType, string.Empty, newAppName); modifiedNameOrType = true; } else if (app.Name != newAppName) { await DbConnection.ExecuteAsync("UPDATE `Apps` SET `Name` = @AppName, `LastKnownName` = @AppName WHERE `AppID` = @AppID", new { AppID, AppName = newAppName }); await MakeHistory("modified_info", SteamDB.DatabaseNameType, app.Name, newAppName); modifiedNameOrType = true; } if (app.AppType != newAppType) { await DbConnection.ExecuteAsync("UPDATE `Apps` SET `AppType` = @Type WHERE `AppID` = @AppID", new { AppID, Type = (int)newAppType }); if (app.AppType == EAppType.Invalid) { await MakeHistory("created_info", SteamDB.DatabaseAppType, string.Empty, newAppType.ToString("d")); } else { await MakeHistory("modified_info", SteamDB.DatabaseAppType, app.AppType.ToString(), newAppType.ToString("d")); } modifiedNameOrType = true; } if (modifiedNameOrType && Triggers.Any(newAppName.Contains)) { IRC.Instance.SendOps($"New {newAppType}: {Colors.BLUE}{Utils.LimitStringLength(newAppName)}{Colors.NORMAL} -{Colors.DARKBLUE} {SteamDB.GetAppUrl(AppID, "history")}"); } } foreach (var section in ProductInfo.KeyValues.Children) { var sectionName = section.Name.ToLowerInvariant(); if (sectionName == "appid" || sectionName == "change_number") { continue; } if (sectionName == "common" || sectionName == "extended") { foreach (var keyvalue in section.Children) { var keyName = $"{sectionName}_{keyvalue.Name}"; if (keyName == "common_type" || keyName == "common_gameid" || keyName == "common_name" || keyName == "extended_order") { // Ignore common keys that are either duplicated or serve no real purpose continue; } if (keyvalue.Value != null) { await ProcessKey(keyName, keyvalue.Name, keyvalue.Value); } else { await ProcessKey(keyName, keyvalue.Name, Utils.JsonifyKeyValue(keyvalue), keyvalue); } } } else if (sectionName == "public_only") { isPublicOnly = section.Value == "1"; await ProcessKey($"root_{sectionName}", section.Name, section.Value); } else { sectionName = $"root_{sectionName}"; if (await ProcessKey(sectionName, sectionName, Utils.JsonifyKeyValue(section), section) && sectionName == "root_depots") { await DbConnection.ExecuteAsync("UPDATE `Apps` SET `LastDepotUpdate` = CURRENT_TIMESTAMP() WHERE `AppID` = @AppID", new { AppID }); } } } // If app gets hidden but we already have data, do not delete the already existing app info if (newAppName != null) { foreach (var data in CurrentData.Values) { // This key still exists in appinfo and was correctly processed above if (data.Processed) { continue; } // This is a key that is created and handled by steamdb.info; not in appinfo if (data.KeyName.StartsWith("website", StringComparison.Ordinal)) { continue; } // If this app requires a token, but previously was public and we had stored data, keep it around if (isPublicOnly && !data.KeyName.StartsWith("common", StringComparison.Ordinal)) { continue; } await DbConnection.ExecuteAsync("DELETE FROM `AppsInfo` WHERE `AppID` = @AppID AND `Key` = @Key", new { AppID, data.Key }); await MakeHistory("removed_key", data.Key, data.Value); } } else { if (string.IsNullOrEmpty(app.Name)) // We don't have the app in our database yet { await DbConnection.ExecuteAsync("INSERT INTO `Apps` (`AppID`, `Name`) VALUES (@AppID, @AppName) ON DUPLICATE KEY UPDATE `AppType` = `AppType`", new { AppID, AppName = $"{SteamDB.UnknownAppName} {AppID}" }); } else if (!app.Name.StartsWith(SteamDB.UnknownAppName, StringComparison.Ordinal)) // We do have the app, replace it with default name { await DbConnection.ExecuteAsync("UPDATE `Apps` SET `Name` = @AppName, `AppType` = @AppType WHERE `AppID` = @AppID", new { AppID, AppType = (int)EAppType.Invalid, AppName = $"{SteamDB.UnknownAppName} {AppID}" }); await MakeHistory("deleted_app", 0, app.Name); } } // Close the connection as it's no longer needed going into depot processor DbConnection.Close(); if (ProductInfo.KeyValues["depots"].Children.Any()) { await Steam.Instance.DepotProcessor.Process(AppID, ChangeNumber, ProductInfo.KeyValues["depots"]); } if (ProductInfo.MissingToken && PICSTokens.HasAppToken(AppID)) { Log.WriteError(nameof(PICSTokens), $"Overridden token for appid {AppID} is invalid?"); IRC.Instance.SendOps($"[Tokens] Looks like the overridden token for appid {AppID} ({newAppName}) is invalid"); } if (Settings.IsMillhaven && newAppType == EAppType.Beta && !LicenseList.OwnedApps.ContainsKey(AppID)) { var betaAppId = ProductInfo.KeyValues["extended"]["betaforappid"].AsUnsignedInteger(); if (betaAppId == 0) { betaAppId = ProductInfo.KeyValues["common"]["parent"].AsUnsignedInteger(); } Log.WriteDebug(nameof(AppProcessor), $"Adding beta access request for app {AppID} ({betaAppId})"); Steam.Instance.FreeLicense.AddBeta(betaAppId); } }