Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Botting #86

Open
Nostrademous opened this issue Jul 22, 2016 · 49 comments
Open

Botting #86

Nostrademous opened this issue Jul 22, 2016 · 49 comments

Comments

@Nostrademous
Copy link

I cloned a while ago from @tejado and have been working on implementing features... Got to say things are going well and I'm willing to answer questions people have, but not willing to copy/paste source code since it would lead to more questions and at this point I'm divergent from the current code base by several revisions (some of them structural).

I do not claim to have the best or most advanced bot, but it does what I want it to do... it just leveled a brand new test account from lvl 1 -> 20 in under a day (servers were stable).

Here is what I have figured out thus far:

  • looping a specified set of waypoints OR a random-walk based on seeded start location
  • use all pokestops we encounter
  • catching all pokemon that are map visible as we walk
    ** catching uses curve balls and probably a "too" high chance of excellent throws
    ** catching uses appropriate level of pokeball based on difficulty of pokemon
    ** catching uses razz berries as necessary based of difficulty of pokemon
  • inventory knowledge - I know how much I have of each item (except evolution candies for now....)
  • pokemon inventory control (aka we transfer pokemons to the professor for candy when overly full, config options to keep what you want by type/nickname/cp-level)
  • ability to scan our Pokedex to know what pokemons we have seen or not seen yet
  • bag item control (delete items we don't care about if we run out of space... also cap our pokeballs so we don't keep too many)
  • egg hatching detection
  • automatic egg incubation
  • detection of bad network conditions or session-key changes by server with auto-reconnect after timeout
  • code for using Lucky Eggs (currently not automated as when to do it is debatable .. )
  • code for automatic evolution of pokemons (although untested still)

Feel free to ask questions, but like I said, I won't be releasing code or copy/pasting solutions, but can help with proto formats.

@ztukaz
Copy link

ztukaz commented Jul 22, 2016

detection of bad network conditions or session-key changes by server with auto-reconnect after timeout -> miss
Tell me more about this, i don't know too much about sessions

@dnsBlah
Copy link

dnsBlah commented Jul 22, 2016

I believe your evolution candies are listed in your inventory as well in the dictionary of the pokemon.

{
            "inventory_item_data": {
              "pokemon_family": {
                "family_id": 124, 
                "candy": 20
              }
            }, 
            "modified_timestamp_ms": 1469131340176
          }

Could you help me out how to trigger egg incubation ?
In the inventory I can find if I have a available incubator and its id, how can to get my eggs id
How do I trigger it ?

@Nostrademous
Copy link
Author

Nostrademous commented Jul 22, 2016

@dnsBlah they are listed in dictionary of pokemons but they all are 0 apparently when you walk it... thanks for the pokemon_family data... that will work

Egg Incubation - the proto is slightly wrong as checked (at least time last time I checked). Notice I have "repeated" whereas what's checked in is "optional". @tejado doesn't provide the .proto files here (not sure why) so it won't be an easy fix for you guys - but that fix is only necessary if you want to incubate multiple eggs at the same time.

message EggIncubators {
  repeated EggIncubator egg_incubator = 1;
}

Below should explain how to use incubators (the code is using my structure, but should give you an idea of how to use it).

def useIncubator(api):
    egg_ids = []
    inc_ids = []
    inv = getInventory(api)
    if inv:
        for items in inv.inventory_delta.inventory_items:
            pk = items.inventory_item_data.pokemon
            if pk and pk is not None:
                if pk.is_egg and not pk.egg_km_walked_start:
                    egg_ids.append(pk.id)
            ics = items.inventory_item_data.egg_incubators
            for ic in ics.egg_incubator:  # <-- requires the fixed proto I mentioned, othewise can't loop
                if ic and ic is not None:
                    if ic.item_id:
                        inc_ids.append(ic.item_id)
    log.debug('Available Eggs for Incubation: %s', egg_ids)
    log.debug('Available Incubators: %s', inc_ids)

    for i in range(0, min(len(egg_ids),len(inc_ids))):
        api.use_item_egg_incubator(item_id=inc_ids[i], pokemon_id=egg_ids[i])
        inc_use = api.call(False)
        log.info('Using Egg Incubator "%s" on "%d"...' % (inc_ids[i], egg_ids[i]))
        inc_pay = getPayload(inc_use)
        if inc_pay:
            inc_resp = rsub.UseItemEggIncubatorResponse()
            inc_resp.ParseFromString(inc_pay)
            print(inc_resp)
        else:
            log.error('Bad Payload - Using Egg Incubator')

