예제 #1
0
        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);
        }
예제 #2
0
 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");
     }
                                                          ));
 }
예제 #3
0
        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);
            }
        }
예제 #4
0
 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
         };
     }));
 }
예제 #5
0
        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);
            }
        }
예제 #6
0
        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);
        }