public static async Task <bool> GetSystemCache(Dictionary <string, JsonElement> elementAsDictionary, IDatabase _rdb, StarSystemChecker starSystemChecker) { var reqProps = typeof(RequiredPropertiesForCache).GetEnumNames(); var requiredProperties = elementAsDictionary.Keys.Where(k => Enum.TryParse(typeof(RequiredPropertiesForCache), k, false, out _)); var missingProps = reqProps.Except(requiredProperties); bool setCache = false; if (!missingProps.Any()) { /*await _rdb.StringSetAsyncWithRetries( * $"SystemAddress:{elementAsDictionary["SystemAddress"].GetInt64()}", * JsonSerializer.Serialize(new * { * SystemAddress = elementAsDictionary["SystemAddress"].GetInt64(), * StarSystem = elementAsDictionary["StarSystem"].GetString(), * StarPos = elementAsDictionary["StarPos"] * }), * TimeSpan.FromHours(10), * flags: CommandFlags.FireAndForget * );*/ var arrayEnum = elementAsDictionary["StarPos"].EnumerateArray().ToArray(); var edSysData = new EDSystemData { Id64 = elementAsDictionary["SystemAddress"].GetInt64(), Name = elementAsDictionary["StarSystem"].GetString(), Coordinates = new EDSystemCoordinates { X = arrayEnum[0].GetDouble(), Y = arrayEnum[1].GetDouble(), Z = arrayEnum[2].GetDouble() } }; await starSystemChecker.InsertOrUpdateSystemAsync(edSysData); // Since the event has all properties, we allow setting the cache //setCache = true; } var importantProps = new[] { "StarPos", "StarSystem", "SystemAddress" }; if (!missingProps.Contains("SystemAddress")) { /*var cachedSystem = await _rdb.StringGetAsyncWithRetries($"SystemAddress:{elementAsDictionary["SystemAddress"].GetInt64()}"); * if (cachedSystem != RedisValue.Null) * { * var jel = JsonDocument.Parse(cachedSystem.ToString()).RootElement; * // Don't replace values that already exists on the event, supposedly the journal is supposed to be correct on those already * //elementAsDictionary["SystemAddress"] = jel.GetProperty("SystemAddress"); * if (!elementAsDictionary.ContainsKey("StarSystem")) * { * elementAsDictionary["StarSystem"] = jel.GetProperty("StarSystem"); * } * if (!elementAsDictionary.ContainsKey("StarPos")) * { * elementAsDictionary["StarPos"] = jel.GetProperty("StarPos"); * } * * // Do not allow setting the cache, just because we fetched it from the cache. * setCache = false; * } * else*/ { var systemData = await starSystemChecker.GetSystemDataAsync(elementAsDictionary["SystemAddress"].GetInt64()); if (systemData != null) { var jel = JsonDocument.Parse(JsonSerializer.Serialize(new { SystemAddress = systemData.Id64, StarSystem = systemData.Name, StarPos = new[] { systemData.Coordinates.X, systemData.Coordinates.Y, systemData.Coordinates.Z } })).RootElement; // Don't replace values that already exists on the event, supposedly the journal is supposed to be correct on those already //elementAsDictionary["SystemAddress"] = jel.GetProperty("SystemAddress"); if (!elementAsDictionary.ContainsKey("StarSystem")) { elementAsDictionary["StarSystem"] = jel.GetProperty("StarSystem"); } if (!elementAsDictionary.ContainsKey("StarPos")) { elementAsDictionary["StarPos"] = jel.GetProperty("StarPos"); } // It's safe to set the cache here, since we fetch the data from the database //setCache = true; } } } return(setCache); }
public static async Task <JsonElement> SetGamestateProperties(JsonElement element, EDGameState gameState, string commander, StarSystemChecker starSystemChecker) { return(await GameStateHandler.SetGamestateProperties(element, gameState, commander, starSystemChecker, (newState) => new { _systemAddress = gameState.SystemAddress, _systemName = gameState.SystemName, _systemCoordinates = gameState.SystemCoordinates, _marketId = gameState.MarketId, _stationName = gameState.StationName, _shipId = gameState.ShipId, _odyssey = gameState.Odyssey }, (transientState, elementAsDictionary) => { elementAsDictionary["_systemAddress"] = transientState.GetProperty("_systemAddress"); elementAsDictionary["_systemName"] = transientState.GetProperty("_systemName"); elementAsDictionary["_systemCoordinates"] = transientState.GetProperty("_systemCoordinates"); elementAsDictionary["_marketId"] = transientState.GetProperty("_marketId"); elementAsDictionary["_stationName"] = transientState.GetProperty("_stationName"); elementAsDictionary["_shipId"] = transientState.GetProperty("_shipId"); } )); }
public static async Task <(int errorCode, string resultContent, TimeSpan executionTime, bool sentData)> UploadJournalItemToEDSM(HttpClient hc, string journalRow, Guid userIdentifier, EDSMIntegrationSettings edsmSettings, EDGameState gameState, StarSystemChecker starSystemChecker) { var element = JsonDocument.Parse(journalRow).RootElement; if (!element.TryGetProperty("event", out JsonElement journalEvent)) { return(303, string.Empty, TimeSpan.Zero, false); } Stopwatch sw = new Stopwatch(); sw.Start(); try { element = await SetGamestateProperties(element, gameState, edsmSettings.CommanderName.Trim(), starSystemChecker); if (System.Enum.TryParse(typeof(IgnoredEvents), journalEvent.GetString(), false, out _)) { return(304, string.Empty, TimeSpan.Zero, false); } if (!gameState.SendEvents) { return(104, string.Empty, TimeSpan.Zero, false); } var formContent = new MultipartFormDataContent(); var json = JsonSerializer.Serialize(element, new JsonSerializerOptions() { WriteIndented = true }); formContent.Add(new StringContent(edsmSettings.CommanderName.Trim()), "commanderName"); formContent.Add(new StringContent(edsmSettings.ApiKey), "apiKey"); formContent.Add(new StringContent("Journal Limpet"), "fromSoftware"); formContent.Add(new StringContent(SharedSettings.VersionNumber), "fromSoftwareVersion"); formContent.Add(new StringContent(json), "message"); await SSEActivitySender.SendUserLogDataAsync(userIdentifier, new { fromIntegration = "EDSM", data = element }); var policy = Policy .HandleResult <HttpResponseMessage>(res => !res.IsSuccessStatusCode) .Or <HttpRequestException>() .WaitAndRetryAsync(30, retryCount => TimeSpan.FromSeconds(retryCount * 5)); var status = await policy.ExecuteAsync(() => hc.PostAsync("https://www.edsm.net/api-journal-v1", formContent)); var postResponseBytes = await status.Content.ReadAsByteArrayAsync(); var postResponse = System.Text.Encoding.UTF8.GetString(postResponseBytes); if (!status.IsSuccessStatusCode) { return((int)status.StatusCode, postResponse, TimeSpan.FromSeconds(30), true); } var resp = JsonSerializer.Deserialize <EDSMApiResponse>(postResponse); sw.Stop(); return(resp.ResultCode, postResponse, sw.Elapsed, true); } catch (InvalidTimestampException) { return(206, string.Empty, TimeSpan.FromMilliseconds(100), false); } }
public static async Task <JsonElement> SetGamestateProperties(JsonElement element, EDGameState gameState, string commander, StarSystemChecker starSystemChecker) { return(await GameStateHandler.SetGamestateProperties(element, gameState, commander, starSystemChecker, (newState) => { return new { systemName = gameState.SystemName, systemAddress = gameState.SystemAddress, systemCoordinates = gameState.SystemCoordinates, bodyName = gameState.BodyName, bodyId = gameState.BodyId, clientVersion = "Journal Limpet: " + SharedSettings.VersionNumber, odyssey = gameState.Odyssey, isBeta = false }; })); }
public static async Task <Dictionary <string, object> > UploadJournalItemToCanonnRD(string journalRow, string cmdrName, EDGameState gameState, List <CanonnEventDefinition> validCanonnEvents, StarSystemChecker starSystemChecker) { var element = JsonDocument.Parse(journalRow).RootElement; if (!element.TryGetProperty("event", out JsonElement journalEvent)) { return(null); } Stopwatch sw = new Stopwatch(); sw.Start(); try { var newGameState = await SetGamestateProperties(element, gameState, cmdrName, starSystemChecker); var matchingValidEvents = validCanonnEvents.Where(e => e.Event == journalEvent.GetString()); if (!matchingValidEvents.Any()) { return(null); } bool foundMatchingEvent = false; foreach (var matchingValidEvent in matchingValidEvents) { var fieldsToMatch = matchingValidEvent.ExtensionData ?? new Dictionary <string, object>(); if (fieldsToMatch.Count > 0) { var elementAsDictionary = JsonSerializer.Deserialize <Dictionary <string, object> >(element.GetRawText()); if (fieldsToMatch.All(k => elementAsDictionary.ContainsKey(k.Key) && elementAsDictionary[k.Key].ToString() == k.Value.ToString())) { foundMatchingEvent = true; break; } } else { foundMatchingEvent = true; break; } } if (!foundMatchingEvent) { return(null); } if (!gameState.SendEvents) { return(null); } var eddnItem = new Dictionary <string, object>() { { "gameState", newGameState }, { "rawEvent", element }, { "eventType", journalEvent.GetString() }, { "cmdrName", cmdrName } }; return(eddnItem); } catch (InvalidTimestampException) { return(null); } }
public async static Task <JsonElement> SetGamestateProperties(JsonElement element, EDGameState gameState, string commander, StarSystemChecker starSystemChecker, Func <EDGameState, object> setProperties, Action <JsonElement, Dictionary <string, JsonElement> > addStateToElement = null) { var _rdb = SharedSettings.RedisClient.GetDatabase(1); var elementAsDictionary = JsonSerializer.Deserialize <Dictionary <string, JsonElement> >(element.GetRawText()); if (elementAsDictionary.TryGetValue("timestamp", out var timeStampElement)) { if (!timeStampElement.TryGetDateTimeOffset(out _)) { throw new InvalidTimestampException(); } } bool setCache = await EDSystemCache.GetSystemCache(elementAsDictionary, _rdb, starSystemChecker); GameStateChanger.GameStateFixer(gameState, commander, elementAsDictionary); var addItems = setProperties(gameState); var transientState = JsonDocument.Parse(JsonSerializer.Serialize(addItems)).RootElement; await EDSystemCache.SetSystemCache(gameState, _rdb, setCache); if (addStateToElement != null) { addStateToElement(transientState, elementAsDictionary); var json = JsonSerializer.Serialize(elementAsDictionary); return(JsonDocument.Parse(json).RootElement); } return(transientState); }