@Nostrademous
Copy link
Author

@ztukaz - regarding sessions, honestly I'm not super familiar with that. @tejado might honestly know better as this would be a API library / networking / connectivity issue. What I know is from here:
https://github.com/Mila432/Pokemon_Go_API/blob/master/api.pyy

@dnsBlah
Copy link

dnsBlah commented Jul 22, 2016

@Nostrademous
Thanks for the hints
I don't think the statements are right, as a pokemon['is_egg'] == true does not tell me if its active or not.
Instead the incubator tells me with start_ and target_km_walked
But can't link a incubator to an egg :-/

Or is that the reason why I need a other proto to request the inventory? or just try all 9 eggs until positive result?

@Nostrademous
Copy link
Author

Nostrademous commented Jul 22, 2016

@dnsBlah
pokemon['is_egg'] tells you it's an egg
pokemon['egg_km_walked_start'] is only present if it is an active egg (and can only be present if it's an egg) <-- this is why I check that it is NOT present to know it's an available egg

With both those checks you can then record pokemon['id'] as a valid egg for incubation. That is the 'id' you pass as the 2nd argument to api.use_item_egg_incubator()

Also, looks liek POGO fixed the "repeated" 20 hrs ago.... heh, didnt' realize.
https://github.com/AeonLucid/POGOProtos/blob/master/src/POGOProtos/Inventory/EggIncubators.proto

@dnsBlah
Copy link

dnsBlah commented Jul 22, 2016

Hi @Nostrademous
Like I mentioned, the egg does not show anything about start...

{
            "inventory_item_data": {
              "pokemon": {
                "creation_time_ms": 1469191037546, 
                "captured_cell_id": 5171996602586365952, 
                "is_egg": true, 
                "id": 11891607393952159418
              }
            }, 
            "modified_timestamp_ms": 1469191037546
          }

(I have 9 eggs *max ofcourse) All 9 look like this, but I'm walking 1.

{
            "inventory_item_data": {
              "egg_incubators": {
                "egg_incubator": {
                  "target_km_walked": 153.98680114746094, 
                  "start_km_walked": 148.98680114746094, 
                  "pokemon_id": -4500287810622364247, 
                  "item_type": 901, 
                  "incubator_type": 1, 
                  "item_id": "EggIncubatorProto-1928901772253991081"
                }
              }
            }, 
            "modified_timestamp_ms": 1469219038432
          }, 

See what I mean :)
I understand the call thanks of your hint above.
Seems like almost all calls are just 2 parameters?

But, yet, I don't see a link between the incubator and the egg's
I tried partials of the incibator item_id, of the pokemon_id
None relates to any of the eggs in my inventory

@Nostrademous
Copy link
Author

@dnsBlah I just verified and I guess it changed, you are right, 'km' stuff no longer listed for active eggs.
I guess you loop over the eggs and try each one.

If you try to incubate an egg already in use it will return a RESPONSE with:
ERROR_POKEMON_ALREADY_INCUBATING = 6;

If you get that, just try a different egg:
Results are:

    enum Result {
        UNSET = 0;
        SUCCESS = 1;
        ERROR_INCUBATOR_NOT_FOUND = 2;
        ERROR_POKEMON_EGG_NOT_FOUND = 3;
        ERROR_POKEMON_ID_NOT_EGG = 4;
        ERROR_INCUBATOR_ALREADY_IN_USE = 5;
        ERROR_POKEMON_ALREADY_INCUBATING = 6;
        ERROR_INCUBATOR_NO_USES_REMAINING = 7;
    }

@dnsBlah
Copy link

dnsBlah commented Jul 22, 2016

<3 thank you!

@dnsBlah
Copy link

