From 0df066ff3c39255e9f9bcebcaba3adb683378c97 Mon Sep 17 00:00:00 2001 From: Felix Date: Fri, 19 Aug 2016 00:37:41 +0200 Subject: [PATCH] Dump traffic option - Option to dump requests and responses into log folder - Added all player badges - Better ptc kicking and auth validation --- cfg.js | 22 ++- package.json | 3 +- src/db/mongo.js | 4 +- src/db/mysql.js | 4 +- src/index.js | 19 ++ src/packets/Responses.GetInventory.js | 61 +++---- src/packets/Responses.GetMapObjects.js | 10 +- src/packets/Responses.GetPlayerProfile.js | 208 +++++++++++++++++++++- src/player.js | 6 +- src/request.js | 20 ++- 10 files changed, 293 insertions(+), 64 deletions(-) diff --git a/cfg.js b/cfg.js index 47b7a69..cdf084e 100644 --- a/cfg.js +++ b/cfg.js @@ -1,19 +1,19 @@ export const MINIMUM_CLIENT_VERSION = "0.33.0"; -export const SERVER_PORT = 3000; -export const SERVER_HOST_IP = "127.0.0.1"; export const SERVER_GAME_MODE = 0; export const SERVER_TICK_INTERVAL = 1; // better dont change export const SERVER_SAVE_INTERVAL = 1e3 * 60; // 1min export const SERVER_MAX_CONNECTIONS = 64; export const SERVER_PLAYER_CONNECTION_TIMEOUT = 1e3 * 60 * 30; // 30min -export const SERVER_LOG_REQUESTS = true; - export const SERVER_BOOT_TIMEOUT = 10e3; export const SERVER_DEFAULT_CONSOLE_COLOR = 32; +// HTTP +export const SERVER_PORT = 3000; +export const SERVER_HOST_IP = "127.0.0.1"; + // Either mongo or mysql export const SERVER_USE_DATABASE = "MONGO"; @@ -36,4 +36,16 @@ export const SERVER_POGO_CLIENT_PROVIDER = "GOOGLE"; // either google or ptc export const SERVER_POGO_CLIENT_USERNAME = "USERNAME"; export const SERVER_POGO_CLIENT_PASSWORD = "PASSWORD"; -export const SERVER_GMAPS_API_KEY = "AIzaSyDF9rkP8lhcddBtvH9gVFzjnNo13WtmJIM"; \ No newline at end of file +export const SERVER_GMAPS_API_KEY = "AIzaSyDF9rkP8lhcddBtvH9gVFzjnNo13WtmJIM"; + +// path to save logs into +export const SERVER_DUMP_PATH = "./logs/"; + +// save traffic dumps into /logs +export const SERVER_DUMP_TRAFFIC = true; + +// show request types in console +export const SERVER_LOG_REQUESTS = true; + +// transfer account progress from official servers +export const SERVER_CLONE_NEW_ACCOUNTS_FROM_OFFICIAL_SERVER = false; \ No newline at end of file diff --git a/package.json b/package.json index 3d9213b..218b398 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "POGOServer", - "version": "0.3.0", + "version": "0.3.1", "description": "", "repository": { "type": "git", @@ -28,6 +28,7 @@ "long": "^3.2.0", "pogo-asset-downloader": "^0.2.2", "node-pogo-protos": "^1.3.0", + "pogo-decode": "^0.5.2", "path": "^0.12.7", "directory-tree": "^1.1.0", "nodegit": "^0.14.1", diff --git a/src/db/mongo.js b/src/db/mongo.js index 17d34cf..57d6277 100644 --- a/src/db/mongo.js +++ b/src/db/mongo.js @@ -9,7 +9,7 @@ export function setupConnection() { return new Promise((resolve) => { mongodb.MongoClient.connect(url, (error, db) => { if (error) { - this.print(error, 31); + this.print("MongoDB " + error, 31); this.retry("Retrying again in ", () => this.setupConnection().then(resolve), 5); return void 0; } else { @@ -20,7 +20,7 @@ export function setupConnection() { }); } db.on("close", (error) => { - this.print(error, 31); + this.print("MongoDB " + error, 31); this.retry("Trying to reconnect in ", () => this.setupConnection().then(resolve), 5); }); }); diff --git a/src/db/mysql.js b/src/db/mysql.js index 2e19d04..3265c84 100644 --- a/src/db/mysql.js +++ b/src/db/mysql.js @@ -15,7 +15,7 @@ export function setupConnection() { return new Promise((resolve) => { connection.connect((error) => { if (error) { - this.print(error, 31); + this.print("MySQL " + error, 31); this.retry("Retrying again in ", () => this.setupConnection().then(resolve), 5); return void 0; } @@ -26,7 +26,7 @@ export function setupConnection() { }); }); connection.on("error", (error) => { - this.print(error, 31); + this.print("MySQL " + error, 31); this.retry("Trying to reconnect in ", () => this.setupConnection().then(resolve), 5); }); }); diff --git a/src/index.js b/src/index.js index f5e3976..cf74759 100644 --- a/src/index.js +++ b/src/index.js @@ -1,6 +1,8 @@ import fs from "fs"; +import fse from "fs-extra"; import http from "http"; import proto from "./proto"; +import decode from "pogo-decode"; import { inherit @@ -204,6 +206,23 @@ class GameServer { } } + dumpTraffic(req, res) { + + // decode opts + let opts = { + removeNulls: true, + encodeBuffers: true + }; + + try { + let decoded = JSON.stringify(decode(req, res, opts), null, 2); + fse.outputFileSync(CFG.SERVER_DUMP_PATH + Date.now(), decoded); + } catch (e) { + this.print("Dump traffic: " + e, 31); + } + + } + greet() { console.log(greetMessage); } diff --git a/src/packets/Responses.GetInventory.js b/src/packets/Responses.GetInventory.js index ddfc8a3..6a7854c 100644 --- a/src/packets/Responses.GetInventory.js +++ b/src/packets/Responses.GetInventory.js @@ -35,28 +35,27 @@ export default function GetInventoryData(obj) { "modified_timestamp_ms": new Date().getTime() * 1e3, "inventory_item_data": new proto.Inventory.InventoryItemData({ "player_stats": new proto.Data.Player.PlayerStats({ - "level": 3, - "experience": 0, - "prev_level_xp": 0, - "next_level_xp": 0, - "km_walked": 1.017870306968689, - "pokemons_encountered": 6, - "unique_pokedex_entries": 3, - "pokemons_captured": 3, - "evolutions": 0, - "poke_stop_visits": 25, - "pokeballs_thrown": 11, - "eggs_hatched": 0, - "big_magikarp_caught": 0, - "battle_attack_won": 0, - "battle_attack_total": 0, - "battle_defended_won": 0, - "battle_training_won": 0, - "battle_training_total": 0, - "prestige_raised_total": 0, - "prestige_dropped_total": 0, - "pokemon_deployed": 0, - "small_rattata_caught": 0 + level: 3, + experience: 4870, + prev_level_xp: 1000, + next_level_xp: 6000, + km_walked: 1.0598372220993042, + pokemons_encountered: 11, + unique_pokedex_entries: 5, + pokemons_captured: 5, + evolutions: 0, + poke_stop_visits: 37, + pokeballs_thrown: 22, + eggs_hatched: 0, + big_magikarp_caught: 0, + battle_attack_won: 0, + battle_attack_total: 0, + battle_defended_won: 0, + battle_training_won: 0, + battle_training_total: 0, + prestige_raised_total: 0, + prestige_dropped_total: 0, + pokemon_deployed: 0 }) }) }), @@ -138,24 +137,6 @@ export default function GetInventoryData(obj) { }) }) }), - new proto.Inventory.InventoryItem({ - "modified_timestamp_ms": new Date().getTime() * 1e3, - "inventory_item_data": new proto.Inventory.InventoryItemData({ - "egg_incubators": new proto.Inventory.EggIncubators({ - "egg_incubator": [ - new proto.Inventory.EggIncubator({ - "id": "EggIncubatorProto-2589714687259241229", - "item_id": 901, - "incubator_type": 1, - "uses_remaining": 0, - "pokemon_id": 0, - "start_km_walked": 0, - "target_km_walked": 0 - }) - ] - }) - }) - }), new proto.Inventory.InventoryItem({ "modified_timestamp_ms": new Date().getTime() * 1e3, "inventory_item_data": new proto.Inventory.InventoryItemData({ diff --git a/src/packets/Responses.GetMapObjects.js b/src/packets/Responses.GetMapObjects.js index abee07c..c5f962a 100644 --- a/src/packets/Responses.GetMapObjects.js +++ b/src/packets/Responses.GetMapObjects.js @@ -34,9 +34,9 @@ export default function GetMapObjects(player, request) { let latitude = player.latitude; let longitude = player.longitude; - let cell = cellsRes[cellsRes.length - 1]; + let cell = cellsRes[0]; - cellsRes[cellsRes.length - 2].forts = [ + cell.forts = [ new proto.Map.Fort.FortData({ id: "roflcopter", last_modified_timestamp_ms: 1470787552992, @@ -59,7 +59,7 @@ export default function GetMapObjects(player, request) { longitude: longitude, spawn_point_id: "87bdd289c69", pokemon_data: new proto.Data.PokemonData({ - pokemon_id: 16, + pokemon_id: 145, cp: 277, stamina: 41, stamina_max: 41, @@ -80,7 +80,7 @@ export default function GetMapObjects(player, request) { new proto.Map.Pokemon.MapPokemon({ spawn_point_id: "87bdd289c69", encounter_id: 11810991820755313517, - pokemon_id: 16, + pokemon_id: 145, latitude: latitude, longitude: longitude, expiration_timestamp_ms: (new Date().getTime() + 1e6) * 1e3 @@ -90,7 +90,7 @@ export default function GetMapObjects(player, request) { cell.nearby_pokemons = [ new proto.Map.Pokemon.NearbyPokemon({ distance_in_meters: 200.0, - pokemon_id: 16 + pokemon_id: 145 }) ]; diff --git a/src/packets/Responses.GetPlayerProfile.js b/src/packets/Responses.GetPlayerProfile.js index 56d7a7f..ca82c22 100644 --- a/src/packets/Responses.GetPlayerProfile.js +++ b/src/packets/Responses.GetPlayerProfile.js @@ -12,14 +12,210 @@ export default function GetPlayerProfile(obj) { start_time: new Date().getTime() * 1000, badges: [ new proto.Data.PlayerBadge({ - badge_type: proto.Enums.BadgeType.BADGE_PIKACHU, - rank: 1, - start_value: 0, - end_value: 2000, - current_value: 1337 + "badge_type": 1, + "rank": 0, + "start_value": 0, + "end_value": 10, + "current_value": 1.0598372225667916 + }), + new proto.Data.PlayerBadge({ + "badge_type": 2, + "rank": 1, + "start_value": 5, + "end_value": 50, + "current_value": 5.031372549019608 + }), + new proto.Data.PlayerBadge({ + "badge_type": 3, + "rank": 0, + "start_value": 0, + "end_value": 30, + "current_value": 5.031372549019608 + }), + new proto.Data.PlayerBadge({ + "badge_type": 5, + "rank": 0, + "start_value": 0, + "end_value": 3, + "current_value": 0 + }), + new proto.Data.PlayerBadge({ + "badge_type": 6, + "rank": 0, + "start_value": 0, + "end_value": 10, + "current_value": 0 + }), + new proto.Data.PlayerBadge({ + "badge_type": 8, + "rank": 0, + "start_value": 0, + "end_value": 100, + "current_value": 37.00098039215686 + }), + new proto.Data.PlayerBadge({ + "badge_type": 11, + "rank": 0, + "start_value": 0, + "end_value": 3, + "current_value": 0 + }), + new proto.Data.PlayerBadge({ + "badge_type": 13, + "rank": 0, + "start_value": 0, + "end_value": 10, + "current_value": 0 + }), + new proto.Data.PlayerBadge({ + "badge_type": 14, + "rank": 0, + "start_value": 0, + "end_value": 10, + "current_value": 0 + }), + new proto.Data.PlayerBadge({ + "badge_type": 18, + "rank": 0, + "start_value": 0, + "end_value": 10, + "current_value": 8.062745098039215 + }), + new proto.Data.PlayerBadge({ + "badge_type": 19, + "rank": 0, + "start_value": 0, + "end_value": 10, + "current_value": 0 + }), + new proto.Data.PlayerBadge({ + "badge_type": 20, + "rank": 0, + "start_value": 0, + "end_value": 10, + "current_value": 8.062745098039215 + }), + new proto.Data.PlayerBadge({ + "badge_type": 21, + "rank": 0, + "start_value": 0, + "end_value": 10, + "current_value": 1.007843137254902 + }), + new proto.Data.PlayerBadge({ + "badge_type": 22, + "rank": 0, + "start_value": 0, + "end_value": 10, + "current_value": 0 + }), + new proto.Data.PlayerBadge({ + "badge_type": 23, + "rank": 0, + "start_value": 0, + "end_value": 10, + "current_value": 0 + }), + new proto.Data.PlayerBadge({ + "badge_type": 24, + "rank": 0, + "start_value": 0, + "end_value": 10, + "current_value": 8.062745098039215 + }), + new proto.Data.PlayerBadge({ + "badge_type": 25, + "rank": 0, + "start_value": 0, + "end_value": 10, + "current_value": 0 + }), + new proto.Data.PlayerBadge({ + "badge_type": 26, + "rank": 0, + "start_value": 0, + "end_value": 10, + "current_value": 0 + }), + new proto.Data.PlayerBadge({ + "badge_type": 27, + "rank": 0, + "start_value": 0, + "end_value": 10, + "current_value": 0 + }), + new proto.Data.PlayerBadge({ + "badge_type": 28, + "rank": 0, + "start_value": 0, + "end_value": 10, + "current_value": 0 + }), + new proto.Data.PlayerBadge({ + "badge_type": 29, + "rank": 0, + "start_value": 0, + "end_value": 10, + "current_value": 0 + }), + new proto.Data.PlayerBadge({ + "badge_type": 30, + "rank": 0, + "start_value": 0, + "end_value": 10, + "current_value": 0 + }), + new proto.Data.PlayerBadge({ + "badge_type": 31, + "rank": 0, + "start_value": 0, + "end_value": 10, + "current_value": 0 + }), + new proto.Data.PlayerBadge({ + "badge_type": 32, + "rank": 0, + "start_value": 0, + "end_value": 10, + "current_value": 0 + }), + new proto.Data.PlayerBadge({ + "badge_type": 33, + "rank": 0, + "start_value": 0, + "end_value": 10, + "current_value": 0 + }), + new proto.Data.PlayerBadge({ + "badge_type": 34, + "rank": 0, + "start_value": 0, + "end_value": 10, + "current_value": 0 + }), + new proto.Data.PlayerBadge({ + "badge_type": 35, + "rank": 0, + "start_value": 0, + "end_value": 10, + "current_value": 0 + }), + new proto.Data.PlayerBadge({ + "badge_type": 36, + "rank": 0, + "start_value": 0, + "end_value": 3, + "current_value": 0 + }), + new proto.Data.PlayerBadge({ + "badge_type": 37, + "rank": 0, + "start_value": 0, + "end_value": 3, + "current_value": 0 }) ] }).encode() ); -} \ No newline at end of file +} diff --git a/src/player.js b/src/player.js index 58e05cf..a4fa391 100644 --- a/src/player.js +++ b/src/player.js @@ -52,6 +52,9 @@ class Player { this.pokedex = null; this.inventory = null; + this.isPTCAccount = false; + this.isGoogleAccount = false; + this.response = obj.response; this.connection = obj.connection; @@ -302,7 +305,8 @@ export function forwardPlayer() { return new Promise((resolve) => { this.getUserByEmail(player.email).then((doc) => { if (player.email.length) { - this.print(`${player.email.replace("@gmail.com", "")} authenticated!`, 36); + let provider = player.isGoogleAccount ? "Google" : "PTC"; + this.print(`${player.email.replace("@gmail.com", "")} authenticated via ${provider}!`, 36); } if (doc) { this.loginPlayer().then((res) => { diff --git a/src/request.js b/src/request.js index 9b067ba..782b1fd 100644 --- a/src/request.js +++ b/src/request.js @@ -1,4 +1,3 @@ -import fs from "fs"; import proto from "./proto"; import * as CFG from "../cfg"; @@ -35,12 +34,19 @@ export function authenticatePlayer() { // TODO: Support PTC server authentification + if (!token || !token.provider) { + this.print("Invalid authentication token! Kicking..", 31); + this.removePlayer(player); + return void 0; + } + if (token.provider === "google") { if (token.token !== null) { let decoded = jwtDecode(token.token.contents); player.generateUid(decoded.email); player.email = decoded.email; player.email_verified = decoded.email_verified; + player.isGoogleAccount = true; this.print(`${player.email.replace("@gmail.com", "")} connected!`, 36); } else { @@ -50,10 +56,17 @@ export function authenticatePlayer() { } } else if (token.provider === "ptc") { + let decoded = token.token.contents; + player.isPTCAccount = true; this.print("PTC auth isnt supported yet! Kicking..", 31); this.removePlayer(player); return void 0; } + else { + this.print("Invalid provider! Kicking..", 31); + this.removePlayer(player); + return void 0; + } player.authenticated = true; @@ -117,7 +130,10 @@ export function onRequest(req, res) { } this.processRequests(request.requests).then((answer) => { - let msg = this.envelopResponse(1, request.request_id, answer, request.hasOwnProperty("auth_ticket")); + let msg = this.envelopResponse(1, request.request_id, answer, !!request.auth_ticket); + if (CFG.SERVER_DUMP_TRAFFIC) { + this.dumpTraffic(req.body, msg); + } this.send(msg); });