- Cleaner game master handling
- Added contact and currency player subclasses
- Authentication works
- Cleaner device sig parsing, handle unknown as repeated field
- Added various player and world packets
- Seperate settings object for DownloadSettings request
- Basic GetMapObjects response
- Removed unnecessary code in request.js
- Extended response.js
- Outsourced parseSignature into utils.js
This commit is contained in:
Felix 2016-08-28 14:31:08 +02:00
parent dbde45fe73
commit aa3743b4bd
32 changed files with 474 additions and 176 deletions

View File

@ -4,6 +4,8 @@ import POGOProtos from "pokemongo-protobuf";
import print from "./print";
import CFG from "../cfg";
import { _toCC } from "./utils";
/**
* @param {Request} req
* @param {Array} res

View File

@ -45,8 +45,6 @@ export default class GameServer {
this.apiClients = {};
this.assets = {};
this.master = null;
this.socket = null;
this.cycleInstance = null;
@ -119,16 +117,6 @@ export default class GameServer {
}
}
/**
* @param {Request} req
*/
parseSignature(req) {
let key = pcrypt.decrypt(req.unknown6.unknown2.encrypted_signature);
return (
POGOProtos.parseWithUnknown(key, "POGOProtos.Networking.Envelopes.Signature")
);
}
/**
* @param {String} path
* @return {Boolean}

View File

@ -1,6 +0,0 @@
/**
* Global shared parsed
* game master file
* @type {GameMaster}
*/
export let GAME_MASTER = null;

View File