dnsBlah commented Jul 23, 2016

It also seems like that the incubators are not shown in the inventory list...
Just 1 (the unlimited one), and I have 3

@Nostrademous
Copy link
Author

@dnsBlah are you using ITEM_ID=902 for the "extra incubators"? Will have to check if they show up or not, I don't really care actually as when I use incubators I enumerate them differently.

@dnsBlah
Copy link

dnsBlah commented Jul 23, 2016

I'm guessing i have it working now.. However I don't get unique id's from my item: 902
But will see tomorrow..

@Nostrademous
Copy link
Author

@dnsBlah

def useIncubator(api):
    egg_ids = []
    inc_ids = []
    inv = getInventory(api)
    if inv:
        for items in inv.inventory_delta.inventory_items:
            pk = items.inventory_item_data.pokemon
            if pk and pk is not None:
                if pk.is_egg:
                    egg_ids.append(pk.id)
        for items in inv.inventory_delta.inventory_items:
            ics = items.inventory_item_data.egg_incubators
            for ic in ics.egg_incubator:
                if ic and ic is not None:
                    if ic.item_id: # and not ic.target_km_walked:
                        inc_ids.append(ic.item_id)

    log.debug('All Eggs: %s', egg_ids)
    log.debug('All Incubators: %s', inc_ids)

    for inc in inc_ids:
        for egg in egg_ids:
            api.use_item_egg_incubator(item_id=inc, pokemon_id=egg)
            inc_use = api.call(False)
            inc_pay = getPayload(inc_use)
            if inc_pay:
                inc_resp = rsub.UseItemEggIncubatorResponse()
                inc_resp.ParseFromString(inc_pay)
                if inc_resp.result == 1:
                    log.info('Using Egg Incubator "%s" on "%d"...' % (inc, egg))
                    log.info(inc_resp)
                elif inc_resp.result == 6:
                    continue
                elif inc_resp.result == 5:
                    log.info('Incubator "%s" already in use' % inc)
                    break
            else:
                log.error('Bad Payload - Using Egg Incubator')

@ztukaz
Copy link

ztukaz commented Jul 24, 2016

@Nostrademous

@tejado doesn't provide the .proto files here (not sure why) so it won't be an easy fix for you guys - but that fix is only necessary if you want to incubate multiple eggs at the same time.

Did you imported in this project manually?

@dnsBlah
Copy link

dnsBlah commented Jul 24, 2016

@Nostrademous
With an other proto class its working fine now :)
Also finding other incubators :-)

@Nostrademous
Copy link
Author

Nostrademous commented Jul 26, 2016

@dnsBlah glad you got it working :)

I just recently added mass evolving capability to my bot with the use of a Lucky Egg (if I can do more than 125 evolutions at once). This required tracking proper candy and candy requirements (which I do now).

Also added level-up detection and level-up-prize gathering.

Leveled a brand new account to level 22 in under 12 hours - played by bot from level 1 on (without the use of any evolution or lucky-egg).

@ztukaz
Copy link

ztukaz commented Jul 26, 2016

@Nostrademous
How did you approach gym ?
It should be something like, StartGymBattle, AttackGym and then Put pokemon right?

With StartGymBattle I get always status = 3 and empty results

gym_id = id of the gym (fort)
attacking_pokemon_ids = [idpok1,idpok2]
defending_pokemon_id=id_first_defender
player_latitude=lat
player_longitude=lng

{'responses': {'START_GYM_BATTLE': {}}, 'status_code': 3, 'auth_ticket': {'expire_timestamp_ms': 1469664544675L, 'start': 'tbXTF4N9/wntFc4f0PV6KlBm7kfwsflM2jW/PTtO2tS8jTG9YYAlBBcFTag9PbRo1TFX9NwYDOAiAmuIEpg6bygUFhoHklL52T4i2OWkOgU=', 'end': 'n5kcn21Ojw+YUJZDUBPwwg=='}, 'request_id': 8145806132888207460L}

@dnsBlah
Copy link

dnsBlah commented Jul 27, 2016

