public override int GetHashCode() { int hash = 1; if (LogName.Length != 0) { hash ^= LogName.GetHashCode(); } if (resource_ != null) { hash ^= Resource.GetHashCode(); } if (payloadCase_ == PayloadOneofCase.ProtoPayload) { hash ^= ProtoPayload.GetHashCode(); } if (payloadCase_ == PayloadOneofCase.TextPayload) { hash ^= TextPayload.GetHashCode(); } if (payloadCase_ == PayloadOneofCase.JsonPayload) { hash ^= JsonPayload.GetHashCode(); } if (timestamp_ != null) { hash ^= Timestamp.GetHashCode(); } if (Severity != 0) { hash ^= Severity.GetHashCode(); } if (InsertId.Length != 0) { hash ^= InsertId.GetHashCode(); } if (httpRequest_ != null) { hash ^= HttpRequest.GetHashCode(); } hash ^= Labels.GetHashCode(); if (operation_ != null) { hash ^= Operation.GetHashCode(); } if (Trace.Length != 0) { hash ^= Trace.GetHashCode(); } if (sourceLocation_ != null) { hash ^= SourceLocation.GetHashCode(); } hash ^= (int)payloadCase_; return(hash); }
public async Task <ProtoResponse> PostAsync(ProtoPayload payload) { var response = await HandleProtoRequest(payload).ConfigureAwait(false); if (response?.Data == null) { _logger.LogError($"[Proto] [{payload.Uuid}] null data response!"); } Response.Headers["Accept"] = "application/json"; Response.Headers["Content-Type"] = "application/json"; return(response); }
// Handle MAD data /* * [ * HttpPost("/raw"), * Produces("application/json"), * ] * public async Task<ProtoResponse> PostAsync(List<ProtoData> payloads) * { * Response.Headers["Accept"] = "application/json"; * Response.Headers["Content-Type"] = "application/json"; * var response await HandleProtoRequest(new ProtoPayload * { * Username = "******", * Uuid = Request.Headers["Origin"], * Contents = payloads, * }); * return response; * } */ #endregion #region Handlers private async Task <ProtoResponse> HandleProtoRequest(ProtoPayload payload) { if (payload == null) { _logger.LogError("Invalid proto payload received"); return(null); } var stopwatch = new Stopwatch(); stopwatch.Start(); var device = await _deviceRepository.GetByIdAsync(payload.Uuid).ConfigureAwait(false); if (device != null) { device.LastLatitude = payload.LatitudeTarget; device.LastLongitude = payload.LongitudeTarget; device.LastSeen = DateTime.UtcNow.ToTotalSeconds(); await _deviceRepository.UpdateAsync(device).ConfigureAwait(false); } if (!string.IsNullOrEmpty(payload.Username) && payload.Level > 0) { if (!_levelCache.ContainsKey(payload.Username)) { _levelCache.Add(payload.Username, payload.Level); } else { var oldLevel = _levelCache[payload.Username]; if (oldLevel != payload.Level) { var account = await _accountRepository.GetByIdAsync(payload.Username).ConfigureAwait(false); if (account != null) { account.Level = payload.Level; await _accountRepository.UpdateAsync(account).ConfigureAwait(false); } _levelCache[payload.Username] = payload.Level; } } } if (payload.Contents?.Count == 0) { _logger.LogWarning($"[Proto] [{payload.Uuid}] Invalid GMO"); return(null); } var wildPokemon = 0; var nearbyPokemon = 0; var clientWeather = 0; var forts = 0; var fortDetails = new List <FortDetailsOutProto>(); var quests = 0; var fortSearch = 0; var encounters = 0; var cells = new List <ulong>(); var inventory = new List <InventoryDeltaProto>(); var playerData = 0; //var spawnpoints = new List<Spawnpoint>(); var isEmptyGmo = true; var isInvalidGmo = true; var containsGmo = false; if (payload.Contents == null) { _logger.LogWarning($"[Proto] [{payload.Uuid}] Empty data"); return(null); } Coordinate targetCoord = null; var inArea = false; if (payload.LatitudeTarget != 0 && payload.LongitudeTarget != 0) { targetCoord = new Coordinate(payload.LatitudeTarget, payload.LongitudeTarget); } var targetKnown = false; S2CellId targetCellId = default; if (targetCoord != null) { // Check target is within cell id instead of checking geofences targetKnown = true; targetCellId = S2CellId.FromLatLng(S2LatLng.FromDegrees(targetCoord.Latitude, targetCoord.Longitude)); //_logger.LogDebug($"[Proto] [{payload.Uuid}] Data received within target area {targetCoord} and target distance {payload.TargetMaxDistance}"); } //_logger.LogWarning($"[{device.Uuid}] InArea={inArea}"); foreach (var rawData in payload.Contents) { if (string.IsNullOrEmpty(rawData.Data)) { _logger.LogWarning($"[Proto] [{payload.Uuid}] Unhandled proto {rawData.Method}: {rawData.Data}"); continue; } var data = rawData.Data; var method = (Method)rawData.Method; switch (method) { case Method.GetPlayer: try { var gpr = GetPlayerOutProto.Parser.ParseFrom(Convert.FromBase64String(data)); if (gpr?.Success == true) { await PushData(RedisChannels.ProtoAccount, new { gpr, username = payload.Username, }); playerData++; } else { _logger.LogError($"[Proto] [{payload.Uuid}] Malformed GetPlayerOutProto"); } } catch (Exception ex) { _logger.LogError($"[Proto] [{payload.Uuid}] Unable to decode GetPlayerOutProto: {ex}"); } break; case Method.GetHoloholoInventory: try { var ghi = GetHoloholoInventoryOutProto.Parser.ParseFrom(Convert.FromBase64String(data)); if (ghi?.Success == true) { if (ghi.InventoryDelta.InventoryItem?.Count > 0) { // TODO: Publish with redis inventory.Add(ghi.InventoryDelta); } } else { _logger.LogError($"[Proto] [{payload.Uuid}] Malformed GetHoloholoInventoryOutProto"); } } catch (Exception ex) { _logger.LogError($"[Proto] [{payload.Uuid}] Unable to decode GetHoloholoInventoryOutProto: {ex}"); } break; case Method.FortSearch: try { var fsr = FortSearchOutProto.Parser.ParseFrom(Convert.FromBase64String(data)); if (fsr != null) { if (fsr.ChallengeQuest?.Quest != null) { await PushData(RedisChannels.ProtoQuest, new { raw = data, }); quests++; } //fortSearch.Add(fsr); fortSearch++; } else { _logger.LogError($"[Proto] [{payload.Uuid}] Malformed FortSearchOutProto"); } } catch (Exception ex) { _logger.LogError($"[Proto] [{payload.Uuid}] Unable to decode FortSearchOutProto: {ex}"); } break; case Method.Encounter: isEmptyGmo = false; isInvalidGmo = false; try { if (payload.Level >= 30) { var er = EncounterOutProto.Parser.ParseFrom(Convert.FromBase64String(data)); if (er?.Status == EncounterOutProto.Types.Status.EncounterSuccess) { await PushData(RedisChannels.ProtoEncounter, new { data = er, username = payload.Username, }); encounters++; } else if (er == null) { _logger.LogError($"[Proto] [{payload.Uuid}] Malformed EncounterOutProto"); } } } catch (Exception ex) { _logger.LogError($"[Proto] [{payload.Uuid}] Unable to decode EncounterOutProto: {ex}"); } break; case Method.FortDetails: try { var fdr = FortDetailsOutProto.Parser.ParseFrom(Convert.FromBase64String(data)); if (fdr != null) { fortDetails.Add(fdr); //fortDetails++; // TODO: Publish with redis //await PublishData(RedisChannels.Fort, fdr); } else { _logger.LogError($"[Proto] [{payload.Uuid}] Malformed FortDetailsOutProto"); } } catch (Exception ex) { _logger.LogError($"[Proto] [{payload.Uuid}] Unable to decode FortDetailsOutProto: {ex}"); } break; case Method.GetMapObjects: containsGmo = true; try { var gmo = GetMapObjectsOutProto.Parser.ParseFrom(Convert.FromBase64String(data)); if (gmo != null) { isInvalidGmo = false; var mapCellsNew = gmo.MapCell; if (mapCellsNew.Count == 0) { //_logger.LogDebug($"[Proto] [{payload.Uuid}] Map cells are empty"); //return null; } // Check if we're within the same cell, if so then we are within the target distance if (!inArea && targetKnown && mapCellsNew.Select(x => x.S2CellId).Contains(targetCellId.Id)) { inArea = true; } foreach (var mapCell in mapCellsNew) { cells.Add(mapCell.S2CellId); await PushData(RedisChannels.ProtoCell, mapCell.S2CellId); var tsMs = mapCell.AsOfTimeMs; foreach (var wild in mapCell.WildPokemon) { await PushData(RedisChannels.ProtoWildPokemon, new { cell = mapCell.S2CellId, data = wild, timestamp_ms = tsMs, username = payload.Username, }); wildPokemon++; } foreach (var nearby in mapCell.NearbyPokemon) { await PushData(RedisChannels.ProtoNearbyPokemon, new { cell = mapCell.S2CellId, data = nearby, timestamp_ms = tsMs, username = payload.Username, }); nearbyPokemon++; } foreach (var fort in mapCell.Fort) { await PushData(RedisChannels.ProtoFort, new { cell = mapCell.S2CellId, data = fort, }); forts++; } } foreach (var weather in gmo.ClientWeather) { await PushData(RedisChannels.ProtoWeather, new Weather(weather)); clientWeather++; } if (wildPokemon == 0 && nearbyPokemon == 0 && forts == 0 && quests == 0) { foreach (var cellId in cells) { if (!_emptyCells.ContainsKey(cellId)) { _emptyCells.Add(cellId, 1); } else { _emptyCells[cellId]++; } if (_emptyCells[cellId] == 3) { _logger.LogWarning($"[Proto] [{payload.Uuid}] Cell {cellId} was empty 3 times in a row, assuming empty..."); await PushData(RedisChannels.ProtoCell, cellId); } } _logger.LogDebug($"[Proto] [{payload.Uuid}] GMO is empty"); isEmptyGmo = true; } else { cells.ForEach(cellId => _emptyCells[cellId] = 0); isEmptyGmo = false; } } else { _logger.LogError($"[Proto] [{payload.Uuid}] Malformed GetMapObjectsOutProto"); } } catch (Exception ex) { _logger.LogError($"[Proto] [{payload.Uuid}] Unable to decode GetMapObjectsOutProto: {ex}"); } break; case Method.GymGetInfo: try { var ggi = GymGetInfoOutProto.Parser.ParseFrom(Convert.FromBase64String(data)); if (ggi != null) { if (ggi.GymStatusAndDefenders == null) { ConsoleExt.WriteWarn($"[DataConsumer] Invalid GymStatusAndDefenders provided, skipping...\n: {ggi}"); continue; } var fortId = ggi.GymStatusAndDefenders.PokemonFortProto.FortId; var gymDefenders = ggi.GymStatusAndDefenders.GymDefender; if (gymDefenders == null) { continue; } foreach (var gymDefender in gymDefenders) { if (gymDefender.TrainerPublicProfile != null) { await PushData(RedisChannels.ProtoGymTrainer, new Trainer(gymDefender)); } if (gymDefender.MotivatedPokemon != null) { await PushData(RedisChannels.ProtoGymDefender, new GymDefender(fortId, gymDefender)); } } } else { _logger.LogError($"[Proto] [{payload.Uuid}] Malformed GymGetInfoOutProto"); } } catch (Exception ex) { _logger.LogError($"[Proto] [{payload.Uuid}] Unable to decode GymGetInfoOutProto: {ex}"); } break; //case Method.Unset: default: _logger.LogDebug($"[Proto] [{payload.Uuid}] Invalid method or data provided. {method}:{data}"); break; } } Coordinate pokemonCoords = null; /* * if (targetCoord != null) * { * foreach (var fort in forts) * { * if (!inArea) * { * var coord = new Coordinate(fort.data.Latitude, fort.data.Longitude); * if (coord.DistanceTo(targetCoord) <= payload.TargetMaxDistance) * { * inArea = true; * } * } * } * } * if (targetCoord != null || payload.PokemonEncounterId != null) * { * foreach (var pokemon in wildPokemons) * { * WildPokemonProto wild = (WildPokemonProto)pokemon.data; * if (targetCoord != null) * { * if (pokemonCoords != null && inArea) * { * break; * } * * if (!inArea) * { * var coord = new Coordinate(wild.Latitude, wild.Longitude); * if (coord.DistanceTo(targetCoord) <= payload.TargetMaxDistance) * { * inArea = true; * } * } * } * if (!string.IsNullOrEmpty(payload.PokemonEncounterId)) * { * if (pokemonCoords != null && inArea) * { * break; * } * * if (pokemonCoords == null) * { * if (string.Compare(wild.EncounterId.ToString(), payload.PokemonEncounterId, true) == 0) * { * pokemonCoords = new Coordinate(wild.Latitude, wild.Longitude); * } * } * } * } * } * if (targetCoord != null && !inArea) * { * foreach (var cell in cells) * { * if (inArea) * { * break; * } * * var s2cell = new S2Cell(new S2CellId(cell)); * var latlng = new S2LatLng(s2cell.Center); * var coord = new Coordinate(latlng.LatDegrees, latlng.LngDegrees); * if (coord.DistanceTo(targetCoord) <= Math.Max(payload.TargetMaxDistance ?? 250, 100)) * { * inArea = true; * } * } * } */ stopwatch.Stop(); var response = new ProtoResponse { Status = "ok", Data = new ProtoDataDetails { Nearby = nearbyPokemon, Wild = wildPokemon, Forts = forts, Quests = quests, FortSearch = fortSearch, Encounters = encounters, Level = payload.Level, OnlyEmptyGmos = containsGmo && isEmptyGmo, OnlyInvalidGmos = containsGmo && isInvalidGmo, ContainsGmos = containsGmo, InArea = inArea, LatitudeTarget = targetCoord?.Latitude, LongitudeTarget = targetCoord?.Longitude, PokemonLatitude = pokemonCoords?.Latitude, PokemonLongitude = pokemonCoords?.Longitude, PokemonEncounterId = payload.PokemonEncounterId, }, }; _logger.LogInformation($"[{payload.Uuid}] {response.ToJson()} parsed in {stopwatch.Elapsed.TotalSeconds}s"); return(response); }