@ -1,29 +1,41 @@
import POGOProtos from "pokemongo-protobuf";
/**
* @class GameMaster
*/
export default class GameMaster {
/**
* @param {Buffer} buffer
* @param {Object} decode
* @constructor
*/
constructor(buffer) {
constructor(decode) {
this.settings = this.buildSettings();
this.buffer = buffer;
this.decode = decode;
this.buffer = this.encode();
this.parse();
}
/**
* @return {Buffer}
*/
encode() {
return (
POGOProtos.serialize(this.decode, "POGOProtos.Networking.Responses.DownloadItemTemplatesResponse")
);
}
parse() {
let ii = 0;
let length = 0;
let item = null;
let items = this.buffer.item_templates;
let items = this.decode.item_templates;
length = items.length;
@ -60,4 +72,13 @@ export default class GameMaster {
);
}
/**
* @return {Buffer}
*/
serialize() {
return (
this.buffer
);
}
}

View File

@ -0,0 +1,24 @@
/**
* @class Contact
*/
export default class Contact {
/** @constructor */
constructor() {
this.sendMarketingEmails = false;
this.sendPushNotifications = false;
}
/**
* @return {Object}
*/
serialize() {
return ({
send_marketing_emails: this.sendMarketingEmails,
send_push_notifications: this.sendPushNotifications
});
}
}

View File

@ -0,0 +1,30 @@
/**
* @class Currency
*/
export default class Currency {
/** @constructor */
constructor() {
this.currencies = {
"POKECOINS": 0,
"STARDUST": 0
};
}
/**
* @return {Array}
*/
serialize() {
let out = [];
for (let key in this.currencies) {
out.push({
name: key,
amount: this.currencies[key]
});
};
return (out);
}
}

View File

@ -1,7 +1,7 @@
/**
* @class Info
*/
class Info {
export default class Info {
/** @constructor */
constructor() {
@ -68,23 +68,21 @@ class Info {
}
}
getPlayerInfo() {
serialize() {
return ({
player_stats: {
level: this.lvl,
experience: this.exp,
prev_level_xp: this.prevLvlExp,
next_level_xp: this.nextLvlExp,
km_walked: this.kmWalked,
pokemons_encountered: this.pkmnEncountered,
unique_pokedex_entries: this.uniquePokedexEntries,
pokemons_captured: this.pkmnCaptured,
poke_stop_visits: this.pokeStopVisits,
pokeballs_thrown: this.pokeballsThrown,
eggs_hatched: this.eggsHatched,
big_magikarp_caught: this.bigMagikarpCaught,
pokemon_deployed: this.pkmnDeployed
}
level: this.lvl,
experience: this.exp,
prev_level_xp: this.prevLvlExp,
next_level_xp: this.nextLvlExp,
km_walked: this.kmWalked,
pokemons_encountered: this.pkmnEncountered,
unique_pokedex_entries: this.uniquePokedexEntries,
pokemons_captured: this.pkmnCaptured,
poke_stop_visits: this.pokeStopVisits,
pokeballs_thrown: this.pokeballsThrown,
eggs_hatched: this.eggsHatched,
big_magikarp_caught: this.bigMagikarpCaught,
pokemon_deployed: this.pkmnDeployed
});
}

View File

@ -1,7 +1,9 @@
import Pokemon from "../../Pokemon";
/**
* @class Party
*/
class Party {
export default class Party {
/** @constructor */
constructor() {

View File

@ -1,5 +1,3 @@
import Candy from "./Candy";
/**
* @class Tutorial
*/
@ -7,38 +5,24 @@ export default class Tutorial {
/** @constructor */
constructor() {
this.states = [];
this.LEGAL_SCREEN = 0;
this.AVATAR_SELECTION = 1;
this.ACCOUNT_CREATION = 2;
this.POKEMON_CAPTURE = 3;
this.NAME_SELECTION = 4;
this.POKEMON_BERRY = 5;
this.USE_ITEM = 6;
this.FIRST_TIME_EXPERIENCE_COMPLETE = 7;
this.POKESTOP_TUTORIAL = 8;
this.GYM_TUTORIAL = 9;
}
passLegalScreen() {
}
passAvatarSelection() {
}
passAccountCreation() {
skipTutorial() {
this.states = [
"LEGAL_SCREEN",
"AVATAR_SELECTION",
"POKEMON_CAPTURE",
"NAME_SELECTION",
"FIRST_TIME_EXPERIENCE_COMPLETE"
];
}
/**
* @return {Array}
*/
serialize() {
this.skipTutorial();
return (
this.states
);

View File

@ -1,16 +1,26 @@
import Avatar from "./Avatar";
import MapObject from "../World/MapObject";
import POGOProtos from "pokemongo-protobuf";
import jwtDecode from "jwt-decode";
import Info from "./Info";
import Party from "./Party";
import Avatar from "./Avatar";
import Contact from "./Contact";
import Tutorial from "./Tutorial";
import Currency from "./Currency";
import MapObject from "../World/MapObject";
import print from "../../print";
import CFG from "../../../cfg";
import * as _packets from "./packets";
import { inherit } from "../../utils";
import {
inherit,
parseSignature
} from "../../utils";
import { GAME_MASTER } from "../../master";
import { GAME_MASTER } from "../../shared";
/**
* @class Player
@ -28,15 +38,20 @@ export default class Player extends MapObject {
this.world = obj.world;
this._team = 0;
this._email = null;
this.username = "unknown";
this._email = null;
this.email_verified = false;
this.platform = null;
this.isPTCAccount = false;
this.isGoogleAccount = false;
this.isIOS = false;
this.isAndroid = false;
this.hasSignature = false;
this.authenticated = false;
@ -49,13 +64,17 @@ export default class Player extends MapObject {
this.maxPkmnStorage = 250;
this.maxItemStorage = 350;
this.info = new Info(this);
this.party = new Party(this);
this.avatar = new Avatar(this);
this.contact = new Contact(this);
this.currency = new Currency(this);
this.tutorial = new Tutorial(this);
/*
this.bag = new Bag(this);
this.info = new Info(this);
this.pary = new Party(this);
this.avatar = new Avatar(this);
this.pokedex = new Pokedex(this);
this.tutorial = new Tutorial(this);
*/
this.refreshSocket(obj.request, obj.response);
@ -66,15 +85,15 @@ export default class Player extends MapObject {
return (this._team);
}
set team(value) {
this.team = value;
this._team = value;
}
get email() {
return (this._email);
}
set email(value) {
this.email = value;
this.username = this.email;
this._email = value;
this.username = value.replace("@gmail.com", "");
}
/**
@ -89,13 +108,13 @@ export default class Player extends MapObject {
* @param {Response} res
*/
refreshSocket(req, res) {
this.request = req;
this.request = POGOProtos.parseWithUnknown(req.body, "POGOProtos.Networking.Envelopes.RequestEnvelope");
this.response = res;
}
authenticate() {
let request = POGOProtos.parseWithUnknown(this.request.body, "POGOProtos.Networking.Envelopes.RequestEnvelope")
let request = this.request;
let msg = this.GetAuthTicket(request.request_id);
@ -133,6 +152,23 @@ export default class Player extends MapObject {
}
getDevicePlatform() {
let request = this.request;
if (request.unknown6 && request.unknown6[0]) {
let sig = parseSignature(request);
if (sig.device_info !== void 0) {
this.hasSignature = true;
this.isIOS = sig.device_info.device_brand === "Apple";
this.isAndroid = !this.isIOS;
this.platform = this.isIOS ? "ios" : "android";
print(`${this.email} is playing with an ${this.isIOS ? "Apple" : "Android"} device!`, 36);
}
}
}
/**
* @param {String} type
* @param {Object} msg
@ -143,6 +179,18 @@ export default class Player extends MapObject {
case "GET_PLAYER":
resolve(this.GetPlayer(msg));
break;
case "GET_INVENTORY":
resolve(this.GetInventory(msg));
break;
case "GET_ASSET_DIGEST":
resolve(this.GetAssetDigest(msg));
break;
case "GET_HATCHED_EGGS":
resolve(this.GetHatchedEggs(msg));
break;
case "CHECK_AWARDED_BADGES":
resolve(this.CheckAwardedBadges(msg));
break;
};
});
}

View File

@ -0,0 +1,19 @@
import POGOProtos from "pokemongo-protobuf";
/**
* @param {Object} msg
* @return {Buffer}
*/
export default function CheckAwardedBadges(msg) {
let buffer = {
success: true,
awarded_badges: [],
awarded_badge_levels: []
};
return (
POGOProtos.serialize(buffer, "POGOProtos.Networking.Responses.CheckAwardedBadgesResponse")
);
}

View File

@ -0,0 +1,13 @@
import POGOProtos from "pokemongo-protobuf";
import * as shared from "../../../shared";
/**
* @param {Object} msg
* @return {Buffer}
*/
export default function GetAssetDigest(msg) {
return (
shared.GAME_ASSETS[this.platform].buffer
);
}

View File

@ -0,0 +1,21 @@
import POGOProtos from "pokemongo-protobuf";
/**
* @param {Object} msg
* @return {Buffer}
*/
export default function GetHatchedEggs(msg) {
let buffer = {
success: true,
pokemon_id: [],
experience_awarded: [],
candy_awarded: [],
stardust_awarded: []
};
return (
POGOProtos.serialize(buffer, "POGOProtos.Networking.Responses.GetHatchedEggsResponse")
);
}

View File

@ -1,47 +1,33 @@
import POGOProtos from "pokemongo-protobuf";
export default function GetInventory() {
let stats = this.GetInventoryPlayer();
/**
* @param {Object} msg
* @return {Buffer}
*/
export default function GetInventory(msg) {
/*
let items = this.GetInventoryItems();
let party = this.GetInventoryParty();
*/
let buffer = ({
let stats = {
modified_timestamp_ms: +new Date(),
inventory_item_data: {
player_stats: this.info.serialize()
}
};
let buffer = {
success: true,
inventory_delta: {
new_timestamp_ms: new Date().getTime(),
inventory_items: stats.concat(items).concat(party)
inventory_items: [stats]
}
});
};
return (POGOProtos.serialize(buffer, "POGOProtos.Networking.Responses.GetInventoryResponse"));
}
export function GetInventoryPlayer() {
let player = this.player;
return ({
modified_timestamp_ms: new Date().getTime(),
inventory_item_data: {
player_stats: {
level: player.level,
experience: player.exp,
prev_level_xp: "21000",
next_level_xp: "36000",
km_walked: 3.921541213989258,
pokemons_encountered: 75,
unique_pokedex_entries: 25,
pokemons_captured: 71,
poke_stop_visits: 123,
pokeballs_thrown: 74,
eggs_hatched: 1,
big_magikarp_caught: 1,
pokemon_deployed: 1
}
}
});
return (
POGOProtos.serialize(buffer, "POGOProtos.Networking.Responses.GetInventoryResponse")
);
}

View File

@ -2,6 +2,7 @@ import POGOProtos from "pokemongo-protobuf";
/**
* @param {Object} msg
* @return {Buffer}
*/
export default function GetPlayer(msg) {
@ -17,9 +18,11 @@ export default function GetPlayer(msg) {
next_defender_bonus_collect_timestamp_ms: +new Date()
},
contact_settings: this.contact.serialize(),
currencies: this.currencies.serialize()
}
currencies: this.currency.serialize()
};
return (POGOProtos.serialize({ success: true, player_data: buffer }, "POGOProtos.Networking.Responses.GetPlayerResponse"));
return (
POGOProtos.serialize({ success: true, player_data: buffer }, "POGOProtos.Networking.Responses.GetPlayerResponse")
);
}

View File

@ -2,6 +2,8 @@ import POGOProtos from "pokemongo-protobuf";
export default function GetPlayerProfile() {
return (POGOProtos.serialize(buffer, "POGOProtos.Networking.Responses.GetPlayerProfileResponse"));
return (
POGOProtos.serialize(buffer, "POGOProtos.Networking.Responses.GetPlayerProfileResponse")
);
}

View File

@ -1,4 +1,7 @@
export GetPlayer from "./GetPlayer";
export GetInventory from "./GetInventory";
export GetAuthTicket from "./GetAuthTicket";
export GetPlayerProfile from "./GetPlayerProfile";
export GetHatchedEggs from "./GetHatchedEggs";
export GetAssetDigest from "./GetAssetDigest";
export GetPlayerProfile from "./GetPlayerProfile";
export CheckAwardedBadges from "./CheckAwardedBadges";

View File

@ -17,6 +17,8 @@ export default class Pokemon extends MapObject {
*/
constructor(obj) {
super(null);
this.id = 0;
this.dexNumber = 0;

View File

@ -2,6 +2,10 @@ import Player from "../Player";
import CFG from "../../../cfg";
import * as _packets from "./packets";
import { inherit } from "../../utils";
/**
* @class World
*/
@ -138,11 +142,25 @@ export default class World {
getPacket(type, msg) {
return new Promise((resolve) => {
switch (type) {
case "GET_MAP_OBJECTS":
resolve(this.GetMapObjects(msg));
break;
case "CHECK_CHALLENGE":
console.log(type, msg);
resolve(this.CheckChallenge(msg));
break;
case "DOWNLOAD_SETTINGS":
resolve(this.DownloadSettings(msg));
break;
case "DOWNLOAD_REMOTE_CONFIG_VERSION":
resolve(this.DownloadRemoteConfigVersion(msg));
break;
case "DOWNLOAD_ITEM_TEMPLATES":
resolve(this.DownloadItemTemplates(msg));
break;
};
});
}
}
}
inherit(World, _packets);

View File

@ -0,0 +1,16 @@
import POGOProtos from "pokemongo-protobuf";
/**
* @param {Object} msg
*/
export default function CheckChallenge(msg) {
let buffer = {
challenge_url: " "
};
return (
POGOProtos.serialize(buffer, "POGOProtos.Networking.Responses.CheckChallengeResponse")
);
}

View File

@ -0,0 +1,13 @@
import POGOProtos from "pokemongo-protobuf";
import * as shared from "../../../shared";
/**
* @param {Object} msg
* @return {Buffer}
*/
export default function DownloadItemTemplates(msg) {
return (
shared.GAME_MASTER.serialize()
);
}

View File

@ -0,0 +1,19 @@
import POGOProtos from "pokemongo-protobuf";
/**
* @param {Object} msg
*/
export default function DownloadRemoteConfigVersion(msg) {
let buffer = {
"result": "SUCCESS",
"item_templates_timestamp_ms": "1471650700946",
"asset_digest_timestamp_ms": "1467338276561000",
"$unknownFields": []
}
return (
POGOProtos.serialize(buffer, "POGOProtos.Networking.Responses.DownloadRemoteConfigVersionResponse")
);
}

View File

@ -0,0 +1,20 @@
import POGOProtos from "pokemongo-protobuf";
import Settings from "../../../modes";
/**
* @param {Object} msg
* @return {Buffer}
*/
export default function DownloadSettings(msg) {
let buffer = {
hash: "2788184af4004004d6ab0740f7632983332106f6",
settings: Settings.GAME_SETTINGS
};
return (
POGOProtos.serialize(buffer, "POGOProtos.Networking.Responses.DownloadSettingsResponse")
);
}

View File

@ -1,18 +0,0 @@
import POGOProtos from "pokemongo-protobuf";
/**
* @param {Request} request
*/
export function GetMapObject(request) {
let player = this.player;
let latitude = player.latitude;
let longitude = player.longitude;
return new Promise(() => {
// db call
//
});
}

View File

@ -0,0 +1,38 @@
import POGOProtos from "pokemongo-protobuf";
/**
* @param {Object} msg
* @return {Buffer}
*/
export default function GetMapObjects(msg) {
let latitude = msg.latitude;
let longitude = msg.longitude;
let cells = [];
let buffer = {
status: "SUCCESS",
map_cells: cells
};
for (let cell in msg.cell_id) {
cells.push({
s2_cell_id: cell,
current_timestamp_ms: +new Date(),
forts: [],
spawn_points: [],
deleted_objects: [],
fort_summaries: [],
decimated_spawn_points: [],
wild_pokemons: [],
catchable_pokemons: [],
nearby_pokemons: []
});
};
return (
POGOProtos.serialize(buffer, "POGOProtos.Networking.Responses.GetMapObjectsResponse")
);
}

View File

@ -0,0 +1,5 @@
export GetMapObjects from "./GetMapObjects";
export CheckChallenge from "./CheckChallenge";
export DownloadSettings from "./DownloadSettings";
export DownloadItemTemplates from "./DownloadItemTemplates";
export DownloadRemoteConfigVersion from "./DownloadRemoteConfigVersion";

31
src/modes/index.js Normal file
View File

@ -0,0 +1,31 @@
import CFG from "../../cfg";
export default {
GAME_SETTINGS: {
fort_settings: {
interaction_range_meters: 40.25098039215686,
max_total_deployed_pokemon: 10,
max_player_deployed_pokemon: 1,
deploy_stamina_multiplier: 8.062745098039215,
deploy_attack_multiplier: 0,
far_interaction_range_meters: 1000.0156862745098
},
map_settings: {
pokemon_visible_range: 70.00196078431372,
poke_nav_range_meters: 751.0156862745098,
encounter_range_meters: 50.25098039215686,
get_map_objects_min_refresh_seconds: 10.007843017578125,
get_map_objects_max_refresh_seconds: 11.01568603515625,
get_map_objects_min_distance_meters: 10.007843017578125,
google_maps_api_key: CFG.GMAPS_KEY
},
inventory_settings: {
max_pokemon: 1000,
max_bag_items: 1000,
base_pokemon: 250,
base_bag_items: 350,
base_eggs: 9
},
minimum_client_version: CFG.MINIMUM_CLIENT_VERSION
}
}

View File

@ -1,6 +1,5 @@
import fs from "fs";
import url from "url";
import pcrypt from "pcrypt";
import POGOProtos from "pokemongo-protobuf";
import print from "./print";
@ -72,23 +71,22 @@ export function processRpcRequest(req, res, route) {
let player = this.world.getPlayerByRequest(req, res);
if (route[2] === "rpc") {
player.refreshSocket(req, res);
this.onRequest(player, req);
this.onRequest(player);
}
}
/**
* @param {Player} player
* @param {Request} req
*/
export function onRequest(player, req) {
export function onRequest(player) {
let request = this.parseProtobuf(req.body, "POGOProtos.Networking.Envelopes.RequestEnvelope");
let request = player.request;
request.requests = request.requests || [];
if (CFG.DEBUG_LOG_REQUESTS) {
console.log("#####");
print("#####");
request.requests.map((request) => {
console.log("Got request:", request.request_type);
print(request.request_type, 35);
}).join(",");
}
@ -97,6 +95,10 @@ export function onRequest(player, req) {
return void 0;
}
if (player.hasSignature === false) {
player.getDevicePlatform();
}
if (!request.requests.length) {
print("Received invalid request!", 31);
return void 0;
@ -106,42 +108,31 @@ export function onRequest(player, req) {
if (CFG.DEBUG_DUMP_TRAFFIC) {
this.dumpTraffic(request, returns);
}
let msg = this.envelopResponse(1, returns, request, player, !!request.auth_ticket);
let msg = this.envelopResponse(returns, request, player);
player.sendResponse(msg);
});
}
/**
* @param {Number} status
* @param {Array} returns
* @param {Request} req
* @param {Request} request
* @param {Player} player
* @param {Boolean} auth
* @return {Buffer}
*/
export function envelopResponse(status, returns, req, player, auth) {
export function envelopResponse(returns, request, player) {
let buffer = req;
let buffer = request;
delete buffer.requests;
buffer.returns = returns;
// get players device platform one time
if (player.hasSignature === false && buffer.unknown6 && buffer.unknown6.unknown2) {
let sig = this.parseSignature(buffer);
if (sig.device_info !== void 0) {
player.isIOS = sig.device_info.device_brand === "Apple";
player.isAndroid = !player.isIOS;
player.hasSignature = true;
player.asset_digest = this.assets[player.isAndroid ? "android" : "ios"];
print(`${player.email} is playing with an ${player.isIOS ? "Apple" : "Android"} device!`, 36);
}
if (request.auth_ticket) {
print("Authenticate!", 31);
buffer.auth_ticket = AuthTicket();
}
if (auth) buffer.auth_ticket = AuthTicket();
if (buffer.unknown6) {
buffer.unknown6 = [{
"response_type": 6,
@ -153,7 +144,7 @@ export function envelopResponse(status, returns, req, player, auth) {
}];
}
buffer.status_code = status;
buffer.status_code = 1;
return (
POGOProtos.serialize(buffer, "POGOProtos.Networking.Envelopes.ResponseEnvelope")

View File

@ -32,8 +32,6 @@ export function parseMessage(req, type) {
*/
export function processResponse(player, req) {
let buffer = null;
let cc = _toCC(req.request_type);
let msg = this.parseMessage(req, cc);
@ -41,14 +39,26 @@ export function processResponse(player, req) {
try {
switch (req.request_type) {
// Player
case "GET_PLAYER":
player.getPacket("GET_PLAYER", msg).then((result) => {
case "GET_INVENTORY":
case "GET_ASSET_DIGEST":
case "GET_HATCHED_EGGS":
case "CHECK_AWARDED_BADGES":
player.getPacket(req.request_type, msg).then((result) => {
print(`Success: ${req.request_type} => ${result.toString().length}`);
resolve(result);
});
return void 0;
break;
// Global
case "GET_MAP_OBJECTS":
case "CHECK_CHALLENGE":
player.world.getPacket("CHECK_CHALLENGE", msg).then((result) => {
case "DOWNLOAD_SETTINGS":
case "DOWNLOAD_REMOTE_CONFIG_VERSION":
case "DOWNLOAD_ITEM_TEMPLATES":
player.world.getPacket(req.request_type, msg).then((result) => {
print(`Success: ${req.request_type} => ${result.toString().length}`);
resolve(result);
});
return void 0;
@ -61,8 +71,6 @@ export function processResponse(player, req) {
print(`Response error: ${e}`, 31);
};
resolve(buffer);
});
}

View File

@ -6,7 +6,7 @@ import POGOProtos from "pokemongo-protobuf";
import print from "./print";
import CFG from "../cfg";
import * as master from "./master";
import * as shared from "./shared";
import GameMaster from "./models/GameMaster";
@ -36,9 +36,8 @@ export function setup() {
print(`Downloaded assets are valid! Proceeding..`);
master.GAME_MASTER = this.parseGameMaster();
this.master = POGOProtos.serialize(fs.readFileSync(CFG.DUMP_ASSET_PATH + "game_master"), "POGOProtos.Networking.Responses.DownloadItemTemplatesResponse");
let parsedMaster = this.parseGameMaster();
shared.GAME_MASTER = new GameMaster(parsedMaster);
this.setupDatabaseConnection().then(() => {
if (CFG.PORT < 1) {
@ -98,10 +97,10 @@ export function validateModels() {
}
else {
let buffer = fs.readFileSync(path + "asset_digest");
this.assets[name] = {
shared.GAME_ASSETS[name] = {
buffer: buffer,
decode: this.parseProtobuf(buffer, "POGOProtos.Networking.Responses.GetAssetDigestResponse")
}
};
}
// validate models inside folder
@ -130,7 +129,6 @@ export function parseGameMaster() {
try {
let data = fs.readFileSync(CFG.DUMP_ASSET_PATH + "game_master");
master = this.parseProtobuf(data, "POGOProtos.Networking.Responses.DownloadItemTemplatesResponse");
let Master = new GameMaster(master);
} catch (e) {
print(e, 31);
}

6
src/shared.js Normal file
View File

@ -0,0 +1,6 @@
/**
* Global shared assets
*/
export let GAME_ASSETS = {};
export let GAME_MASTER = null;

View File

@ -1,3 +1,6 @@
import POGOProtos from "pokemongo-protobuf";
import pcrypt from "pcrypt";
import CFG from "../cfg";
/**
@ -79,4 +82,14 @@ export function validUsername(str) {
return (
!!(rx_username.test(str))
);
}
/**
* @param {Request} req
*/
export function parseSignature(req) {
let key = pcrypt.decrypt(req.unknown6[0].unknown2.encrypted_signature);
return (
POGOProtos.parseWithUnknown(key, "POGOProtos.Networking.Envelopes.Signature")
);
}