@Nostrademous Please share the level-up-prize gathering. :-D
However I'm sure that the items are gathered anyways when you reach the next level tho..
Still I think it would be good to simulate as much as possible. Because lots of times I end up with more items than my bag can handle ;-)

@Nostrademous
Copy link
Author

Nostrademous commented Jul 27, 2016

@ztukaz tackling gyms next - haven't started yet

@dnsBlah - for leveling use the LEVEL_UP_REWARDS call and you must supply your current level (which you can obtain from Inventory ItemData PlayerStats. The response message will have all the info you need, and unlocked new items which you can now start getting at pokestops.

@Nostrademous
Copy link
Author

@ztukaz isn't status_code 3 stating that it is a NEUTRAL GYM? Meaning you can't attack it as no one owns it?

@dnsBlah
Copy link

dnsBlah commented Jul 28, 2016

Hi @Nostrademous

That's so cool! I now get AWARED_ALREADY
Guess I will have to monitor before I level up, to see what the response might be :)

Any idea when this is called in the real game?
In the heartbeat ? Btw you also know how the heartbeat actually looks like? :D

Thanks!

@Nostrademous
Copy link
Author

Nostrademous commented Jul 29, 2016

@ztukaz @tejado
Working on gyms... but apparently I keep failing my request... no idea why: any thoughts?

def battleGym(fort):
    log.info("<>________________________________________________________________________<>")
    log.info("%s GYM NEARBY", TeamColor.DESCRIPTOR.values[fort.owned_by_team].name)
    # get gym details
    gym_proto = getGymDetails(fort)
    if not gym_proto: return 0
    log.info(gym_proto)
    log.info("<>________________________________________________________________________<>")

    ##############################################
    # gather necessary details to start a battle #
    ##############################################

    # check if gym is neutral/unowned - if so deploy to it
    if fort.owned_by_team == 0: # Neutral
        deployPokemonToGym(gym_proto)
        return 0

    # save a boolean checking if we are on the same team
    sameTeam = gl.my_team == fort.owned_by_team

    # find out who is defending
    defending_pokemon = []
    for defender in gym_proto.gym_state.memberships:
        defending_pokemon.append(defender.pokemon_data)

    # determine who we will attack with
    num = 6
    if sameTeam: num = 1
    my_attackers = pickAttackers(num) # this will be a list []

    #log.error('Function not finished, returning out...')
    #return 0

    # start the battle
    log.info('Gym ID: %s' % gym_proto.gym_state.fort_data.id)
    log.info('Attacker list: %s' % str(my_attackers))
    log.info('Defender: %d' % defending_pokemon[0].id)
    gl.api.start_gym_battle(gym_id=gym_proto.gym_state.fort_data.id, attacking_pokemon_ids=my_attackers, defending_pokemon_id=defending_pokemon[0].id, player_latitude=gl.p_lat, player_longitude=gl.p_lng)

    start_reply = gl.api.call(False)
    start_payload = getPayload(start_reply)

Printing the request I see:

 [23:45:59] [ INFO] Gym ID: 555ba115a93546aca7851fed86d3ef6c.16
 [23:45:59] [ INFO] Attacker list: [17xxxxxx list of IDs xxxx 2L]
 [23:45:59] [ INFO] Defender: 568051736162843098
 [23:46:00] [ERROR] startGymBattle() request failed to get payload

and printing the gym_proto result:

 [23:45:59] [ INFO] gym_state {
  fort_data {
    id: "555ba115a93546aca7851fed86d3ef6c.16"
    last_modified_timestamp_ms: 1469762856688
    latitude: 38.854506
    longitude: -77.349488
    owned_by_team: RED
    guard_pokemon_id: FLAREON
    enabled: true
    gym_points: 2000
  }
  memberships {
    pokemon_data {
      id: 568051736162843098
      pokemon_id: FLAREON
      cp: 1002
      stamina: 130
      stamina_max: 130
      move_1: EMBER_FAST
      move_2: FLAMETHROWER
      owner_name: "Firehawk04xx"
      height_m: 0.884167253971
      weight_kg: 9.47041511536
      individual_attack: 15
      individual_defense: 14
      individual_stamina: 1
      cp_multiplier: 0.481684952974
      pokeball: ITEM_GREAT_BALL
      battles_attacked: 10
      battles_defended: 1
      creation_time_ms: 1469753995514
      num_upgrades: 2
      additional_cp_multiplier: 0.0181734859943
      nickname: "Flareon"
    }
    trainer_public_profile {
      name: "Firehawk04xx"
      level: 13
      avatar {
        skin: 2
        hair: 2
        shirt: 1
        hat: 2
        shoes: 1
        backpack: 2
      }
    }
  }
}

