Skip to content

Commit cefc848

Browse files
committed
Release v2.0.0
2 parents a3b636f + 1d19567 commit cefc848

9 files changed

Lines changed: 295 additions & 206 deletions

File tree

‎README.md‎

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -8,12 +8,12 @@
88

99
**PokéNurse** is a desktop application for Windows and Mac that allows you to manage your pokémon from Pokémon Go without the need for a mobile device. You can now favorite, transfer, and evolve from the comfort of your own home!
1010

11-
## Downloads for v1.9.0
11+
## Downloads for v2.0.0
1212
You may view all the releases [here](https://github.com/vinnymac/PokeNurse/releases)
13-
* [macOS](https://github.com/vinnymac/PokeNurse/releases/download/v1.9.0/PokeNurse.dmg)
14-
* [Windows](https://github.com/vinnymac/PokeNurse/releases/download/v1.9.0/PokeNurse.exe)
15-
* [Linux 32 bit](https://github.com/vinnymac/PokeNurse/releases/download/v1.9.0/PokeNurse-ia32.deb)
16-
* [Linux 64 bit](https://github.com/vinnymac/PokeNurse/releases/download/v1.9.0/PokeNurse-x64.deb)
13+
* [macOS](https://github.com/vinnymac/PokeNurse/releases/download/v2.0.0/PokeNurse.dmg)
14+
* [Windows](https://github.com/vinnymac/PokeNurse/releases/download/v2.0.0/PokeNurse.exe)
15+
* [Linux 32 bit](https://github.com/vinnymac/PokeNurse/releases/download/v2.0.0/PokeNurse-ia32.deb)
16+
* [Linux 64 bit](https://github.com/vinnymac/PokeNurse/releases/download/v2.0.0/PokeNurse-x64.deb)
1717

1818
## Examples
1919
![Login Window](app/loginExample.png)

‎app/actions/authenticate.js‎

Lines changed: 18 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -9,11 +9,10 @@ import {
99

1010
import * as fs from 'async-file'
1111

12-
import client from '../client'
12+
import { setClient } from '../client'
1313

1414
import {
15-
getTrainerInfo,
16-
getTrainerPokemon
15+
getTrainerInfoAndPokemon,
1716
} from './trainer'
1817

1918
const saveAccountCredentialsFailed = createAction('SAVE_ACCOUNT_CREDENTIALS_FAILED')
@@ -29,9 +28,7 @@ const userLoginFailed = createAction('USER_LOGIN_FAILED')
2928
const accountPath = path.join(remote.app.getPath('appData'), '/pokenurse/account.json')
3029

3130
export default {
32-
client,
33-
34-
login({ method, username, password }) {
31+
login({ method, username, password, hashingKey }) {
3532
return async (dispatch) => {
3633
dispatch(userLoginStarted())
3734

@@ -45,15 +42,25 @@ export default {
4542
try {
4643
const token = await login.login(username, password)
4744

48-
client.setAuthInfo(method, token)
45+
const options = {
46+
hashingKey,
47+
authType: method,
48+
authToken: token,
49+
useHashingServer: !!hashingKey,
50+
}
51+
52+
// Use API version 0.51 (minimum version for hashing server)
53+
if (hashingKey) options.version = 5100
54+
55+
const client = new pogobuf.Client(options)
56+
4957
client.init()
5058

59+
setClient(client)
60+
5161
// TODO display a loading spinner
5262
// then fetch all necessary things
53-
await Promise.all([
54-
dispatch(getTrainerInfo()),
55-
dispatch(getTrainerPokemon())
56-
])
63+
await dispatch(getTrainerInfoAndPokemon())
5764

5865
dispatch(userLoginSuccess())
5966
} catch (error) {

‎app/actions/trainer.js‎

Lines changed: 69 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ import {
1010
ipcRenderer,
1111
} from 'electron'
1212

13-
import client from '../client'
13+
import { getClient } from '../client'
1414

1515
// TODO Must move these helpers to app folder
1616
import utils from '../utils'
@@ -53,7 +53,7 @@ function generateEmptySpecies(candies, pokemonSettings) {
5353
})
5454
}
5555

56-
// TODO Can we find these constants in POGOBuf or item templates?
56+
// TODO Can we find these constants in POGOProtos or item templates?
5757
const MILLISECONDS_FACTOR = 1000
5858
const MOVE2_CHARGE_DELAY_MS = 500
5959
const STAB_MULTIPLIER = 1.25 // 25% damage boost
@@ -256,18 +256,22 @@ const transferPokemonFailed = createAction('TRANSFER_POKEMON_FAILED')
256256
const evolvePokemonSuccess = createAction('EVOLVE_POKEMON_SUCCESS')
257257
const evolvePokemonFailed = createAction('EVOLVE_POKEMON_FAILED')
258258

259+
function handleGetPlayerResponse(dispatch, response) {
260+
if (!response.success) {
261+
throw new Error('Failed in retrieving player info. Please restart.')
262+
}
263+
264+
dispatch(getTrainerInfoSuccess({
265+
trainerData: response.player_data
266+
}))
267+
}
268+
259269
function getTrainerInfo() {
260270
return async (dispatch) => {
261271
try {
262-
const response = await client.getPlayer()
272+
const response = await getClient().getPlayer()
263273

264-
if (!response.success) {
265-
dispatch(getTrainerInfoFailed('Failed in retrieving player info. Please restart.'))
266-
return
267-
}
268-
dispatch(getTrainerInfoSuccess({
269-
trainerData: response.player_data
270-
}))
274+
handleGetPlayerResponse(dispatch, response)
271275
} catch (error) {
272276
dispatch(getTrainerInfoFailed(error))
273277
}
@@ -315,9 +319,32 @@ function parseItemTemplates(templates) {
315319

316320
let splitItemTemplates = null
317321

322+
function handleGetItemTemplatesResponse(dispatch, itemTemplates) {
323+
if (!itemTemplates) return
324+
325+
// TODO do not do this everytime we fetch the trainer pokemon, separate first fetch + refresh
326+
itemTemplates.success = itemTemplates.result === 1
327+
328+
if (!itemTemplates.success) {
329+
throw new Error('Failed to retrieve item templates')
330+
}
331+
332+
splitItemTemplates = parseItemTemplates(itemTemplates)
333+
}
334+
335+
function handleGetInventoryResponse(dispatch, inventory) {
336+
if (!inventory.success) {
337+
throw new Error('Failed to retrieve Trainers Pokemon')
338+
}
339+
340+
const payload = parseInventory(inventory)
341+
342+
dispatch(getTrainerPokemonSuccess(payload))
343+
}
344+
318345
async function getInventoryAndItemTemplates(dispatch, inventoryOnly) {
319346
try {
320-
const batch = client.batchStart()
347+
const batch = getClient().batchStart()
321348
batch.getInventory(0)
322349
if (!inventoryOnly) batch.downloadItemTemplates()
323350

@@ -332,47 +359,47 @@ async function getInventoryAndItemTemplates(dispatch, inventoryOnly) {
332359
[inventory, itemTemplates] = response
333360
}
334361

335-
if (!inventory.success) {
336-
dispatch(getTrainerPokemonFailed('Failed to retrieve Trainers Pokemon'))
337-
return
338-
}
339-
340-
if (!inventoryOnly) {
341-
// TODO do not do this everytime we fetch the trainer pokemon, separate first fetch + refresh
342-
itemTemplates.success = itemTemplates.result === 1
343-
344-
if (!itemTemplates.success) {
345-
dispatch(getTrainerPokemonFailed('Failed to retrieve item templates'))
346-
return
347-
}
348-
349-
splitItemTemplates = parseItemTemplates(itemTemplates)
350-
}
351-
352-
const payload = parseInventory(inventory)
353-
354-
dispatch(getTrainerPokemonSuccess(payload))
362+
handleGetItemTemplatesResponse(dispatch, itemTemplates)
363+
handleGetInventoryResponse(dispatch, inventory)
355364
} catch (error) {
356365
dispatch(getTrainerPokemonFailed(error))
357366
}
358367
}
359368

369+
function getTrainerInfoAndPokemon() {
370+
return async (dispatch) => {
371+
const response = await getClient()
372+
.batchStart()
373+
.getInventory(0)
374+
.downloadItemTemplates()
375+
.getPlayer()
376+
.batchCall()
377+
378+
const [inventory, itemTemplates, player] = response
379+
380+
handleGetItemTemplatesResponse(dispatch, itemTemplates)
381+
handleGetInventoryResponse(dispatch, inventory)
382+
handleGetPlayerResponse(dispatch, player)
383+
}
384+
}
385+
360386
function refreshPokemon() {
361-
return (dispatch) => getInventoryAndItemTemplates(dispatch, true)
387+
return async (dispatch) => getInventoryAndItemTemplates(dispatch, true)
362388
}
363389

390+
// TODO might be unnecessary now
364391
function getTrainerPokemon() {
365-
return (dispatch) => getInventoryAndItemTemplates(dispatch)
392+
return async (dispatch) => getInventoryAndItemTemplates(dispatch)
366393
}
367394

368395
function powerUpPokemon(pokemon) {
369396
return async (dispatch) => {
370397
try {
371-
await client.upgradePokemon(pokemon.id)
398+
await getClient().upgradePokemon(pokemon.id)
372399

373400
// TODO parse the response instead of retrieving all the new pokemon
374401
// Requires replacing the main parsing with more functional code
375-
await dispatch(getTrainerPokemon())
402+
await dispatch(refreshPokemon())
376403
dispatch(powerUpPokemonSuccess(pokemon))
377404
} catch (error) {
378405
dispatch(powerUpPokemonFailed(error))
@@ -388,7 +415,7 @@ function toggleFavoritePokemon(pokemon) {
388415
favorite: !pokemon.favorite ? -1 : -0
389416
})
390417

391-
await client.setFavoritePokemon(pokemon.id, !!updatedPokemon.favorite)
418+
await getClient().setFavoritePokemon(pokemon.id, !!updatedPokemon.favorite)
392419
dispatch(toggleFavoritePokemonSuccess(updatedPokemon))
393420
} catch (error) {
394421
dispatch(toggleFavoritePokemonFailed(error))
@@ -401,7 +428,7 @@ function renamePokemon(pokemon, nickname, callback) {
401428

402429
return async (dispatch) => {
403430
try {
404-
await client.nicknamePokemon(updatedPokemon.id, updatedPokemon.nickname)
431+
await getClient().nicknamePokemon(updatedPokemon.id, updatedPokemon.nickname)
405432

406433
dispatch(renamePokemonSuccess(updatedPokemon))
407434

@@ -429,7 +456,7 @@ function transferPokemon(pokemon, delay) {
429456
return async (dispatch) => {
430457
try {
431458
await sleep(delay)
432-
await client.releasePokemon(pokemon.id)
459+
await getClient().releasePokemon(pokemon.id)
433460
dispatch(transferPokemonSuccess(pokemon))
434461
} catch (error) {
435462
dispatch(transferPokemonFailed(error))
@@ -442,7 +469,7 @@ function evolvePokemon(pokemon, delay) {
442469
return async (dispatch) => {
443470
try {
444471
await sleep(delay)
445-
await client.evolvePokemon(pokemon.id)
472+
await getClient().evolvePokemon(pokemon.id)
446473
dispatch(evolvePokemonSuccess(pokemon))
447474
} catch (error) {
448475
dispatch(evolvePokemonFailed(error))
@@ -454,7 +481,7 @@ function evolvePokemon(pokemon, delay) {
454481
const updateMonster = createAction('UPDATE_MONSTER')
455482

456483
function batchStart(selectedPokemon, method) {
457-
let batch = client.batchStart()
484+
let batch = getClient().batchStart()
458485

459486
selectedPokemon.forEach((p) => {
460487
batch = batch[method](p.id)
@@ -468,7 +495,7 @@ function resetStatusAndGetPokemon(errorMessage) {
468495
try {
469496
dispatch(resetStatus())
470497
await sleep(100) // Pogobuf may need a tick after a large batch
471-
await dispatch(getTrainerPokemon())
498+
await dispatch(refreshPokemon())
472499
if (errorMessage) ipcRenderer.send('error-message', errorMessage)
473500
} catch (e) {
474501
errorMessage = errorMessage ? `${errorMessage}\n\n${e}` : `Failed to fetch pokemon:\n\n${e}`
@@ -513,6 +540,7 @@ export default {
513540
sortWithDefaults: createAction('SORT_WITH_DEFAULTS'),
514541
getTrainerInfo,
515542
getTrainerPokemon,
543+
getTrainerInfoAndPokemon,
516544
powerUpPokemon,
517545
toggleFavoritePokemon,
518546
renamePokemon,

‎app/client.js‎

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,11 @@
1-
import pogobuf from 'pogobuf'
1+
let client = null
22

3-
export default new pogobuf.Client()
3+
export default {
4+
getClient() {
5+
return client
6+
},
7+
8+
setClient(c) {
9+
client = c
10+
}
11+
}

‎app/package.json‎

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
{
22
"name": "PokeNurse",
33
"productName": "PokeNurse",
4-
"version": "1.9.0",
4+
"version": "2.0.0",
55
"description": "A tool for Pokémon Go to aid in transferring and evolving Pokémon",
66
"main": "./main.js",
77
"author": {
@@ -13,7 +13,7 @@
1313
"dependencies": {
1414
"async-file": "^2.0.2",
1515
"electron-localshortcut": "^1.0.0",
16-
"node-pogo-protos": "2.4.0",
17-
"pogobuf": "1.8.0"
16+
"node-pogo-protos": "2.4.2",
17+
"pogobuf": "1.9.0"
1818
}
1919
}

0 commit comments

Comments
 (0)