@ztukaz
Copy link

ztukaz commented Jul 29, 2016

@Nostrademous I was waiting for you for the same problem, but still didn't get out

@Nostrademous
Copy link
Author

@tejado @ztukaz so I get it to work sometimes. The fix is modifying the StartGymBattleMessage() protobuf. the defender_id needs to be fixed64.

However it fails at time when the defender_id happens to be larger than int64 but still smaller than uint64. Python by default treats everything as signed.. but I checked your rpc_api and you use "setattr()" in the _build_sub_requests() function which is pass by reference.. so I am not sure what the issue is. However, there is a pattern for me. For IDs larger than int64 but still 8-bytes I get no reponse payload from server. This also happens for me in Incense-based Pokemon encounters.

@dnsBlah
Copy link

dnsBlah commented Jul 29, 2016

I'm just getting responses like:
Session.py - line 407 - startGymBattle()

status_code: 3
request_id: 951201794807
returns: ""

Which are not good I guess status 3? Or I will need the request_id to perform AttackGymMessage <-> Response for the actual battle I guess
Then still I think status 3 is not good

According to the responses it should be, ERROR_GYM_NEUTRAL ?
The gym is not neutral! :-/

@Nostradamous where exactly do you change what in the request message ?

@Nostrademous
Copy link
Author

@dnsBlah if you go into the /pgoapi/protos/POGOProtos_src/Networking/Requests/Messages/StartGymBattleMessage.proto

you need to change the defending_id from uint64 to fixed64

then you need to recompile the proto using "protoc" which you need to have installed of version 3.0.0b4

@dnsBlah
Copy link

dnsBlah commented Jul 29, 2016

Ahhh I need to do that before compiling it!?
Thanks will have a look :)


awesome ;-) but its not always working, however using the same defender, so that part has nothing to do with the fixed64, it's fine I guess
I am experiencing some server issues throughout the whole day already tho.

Guess its a matter of a loop now
and send back the actions battle_log.battle_actions to the BattleAction proto, together with the battle_id and some BattleAction's...
Not sure how to create a BattleAction fo... send an fast-attack for special

@joshk6656
Copy link
Contributor

@Nostrademous can you show some examples of running / reading forts from map_objects (i keep getting a weird error, at work now so can't supply it at this time)?

@dnsBlah
Copy link

dnsBlah commented Aug 2, 2016

You need bigger delay's... You can only call map_objects per 5 seconds.
Besides that there are hardly any pokemon shown anymore. Only within a range of 50-70 meters. Dispite the fact your scanning a bigger area

@Nostrademous
Copy link
Author

@joshk6656 did @dnsBlah comments help you? It's hard to tell what your errors were. If you are not getting good fort data from map_objects it's probably b/c you are soft-banned for teleporting too much. Otherwise it is fairly straight forward.

@Nostrademous
Copy link
Author

Fixed Incense Encounters (catch them all now - reference for fix: AeonLucid/POGOProtos#124

Added support for detecting and catching Lured Pokemon at Lured Pokestops (just check the fort details -> modifiers -> item_id == 501 and check fort.lure_info.lure_expires_timestamp_ms to know if it is lured and for how long). Then use the DiskEncounterMessage and pass the fort.lure_info.fort_id as the spawnpoint_id to the CatchPokemonMessage.

@ztukaz
Copy link

ztukaz commented Aug 2, 2016

in the field attack_actions used in api.attack_gym ( gym_id , battle_id, attack_actions, last_retrieved_actions, player_latitude, player_longitude)
Did you find out what the ??? stands for?

attack_actions = {
         "action_start_ms": int(round(time.time() * 1000)),  #time when the attack start
         "target_index": -1,                                                   #??? index of the array of defensor?
         "damage_windows_end_timestamp_mss":,            #time when the attack end
         "active_pokemon_id":                                             #??? id of attacker
         "attacker_index": -1,                                               #??? index of the array of attacker?
         "duration_ms": 750,                                                #??? duration of the attack
         "energy_delta": 7,                                                   #???
         "Type": ,                                                                  #???
         "damage_windows_start_timestamp_mss":            #???
}

@Nihisil
Copy link

Nihisil commented Aug 3, 2016

@Nostrademous if you can tell how to build actions to api.attack_gym it would be really nice :)

I'm using:

        for x in range(1, times):
            start = server_ms + (x * pokemon_move['duration'])
            window_end = start + pokemon_move['duration']
            window_start = window_end - 200
            actions.append({
                'Type': BattleActionType.ACTION_ATTACK,
                'action_start_ms': server_ms + (x * pokemon_move['duration']),
                'duration_ms': pokemon_move['duration'],
                'damage_windows_start_timestamp_mss': window_start,
                'damage_windows_end_timestamp_mss': window_end,
                'active_pokemon_id': pokemon_id,
                'energy_delta': pokemon_move['damage'] - 1,
                'target_index': -1,
                'attacker_index': -1,
            })

and as result:

[
    {
        "damage_windows_end_timestamp_mss": 1470193970167,
        "active_pokemon_id": 14676247372908233687,
        "action_start_ms": 1470193969627,
        "attacker_index": -1,
        "duration_ms": 540,
        "energy_delta": 6,
        "type": 1,
        "target_index": -1,
        "damage_windows_start_timestamp_mss": 1470193969967
    }
    ...
]

But server didn't accept them, so they are not appear in battle_actions section, so probably I missed some required fields, or I'm sending not right values.

@Nostrademous
Copy link
Author

@ztukaz and @Nihisil Haven't gotten there yet... I can start gym battle's now, but haven't written code to do the actual fight yet.

Instead I spent my time fixing lures/incense encounters, and writing code to auto-deploy pokemon to gyms that belong to my team but don't have full membership saturation (low hanging fruit for getting into a gym). Also track IV stats of pokemon now.

I will work on battles next, although any bugs I find trump that. Also, had a friend implement a webserver to track my bot and all info I want (example below).
web

@Nihisil
Copy link

Nihisil commented Aug 3, 2016

@Nostrademous got it, I'm looking forward to hear update from you about gym battles. If I will be able to fix it, I will let you know what I did.

Also, maybe do you have a dump of official app traffic?

@Nostrademous
Copy link
Author

@Nihisil would be much appreciated if you share what you did if you get it working

Regarding web-server - i don't dump any official traffic... the webserver runs from my own bot and uses only bot data. I just download a package with all the pokemon icons and use google's map api to draw pokestops and pokemon on them. All blue circles are pokestops, those that are connected are the path I plan on taking (calculated using some advanced traveling salesman algorithm), the pokemon appear where I find/catch them.

@Nihisil
Copy link

Nihisil commented Aug 3, 2016

@Nostrademous got it. I was interested in official traffic, because of required attributes to attack gym :)

Your webversion looking great, btw.

@dnsBlah
Copy link

dnsBlah commented Aug 3, 2016

That web integration is crazy! wow

@Nihisil I guess we'll need to use the data/battleaction to setup and retreive actions
as we also beed to send last_received actions
I think there must be a way to retrieve the last actions through the proto directly as a battleaction type
or convert them somehow :-s

@Nihisil
Copy link

Nihisil commented Aug 3, 2016

@dnsBlah yeah, I have sent latest action.

I tried different ways to send attack_actions, but server just doesn't accept them (but it returns OK response) and battle always ends with my defeat.

@dnsBlah
Copy link

dnsBlah commented Aug 3, 2016

Currently I'm in the need to resolve my status_code 3 on numerous requests.
When I fixed it I'm gonna have a look into the battleAction proto
Maybe again something wrong with the proto, and needs to be fixed64 or so, especially the defender id

@ztukaz
Copy link

ztukaz commented Aug 3, 2016

@dnsBlah #161

@dnsBlah
Copy link

dnsBlah commented Aug 3, 2016

@ztukaz
not 53 102
but 3

STATUS CODE 3!
status_code: 3
request_id: 843962591764
returns: ""

This happend randomly in getMapObjects, useItemCapture, capturePokemon
after 10 times, it will re-login from scratch

Sometimes it's fixed, most times it doesnt, also seems location related...
Doing getMapObjects max. 10 time with a delay of at least 5 + the loop counter
as well as increasing the radius to search with 25 each time.

@Nostrademous
Copy link
Author

Making progress here - bunch of things needed to be done first.

First - need to heal my pokemon that I am trying to fight with. If you submit your attacker list but one isn't full health you will get a bad payload return from server. Implementing this now.

@Nostrademous
Copy link
Author

Okay, getting far enough to have my first AttackGymMessage accepted... I have realized the first message you send after StartGymBattle must be essentially blank.

I basically send a AttackGym() with only gym_id, battle_id and player lat/lng.

Server replies with a valid "Active Attacker" and "Active Defender" information with health.. as well as Battle Log info with server timestamp (so we can synchronize actions as your time might have skew) and target_index information I can use in following attacks. This info is the same as in StartGymBattle() but at least I know it's somewhat working.

@Nihisil
Copy link

Nihisil commented Aug 3, 2016

@Nostrademous was you able to put your attack message to the server?

So you send message and it appears in the battle_log.

I send first request with empty attack actions list after this I'm trying to send a new attack message in loop, each one second.

So, each second I'm getting response ATTACK_GYM, and I'm trying to use this information to send my next message. But server didn't apply my actions.

If you did it and server accept your actions, can you please send to me example of code with your attack_actions? I wonder what attributes do you use.

@Nostrademous
Copy link
Author

Nostrademous commented Aug 3, 2016

@tejado I think the issue currently is that you don't support RPC requests where a "nested list/dictionary" type is passed when building outgoing requests in your API library.

For AttackGym we need to supply a "repeated BattleAction" list and you currently only handle dictionaries, lists and base type but not lists of more complicated types, etc

EDIT: in reality I think we need to pass "repeated class<RpcSub.BattleAction>" objects

@Nostrademous
Copy link
Author

Nostrademous commented Aug 3, 2016

I believe rpc_api.py needs to be refined to handle a list of BattleActions.

Something like: NOTE - COMPLETELY UNTESTED CODE

                for (key, value) in entry_content.items():
                    if isinstance(value, list):
                        #self.log.error('Found list: %s - trying as repeated', key)
                        for i in value:
                            #self.log.error('Value is %s' % (type(i)))
                            if isinstance(i, RpcSub.BattleAction):
                                self.log.error('RpcSub.BattleAction Class')
                                subsub_ext = get_class('pgoapi.protos.RpcSub_pb2.BattleAction')()
                                try:
                                    setattr(subsub_ext, 'Type', i.Type)
                                    setattr(subsub_ext, 'action_start_ms', i.action_start_ms)
                                    setattr(subsub_ext, 'duration_ms', i.duration_ms)
                                    setattr(subsub_ext, 'target_index', i.target_index) 
                                    r = getattr(subrequest_extension, key)
                                    r.append(subsub_ext)
                                except Exception as e:
                                    self.log.warning('Argument %s with value %s unknown inside %s (Exception: %s)', key, str(value), proto_name, str(e))

                            else:
                                try:
                                    r = getattr(subrequest_extension, key)
                                    r.append(i)
                                except Exception as e:
                                    self.log.warning('Arguement %s with value %s unknown inside %s (Exception %s)', key, i, proto_name, str(e))

@Nostrademous
Copy link
Author

Made a separate issue based on the what I believe is preventing this API library from properly attacking gyms.

@Nihisil
Copy link

Nihisil commented Aug 4, 2016

@Nostrademous maybe this will help AeonLucid/POGOProtos#112 when api will start to work again.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

5 participants