poke-go-api 0.0.8 → 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/lib/poke-api.rb +9 -1
- data/lib/poke-api/POGOProtos/Signature.rb +94 -0
- data/lib/poke-api/POGOProtosSource/Signature.proto +100 -0
- data/lib/poke-api/auth/google.rb +5 -5
- data/lib/poke-api/auth/ptc.rb +3 -3
- data/lib/poke-api/auth/ticket.rb +51 -0
- data/lib/poke-api/client.rb +17 -15
- data/lib/poke-api/errors.rb +18 -0
- data/lib/poke-api/geometry/s2_base.rb +50 -0
- data/lib/poke-api/geometry/s2_cell_id.rb +146 -0
- data/lib/poke-api/geometry/s2_lat_lon.rb +19 -0
- data/lib/poke-api/geometry/s2_point.rb +33 -0
- data/lib/poke-api/helpers.rb +24 -0
- data/lib/poke-api/request_builder.rb +82 -5
- data/lib/poke-api/response.rb +15 -2
- data/lib/poke-api/testing.rb +31 -18
- data/lib/poke-api/version.rb +1 -1
- metadata +37 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 7d4e06820ff24205fd6343be9abac2400d08b2e3
|
4
|
+
data.tar.gz: 1f3294582db49573f3805226e6515d6b42c94d37
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 73b3a3e1c09ffdaca9bfbb14d5f08023dafc78ee4dc0b5339b673ad99e0d91ad401e0957fdd0701846747b25c98c01b78dd7d790d5634c0faf39c3eac6f0125c
|
7
|
+
data.tar.gz: d8b0b6f96f603393cd721172ca9308f4de3198605910c8d3b54b64ff892f6dfcf901811aa433d1f6790ff43667afe1537a3d45ce6ff59b90d322d808a3f47d12
|
data/lib/poke-api.rb
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
# Load Poke
|
1
|
+
# Load main Poke::API related classes
|
2
2
|
require 'poke-api/logging'
|
3
3
|
require 'poke-api/client'
|
4
4
|
require 'poke-api/helpers'
|
@@ -8,7 +8,15 @@ require 'poke-api/errors'
|
|
8
8
|
require 'poke-api/version'
|
9
9
|
require 'poke-api/auth/ptc'
|
10
10
|
require 'poke-api/auth/google'
|
11
|
+
require 'poke-api/auth/ticket'
|
12
|
+
|
13
|
+
# Load Geometry libraries (native Ruby)
|
14
|
+
require 'poke-api/geometry/s2_base'
|
15
|
+
require 'poke-api/geometry/s2_cell_id'
|
16
|
+
require 'poke-api/geometry/s2_lat_lon'
|
17
|
+
require 'poke-api/geometry/s2_point'
|
11
18
|
|
12
19
|
# Load Google Generated POGOProtos
|
20
|
+
require 'poke-api/POGOProtos/Signature'
|
13
21
|
require 'poke-api/POGOProtos/Networking/Envelopes/RequestEnvelope'
|
14
22
|
require 'poke-api/POGOProtos/Networking/Envelopes/ResponseEnvelope'
|
@@ -0,0 +1,94 @@
|
|
1
|
+
# Generated by the protocol buffer compiler. DO NOT EDIT!
|
2
|
+
# source: Signature.proto
|
3
|
+
|
4
|
+
require 'google/protobuf'
|
5
|
+
|
6
|
+
Google::Protobuf::DescriptorPool.generated_pool.build do
|
7
|
+
add_message "Signature" do
|
8
|
+
optional :timestamp_since_start, :uint64, 2
|
9
|
+
repeated :location_fix, :message, 4, "Signature.LocationFix"
|
10
|
+
optional :gps_info, :message, 5, "Signature.AndroidGpsInfo"
|
11
|
+
optional :sensor_info, :message, 7, "Signature.SensorInfo"
|
12
|
+
optional :device_info, :message, 8, "Signature.DeviceInfo"
|
13
|
+
optional :activity_status, :message, 9, "Signature.ActivityStatus"
|
14
|
+
optional :location_hash1, :uint32, 10
|
15
|
+
optional :location_hash2, :uint32, 20
|
16
|
+
optional :unk22, :bytes, 22
|
17
|
+
optional :timestamp, :uint64, 23
|
18
|
+
repeated :request_hash, :uint64, 24
|
19
|
+
end
|
20
|
+
add_message "Signature.LocationFix" do
|
21
|
+
optional :provider, :string, 1
|
22
|
+
optional :timestamp_since_start, :uint64, 2
|
23
|
+
optional :latitude, :float, 13
|
24
|
+
optional :longitude, :float, 14
|
25
|
+
optional :horizontal_accuracy, :float, 20
|
26
|
+
optional :altitude, :float, 21
|
27
|
+
optional :vertical_accuracy, :float, 22
|
28
|
+
optional :provider_status, :uint64, 26
|
29
|
+
optional :floor, :uint32, 27
|
30
|
+
optional :location_type, :uint64, 28
|
31
|
+
end
|
32
|
+
add_message "Signature.AndroidGpsInfo" do
|
33
|
+
optional :time_to_fix, :uint64, 1
|
34
|
+
repeated :satellites_prn, :int32, 2
|
35
|
+
repeated :snr, :float, 3
|
36
|
+
repeated :azimuth, :float, 4
|
37
|
+
repeated :elevation, :float, 5
|
38
|
+
repeated :has_almanac, :bool, 6
|
39
|
+
repeated :has_ephemeris, :bool, 7
|
40
|
+
repeated :used_in_fix, :bool, 8
|
41
|
+
end
|
42
|
+
add_message "Signature.SensorInfo" do
|
43
|
+
optional :timestamp_snapshot, :uint64, 1
|
44
|
+
optional :magnetometer_x, :double, 3
|
45
|
+
optional :magnetometer_y, :double, 4
|
46
|
+
optional :magnetometer_z, :double, 5
|
47
|
+
optional :angle_normalized_x, :double, 6
|
48
|
+
optional :angle_normalized_y, :double, 7
|
49
|
+
optional :angle_normalized_z, :double, 8
|
50
|
+
optional :accel_raw_x, :double, 10
|
51
|
+
optional :accel_raw_y, :double, 11
|
52
|
+
optional :accel_raw_z, :double, 12
|
53
|
+
optional :gyroscope_raw_x, :double, 13
|
54
|
+
optional :gyroscope_raw_y, :double, 14
|
55
|
+
optional :gyroscope_raw_z, :double, 15
|
56
|
+
optional :accel_normalized_x, :double, 16
|
57
|
+
optional :accel_normalized_y, :double, 17
|
58
|
+
optional :accel_normalized_z, :double, 18
|
59
|
+
optional :accelerometer_axes, :uint64, 19
|
60
|
+
end
|
61
|
+
add_message "Signature.DeviceInfo" do
|
62
|
+
optional :device_id, :string, 1
|
63
|
+
optional :android_board_name, :string, 2
|
64
|
+
optional :android_bootloader, :string, 3
|
65
|
+
optional :device_brand, :string, 4
|
66
|
+
optional :device_model, :string, 5
|
67
|
+
optional :device_model_identifier, :string, 6
|
68
|
+
optional :device_model_boot, :string, 7
|
69
|
+
optional :hardware_manufacturer, :string, 8
|
70
|
+
optional :hardware_model, :string, 9
|
71
|
+
optional :firmware_brand, :string, 10
|
72
|
+
optional :firmware_tags, :string, 12
|
73
|
+
optional :firmware_type, :string, 13
|
74
|
+
optional :firmware_fingerprint, :string, 14
|
75
|
+
end
|
76
|
+
add_message "Signature.ActivityStatus" do
|
77
|
+
optional :start_time_ms, :uint64, 1
|
78
|
+
optional :unknown_status, :bool, 2
|
79
|
+
optional :walking, :bool, 3
|
80
|
+
optional :running, :bool, 4
|
81
|
+
optional :stationary, :bool, 5
|
82
|
+
optional :automotive, :bool, 6
|
83
|
+
optional :tilting, :bool, 7
|
84
|
+
optional :cycling, :bool, 8
|
85
|
+
optional :status, :bytes, 9
|
86
|
+
end
|
87
|
+
end
|
88
|
+
|
89
|
+
Signature = Google::Protobuf::DescriptorPool.generated_pool.lookup("Signature").msgclass
|
90
|
+
Signature::LocationFix = Google::Protobuf::DescriptorPool.generated_pool.lookup("Signature.LocationFix").msgclass
|
91
|
+
Signature::AndroidGpsInfo = Google::Protobuf::DescriptorPool.generated_pool.lookup("Signature.AndroidGpsInfo").msgclass
|
92
|
+
Signature::SensorInfo = Google::Protobuf::DescriptorPool.generated_pool.lookup("Signature.SensorInfo").msgclass
|
93
|
+
Signature::DeviceInfo = Google::Protobuf::DescriptorPool.generated_pool.lookup("Signature.DeviceInfo").msgclass
|
94
|
+
Signature::ActivityStatus = Google::Protobuf::DescriptorPool.generated_pool.lookup("Signature.ActivityStatus").msgclass
|
@@ -0,0 +1,100 @@
|
|
1
|
+
syntax = "proto3";
|
2
|
+
|
3
|
+
message Signature {
|
4
|
+
|
5
|
+
message LocationFix {
|
6
|
+
string provider = 1; // "network", "gps", "fused", possibly others
|
7
|
+
uint64 timestamp_since_start = 2; // in ms
|
8
|
+
float latitude = 13;
|
9
|
+
float longitude = 14;
|
10
|
+
|
11
|
+
// ??? shows up in struct, dunno where these go
|
12
|
+
// float device_speed;
|
13
|
+
// float device_course;
|
14
|
+
float horizontal_accuracy = 20; // iOS only? (range seems to be -1 to +1)
|
15
|
+
float altitude = 21;
|
16
|
+
float vertical_accuracy = 22; // iOS only? (range seems to be ~10-12)
|
17
|
+
uint64 provider_status = 26; // Usually 3 (possibly GPS status: 1 = no fix, 2 = acquiring/inaccurate, 3 = fix acquired)
|
18
|
+
// On iOS there are some LocationFixes with unk26=1 and everything else empty
|
19
|
+
uint32 floor = 27; // No idea what this is, seems to be optional
|
20
|
+
uint64 location_type = 28; // Always 1 (if there is data at all)
|
21
|
+
}
|
22
|
+
|
23
|
+
// don't really care about this since we're not using it
|
24
|
+
message AndroidGpsInfo {
|
25
|
+
uint64 time_to_fix = 1;
|
26
|
+
repeated int32 satellites_prn = 2;
|
27
|
+
repeated float snr = 3;
|
28
|
+
repeated float azimuth = 4;
|
29
|
+
repeated float elevation = 5;
|
30
|
+
repeated bool has_almanac = 6;
|
31
|
+
repeated bool has_ephemeris = 7;
|
32
|
+
repeated bool used_in_fix = 8;
|
33
|
+
}
|
34
|
+
|
35
|
+
message SensorInfo {
|
36
|
+
uint64 timestamp_snapshot = 1; // in ms
|
37
|
+
double magnetometer_x = 3;
|
38
|
+
double magnetometer_y = 4;
|
39
|
+
double magnetometer_z = 5;
|
40
|
+
double angle_normalized_x = 6;
|
41
|
+
double angle_normalized_y = 7;
|
42
|
+
double angle_normalized_z = 8;
|
43
|
+
double accel_raw_x = 10;
|
44
|
+
double accel_raw_y = 11;
|
45
|
+
double accel_raw_z = 12;
|
46
|
+
double gyroscope_raw_x = 13;
|
47
|
+
double gyroscope_raw_y = 14;
|
48
|
+
double gyroscope_raw_z = 15;
|
49
|
+
double accel_normalized_x = 16;
|
50
|
+
double accel_normalized_y = 17;
|
51
|
+
double accel_normalized_z = 18;
|
52
|
+
uint64 accelerometer_axes = 19; // Always 3
|
53
|
+
}
|
54
|
+
|
55
|
+
message DeviceInfo {
|
56
|
+
string device_id = 1; // Hex string
|
57
|
+
string android_board_name = 2;
|
58
|
+
string android_bootloader = 3;
|
59
|
+
string device_brand = 4; // On Android: product.brand
|
60
|
+
string device_model = 5; // On Android: product.device
|
61
|
+
string device_model_identifier = 6; // Android only, build.display.id
|
62
|
+
string device_model_boot = 7; // On Android: boot.hardware
|
63
|
+
string hardware_manufacturer = 8; // On Android: product.manufacturer
|
64
|
+
string hardware_model = 9; // On Android: product.model
|
65
|
+
string firmware_brand = 10; // On Android: product.name, on iOS: "iPhone OS"
|
66
|
+
string firmware_tags = 12; // Android only, build.tags
|
67
|
+
string firmware_type = 13; // On Android: build.type, on iOS instead: iOS version
|
68
|
+
string firmware_fingerprint = 14; // Android only, build.fingerprint
|
69
|
+
}
|
70
|
+
|
71
|
+
message ActivityStatus {
|
72
|
+
// all of these had 1 as their value
|
73
|
+
uint64 start_time_ms = 1;
|
74
|
+
bool unknown_status = 2;
|
75
|
+
bool walking = 3;
|
76
|
+
bool running = 4;
|
77
|
+
bool stationary = 5;
|
78
|
+
bool automotive = 6;
|
79
|
+
bool tilting = 7;
|
80
|
+
bool cycling = 8;
|
81
|
+
bytes status = 9;
|
82
|
+
}
|
83
|
+
|
84
|
+
uint64 timestamp_since_start = 2; // in ms
|
85
|
+
repeated LocationFix location_fix = 4;
|
86
|
+
AndroidGpsInfo gps_info = 5;
|
87
|
+
SensorInfo sensor_info = 7;
|
88
|
+
DeviceInfo device_info = 8;
|
89
|
+
ActivityStatus activity_status = 9;
|
90
|
+
uint32 location_hash1 = 10; // Location1 hashed based on the auth_token - xxHash32
|
91
|
+
uint32 location_hash2 = 20; // Location2 hashed based on the auth_token - xxHash32
|
92
|
+
bytes unk22 = 22; // possibly replay check. Generation unknown but pointed to by 0001B8614
|
93
|
+
uint64 timestamp = 23; // epoch timestamp in ms
|
94
|
+
repeated uint64 request_hash = 24; // hashes of each request message in a hashArray - xxhash64
|
95
|
+
|
96
|
+
// Addresses for the corresponding hash functions:
|
97
|
+
// xxHash32 00054D28
|
98
|
+
// xxhash64 000546C8 - Feeds into 00053D40
|
99
|
+
|
100
|
+
}
|
data/lib/poke-api/auth/google.rb
CHANGED
@@ -7,11 +7,11 @@ module Poke
|
|
7
7
|
include Logging
|
8
8
|
attr_reader :access_token, :provider
|
9
9
|
|
10
|
-
GOOGLE_LOGIN_ANDROID_ID = '9774d56d682e549c'
|
10
|
+
GOOGLE_LOGIN_ANDROID_ID = '9774d56d682e549c'.freeze
|
11
11
|
GOOGLE_LOGIN_SERVICE = 'audience:server:client_id:848232511240-7so421jotr' \
|
12
|
-
'2609rmqakceuu1luuq0ptb.apps.googleusercontent.com'
|
13
|
-
GOOGLE_LOGIN_APP = 'com.nianticlabs.pokemongo'
|
14
|
-
GOOGLE_LOGIN_CLIENT_SIG = '321187995bc7cdc2b5fc91b11a96e2baa8602c62'
|
12
|
+
'2609rmqakceuu1luuq0ptb.apps.googleusercontent.com'.freeze
|
13
|
+
GOOGLE_LOGIN_APP = 'com.nianticlabs.pokemongo'.freeze
|
14
|
+
GOOGLE_LOGIN_CLIENT_SIG = '321187995bc7cdc2b5fc91b11a96e2baa8602c62'.freeze
|
15
15
|
|
16
16
|
def initialize(username, password)
|
17
17
|
@username = username
|
@@ -40,7 +40,7 @@ module Poke
|
|
40
40
|
response = yield
|
41
41
|
|
42
42
|
if response['Error'] == 'NeedsBrowser'
|
43
|
-
raise Errors::GoogleTwoFactorAuthenticationFailure
|
43
|
+
raise Errors::GoogleTwoFactorAuthenticationFailure
|
44
44
|
else
|
45
45
|
unless response['Token'] || response['Auth']
|
46
46
|
raise Errors::GoogleAuthenticationFailure.new(method, response)
|
data/lib/poke-api/auth/ptc.rb
CHANGED
@@ -9,9 +9,9 @@ module Poke
|
|
9
9
|
attr_reader :access_token, :provider
|
10
10
|
|
11
11
|
PTC_LOGIN_URL = 'https://sso.pokemon.com/sso/login?service=https%3A%2F%2Fsso.pokemon.com' \
|
12
|
-
'%2Fsso%2Foauth2.0%2FcallbackAuthorize'
|
13
|
-
PTC_LOGIN_OAUTH = 'https://sso.pokemon.com/sso/oauth2.0/accessToken'
|
14
|
-
PTC_LOGIN_CLIENT_SECRET = 'w8ScCUXJQc6kXKw8FiOhd8Fixzht18Dq3PEVkUCP5ZPxtgyWsbTvWHFLm2wNY0JR'
|
12
|
+
'%2Fsso%2Foauth2.0%2FcallbackAuthorize'.freeze
|
13
|
+
PTC_LOGIN_OAUTH = 'https://sso.pokemon.com/sso/oauth2.0/accessToken'.freeze
|
14
|
+
PTC_LOGIN_CLIENT_SECRET = 'w8ScCUXJQc6kXKw8FiOhd8Fixzht18Dq3PEVkUCP5ZPxtgyWsbTvWHFLm2wNY0JR'.freeze
|
15
15
|
|
16
16
|
def initialize(username, password)
|
17
17
|
@username = username
|
@@ -0,0 +1,51 @@
|
|
1
|
+
module Poke
|
2
|
+
module API
|
3
|
+
module Auth
|
4
|
+
class Ticket
|
5
|
+
attr_reader :start, :ends, :expire
|
6
|
+
|
7
|
+
def initialize
|
8
|
+
@expire = nil
|
9
|
+
@start = nil
|
10
|
+
@ends = nil
|
11
|
+
end
|
12
|
+
|
13
|
+
def has_ticket?
|
14
|
+
return true if @start && @ends && @expire
|
15
|
+
false
|
16
|
+
end
|
17
|
+
|
18
|
+
def set_ticket(auth)
|
19
|
+
@expire = auth[:expire_timestamp_ms]
|
20
|
+
@start = auth[:start]
|
21
|
+
@ends = auth[:end]
|
22
|
+
end
|
23
|
+
|
24
|
+
def is_new_ticket?(new_ticket_time)
|
25
|
+
return true unless @expire && new_ticket_time > @expire
|
26
|
+
false
|
27
|
+
end
|
28
|
+
|
29
|
+
def get_ticket
|
30
|
+
return false unless check_ticket
|
31
|
+
|
32
|
+
true
|
33
|
+
end
|
34
|
+
|
35
|
+
private
|
36
|
+
|
37
|
+
def check_ticket
|
38
|
+
return false unless has_ticket?
|
39
|
+
|
40
|
+
now_ms = (Time.now.to_f * 1000).to_i
|
41
|
+
return true if now_ms < (@expire - 10000)
|
42
|
+
|
43
|
+
@expire = nil
|
44
|
+
@start = nil
|
45
|
+
@ends = nil
|
46
|
+
false
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
data/lib/poke-api/client.rb
CHANGED
@@ -2,7 +2,7 @@ module Poke
|
|
2
2
|
module API
|
3
3
|
class Client
|
4
4
|
include Logging
|
5
|
-
attr_accessor :lat, :lng, :alt, :endpoint
|
5
|
+
attr_accessor :lat, :lng, :alt, :endpoint, :ticket, :sig_path
|
6
6
|
|
7
7
|
def initialize
|
8
8
|
@auth = nil
|
@@ -10,7 +10,9 @@ module Poke
|
|
10
10
|
@reqs = []
|
11
11
|
@lat = 0
|
12
12
|
@lng = 0
|
13
|
-
@alt =
|
13
|
+
@alt = 8
|
14
|
+
@ticket = Auth::Ticket.new
|
15
|
+
@sig_path = nil
|
14
16
|
end
|
15
17
|
|
16
18
|
def login(username, password, provider)
|
@@ -25,12 +27,14 @@ module Poke
|
|
25
27
|
raise Errors::LoginFailure.new(provider, ex)
|
26
28
|
end
|
27
29
|
|
30
|
+
get_hatched_eggs
|
31
|
+
call
|
28
32
|
logger.info "[+] Login with #{provider} Successful"
|
29
|
-
fetch_endpoint
|
30
33
|
end
|
31
34
|
|
32
35
|
def call
|
33
36
|
raise Errors::LoginRequired unless @auth
|
37
|
+
raise Errors::NoRequests if @reqs.empty?
|
34
38
|
req = RequestBuilder.new(@auth, [@lat, @lng, @alt], @endpoint)
|
35
39
|
|
36
40
|
begin
|
@@ -45,6 +49,15 @@ module Poke
|
|
45
49
|
resp
|
46
50
|
end
|
47
51
|
|
52
|
+
def activate_signature(file_path)
|
53
|
+
if File.exist?(path)
|
54
|
+
logger.info "[+] File #{file_path} has been set for signature generation"
|
55
|
+
@sig_path = path
|
56
|
+
else
|
57
|
+
raise Errors::InvalidSignatureFilePath, file_path
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
48
61
|
def store_location(loc)
|
49
62
|
pos = Poke::API::Helpers.get_position(loc).first
|
50
63
|
logger.info "[+] Given location: #{pos.address}"
|
@@ -56,8 +69,7 @@ module Poke
|
|
56
69
|
|
57
70
|
def store_lat_lng(lat, lng)
|
58
71
|
logger.info "[+] Lat/Long: #{lat}, #{lng}"
|
59
|
-
@lat = lat
|
60
|
-
@lng = lng
|
72
|
+
@lat, @lng = lat, lng
|
61
73
|
end
|
62
74
|
|
63
75
|
def inspect
|
@@ -67,16 +79,6 @@ module Poke
|
|
67
79
|
|
68
80
|
private
|
69
81
|
|
70
|
-
def fetch_endpoint
|
71
|
-
get_player
|
72
|
-
get_hatched_eggs
|
73
|
-
get_inventory
|
74
|
-
check_awarded_badges
|
75
|
-
download_settings(hash: '4a2e9bc330dae60e7b74fc85b98868ab4700802e')
|
76
|
-
|
77
|
-
call
|
78
|
-
end
|
79
|
-
|
80
82
|
def method_missing(method, *args)
|
81
83
|
POGOProtos::Networking::Requests::RequestType.const_get(method.upcase)
|
82
84
|
@reqs << (args.empty? ? method.to_sym.upcase : { method.to_sym.upcase => args.first })
|
data/lib/poke-api/errors.rb
CHANGED
@@ -48,6 +48,24 @@ module Poke
|
|
48
48
|
super("Unable to fetch endpoint, please try to login again.")
|
49
49
|
end
|
50
50
|
end
|
51
|
+
|
52
|
+
class NoRequests < StandardError
|
53
|
+
def initialize
|
54
|
+
super("Can not call without any requests set")
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
class InvalidSignatureFilePath < StandardError
|
59
|
+
def initialize(file_path)
|
60
|
+
super("Could not find file #{file_path} for signature generation")
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
class InvalidLevel < StandardError
|
65
|
+
def initialize(level)
|
66
|
+
super("Level #{level} is invalid, must be between 0 and 30.")
|
67
|
+
end
|
68
|
+
end
|
51
69
|
end
|
52
70
|
end
|
53
71
|
end
|
@@ -0,0 +1,50 @@
|
|
1
|
+
module Poke
|
2
|
+
module API
|
3
|
+
module Geometry
|
4
|
+
module S2Base
|
5
|
+
LINEAR_PROJECTION = 0
|
6
|
+
TAN_PROJECTION = 1
|
7
|
+
QUADRATIC_PROJECTION = 2
|
8
|
+
|
9
|
+
MAX_LEVEL = 30
|
10
|
+
NUM_FACES = 6
|
11
|
+
POS_BITS = 2 * MAX_LEVEL + 1
|
12
|
+
MAX_SIZE = 1 << MAX_LEVEL
|
13
|
+
SWAP_MASK = 0x01
|
14
|
+
INVERT_MASK = 0x02
|
15
|
+
LOOKUP_BITS = 4
|
16
|
+
POS_TO_OR = [SWAP_MASK, 0, 0, INVERT_MASK | SWAP_MASK].freeze
|
17
|
+
POS_TO_IJ = [[0, 1, 3, 2],
|
18
|
+
[0, 2, 3, 1],
|
19
|
+
[3, 2, 0, 1],
|
20
|
+
[3, 1, 0, 2]].freeze
|
21
|
+
|
22
|
+
LOOKUP_POS = [nil] * (1 << (2 * LOOKUP_BITS + 2))
|
23
|
+
LOOKUP_IJ = [nil] * (1 << (2 * LOOKUP_BITS + 2))
|
24
|
+
|
25
|
+
def self.lookup_cells(level, i, j, orig_orientation, pos, orientation)
|
26
|
+
return lookup_bits(i, j, orig_orientation, pos, orientation) if level == LOOKUP_BITS
|
27
|
+
|
28
|
+
r = POS_TO_IJ[orientation]
|
29
|
+
4.times do |index|
|
30
|
+
lookup_cells(
|
31
|
+
level + 1, (i << 1) + (r[index] >> 1), (j << 1) + (r[index] & 1),
|
32
|
+
orig_orientation, (pos << 2) + index, orientation ^ POS_TO_OR[index]
|
33
|
+
)
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
def self.lookup_bits(i, j, orig_orientation, pos, orientation)
|
38
|
+
ij = (i << LOOKUP_BITS) + j
|
39
|
+
LOOKUP_POS[(ij << 2) + orig_orientation] = (pos << 2) + orientation
|
40
|
+
LOOKUP_IJ[(pos << 2) + orig_orientation] = (ij << 2) + orientation
|
41
|
+
end
|
42
|
+
|
43
|
+
lookup_cells(0, 0, 0, 0, 0, 0)
|
44
|
+
lookup_cells(0, 0, 0, SWAP_MASK, 0, SWAP_MASK)
|
45
|
+
lookup_cells(0, 0, 0, INVERT_MASK, 0, INVERT_MASK)
|
46
|
+
lookup_cells(0, 0, 0, SWAP_MASK | INVERT_MASK, 0, SWAP_MASK | INVERT_MASK)
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
@@ -0,0 +1,146 @@
|
|
1
|
+
module Poke
|
2
|
+
module API
|
3
|
+
module Geometry
|
4
|
+
class S2CellId
|
5
|
+
include S2Base
|
6
|
+
attr_reader :id
|
7
|
+
|
8
|
+
def initialize(id)
|
9
|
+
@id = id
|
10
|
+
end
|
11
|
+
|
12
|
+
def parent(level)
|
13
|
+
new_lsb = lsb_for_level(level)
|
14
|
+
s2 = S2CellId.new((@id & -new_lsb) | new_lsb)
|
15
|
+
|
16
|
+
raise Errors::InvalidLevel, level unless valid?(s2.id)
|
17
|
+
s2
|
18
|
+
end
|
19
|
+
|
20
|
+
def prev
|
21
|
+
S2CellId.new(@id - (lsb << 1))
|
22
|
+
end
|
23
|
+
|
24
|
+
def next
|
25
|
+
S2CellId.new(@id + (lsb << 1))
|
26
|
+
end
|
27
|
+
|
28
|
+
def level
|
29
|
+
return MAX_LEVEL if leaf?
|
30
|
+
|
31
|
+
x = (@id & 0xffffffff)
|
32
|
+
level = -1
|
33
|
+
|
34
|
+
if x != 0
|
35
|
+
level += 16
|
36
|
+
else
|
37
|
+
x = ((@id >> 32) & 0xffffffff)
|
38
|
+
end
|
39
|
+
|
40
|
+
x &= -x
|
41
|
+
|
42
|
+
level += 8 unless (x & 0x00005555).zero?
|
43
|
+
level += 4 unless (x & 0x00550055).zero?
|
44
|
+
level += 2 unless (x & 0x05050505).zero?
|
45
|
+
level += 1 unless (x & 0x11111111).zero?
|
46
|
+
level
|
47
|
+
end
|
48
|
+
|
49
|
+
def self.from_point(p)
|
50
|
+
face, u, v = xyz_to_face_uv(p)
|
51
|
+
i = st_to_ij(uv_to_st(u))
|
52
|
+
j = st_to_ij(uv_to_st(v))
|
53
|
+
|
54
|
+
S2CellId.new(from_face_ij(face, i, j))
|
55
|
+
end
|
56
|
+
|
57
|
+
def self.from_face_ij(face, i, j)
|
58
|
+
n = face << (POS_BITS - 1)
|
59
|
+
bits = face & SWAP_MASK
|
60
|
+
|
61
|
+
7.downto(0).each do |k|
|
62
|
+
mask = (1 << LOOKUP_BITS) - 1
|
63
|
+
bits += (((i >> (k * LOOKUP_BITS)) & mask) << (LOOKUP_BITS + 2))
|
64
|
+
bits += (((j >> (k * LOOKUP_BITS)) & mask) << 2)
|
65
|
+
bits = LOOKUP_POS[bits]
|
66
|
+
n |= (bits >> 2) << (k * 2 * LOOKUP_BITS)
|
67
|
+
bits &= (SWAP_MASK | INVERT_MASK)
|
68
|
+
end
|
69
|
+
|
70
|
+
@id = (n * 2 + 1)
|
71
|
+
end
|
72
|
+
|
73
|
+
def self.xyz_to_face_uv(p)
|
74
|
+
face = p.largest_abs_component
|
75
|
+
|
76
|
+
pface = case face
|
77
|
+
when 0 then p.x
|
78
|
+
when 1 then p.y
|
79
|
+
else p.z
|
80
|
+
end
|
81
|
+
|
82
|
+
face += 3 if pface < 0
|
83
|
+
|
84
|
+
u, v = valid_face_xyz_to_uv(face, p)
|
85
|
+
[face, u, v]
|
86
|
+
end
|
87
|
+
|
88
|
+
def self.uv_to_st(u)
|
89
|
+
return 0.5 * Math.sqrt(1 + 3 * u) if u >= 0
|
90
|
+
1 - 0.5 * Math.sqrt(1 - 3 * u)
|
91
|
+
end
|
92
|
+
|
93
|
+
def self.st_to_ij(s)
|
94
|
+
[0, [MAX_SIZE - 1, Integer((MAX_SIZE * s).floor)].min].max
|
95
|
+
end
|
96
|
+
|
97
|
+
def self.valid_face_xyz_to_uv(face, p)
|
98
|
+
raise unless p.dot_prod(face_uv_to_xyz(face, 0, 0)) > 0
|
99
|
+
|
100
|
+
case face
|
101
|
+
when 0 then [p.y / p.x, p.z / p.x]
|
102
|
+
when 1 then [-p.x / p.y, p.z / p.y]
|
103
|
+
when 2 then [-p.x / p.z, -p.y / p.z]
|
104
|
+
when 3 then [p.z / p.x, p.y / p.x]
|
105
|
+
when 4 then [p.z / p.y, -p.x / p.y]
|
106
|
+
else [-p.y / p.z, -p.x / p.z]
|
107
|
+
end
|
108
|
+
end
|
109
|
+
|
110
|
+
def self.face_uv_to_xyz(face, u, v)
|
111
|
+
case face
|
112
|
+
when 0 then S2Point.new(1, u, v)
|
113
|
+
when 1 then S2Point.new(-u, 1, v)
|
114
|
+
when 2 then S2Point.new(-u, -v, 1)
|
115
|
+
when 3 then S2Point.new(-1, -v, -u)
|
116
|
+
when 4 then S2Point.new(v, -1, -u)
|
117
|
+
else S2Point.new(v, u, -1)
|
118
|
+
end
|
119
|
+
end
|
120
|
+
|
121
|
+
private_class_method :face_uv_to_xyz, :valid_face_xyz_to_uv, :uv_to_st,
|
122
|
+
:st_to_ij, :xyz_to_face_uv, :from_face_ij
|
123
|
+
|
124
|
+
private
|
125
|
+
|
126
|
+
def leaf?
|
127
|
+
@id & 1 != 0
|
128
|
+
end
|
129
|
+
|
130
|
+
def valid?(s2_id)
|
131
|
+
face = s2_id >> POS_BITS
|
132
|
+
lsb = s2_id & -s2_id
|
133
|
+
(face < NUM_FACES) && (lsb & 0x1555555555555555) != 0
|
134
|
+
end
|
135
|
+
|
136
|
+
def lsb
|
137
|
+
@id & -@id
|
138
|
+
end
|
139
|
+
|
140
|
+
def lsb_for_level(level)
|
141
|
+
1 << (2 * (MAX_LEVEL - level))
|
142
|
+
end
|
143
|
+
end
|
144
|
+
end
|
145
|
+
end
|
146
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
module Poke
|
2
|
+
module API
|
3
|
+
module Geometry
|
4
|
+
class S2LatLon
|
5
|
+
def initialize(lat_degrees, lon_degrees)
|
6
|
+
@lat = lat_degrees * Math::PI / 180
|
7
|
+
@lon = lon_degrees * Math::PI / 180
|
8
|
+
end
|
9
|
+
|
10
|
+
def to_point
|
11
|
+
phi = @lat
|
12
|
+
theta = @lon
|
13
|
+
cosphi = Math.cos(phi)
|
14
|
+
S2Point.new(Math.cos(theta) * cosphi, Math.sin(theta) * cosphi, Math.sin(phi))
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
module Poke
|
2
|
+
module API
|
3
|
+
module Geometry
|
4
|
+
class S2Point
|
5
|
+
attr_reader :x, :y, :z
|
6
|
+
|
7
|
+
def initialize(x, y, z)
|
8
|
+
@x = x
|
9
|
+
@y = y
|
10
|
+
@z = z
|
11
|
+
end
|
12
|
+
|
13
|
+
def abs
|
14
|
+
[@x.abs, @y.abs, @z.abs]
|
15
|
+
end
|
16
|
+
|
17
|
+
def largest_abs_component
|
18
|
+
temp = abs
|
19
|
+
|
20
|
+
if temp[0] > temp[1]
|
21
|
+
temp[0] > temp[2] ? 0 : 2
|
22
|
+
else
|
23
|
+
temp[1] > temp[2] ? 1 : 2
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
def dot_prod(o)
|
28
|
+
@x * o.x + @y * o.y + @z * o.z
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
data/lib/poke-api/helpers.rb
CHANGED
@@ -1,4 +1,5 @@
|
|
1
1
|
require 'geocoder'
|
2
|
+
require 'ruby-xxhash'
|
2
3
|
|
3
4
|
module Poke
|
4
5
|
module API
|
@@ -11,6 +12,29 @@ module Poke
|
|
11
12
|
def camel_case_lower(sym)
|
12
13
|
sym.to_s.split('_').collect(&:capitalize).join
|
13
14
|
end
|
15
|
+
|
16
|
+
def generate_location_one(auth_ticket, pos)
|
17
|
+
first_hash = XXhash.xxh32(auth_ticket, 0x1B845238)
|
18
|
+
location_bytes = d2h(pos[0]) + d2h(pos[1]) + d2h(pos[2])
|
19
|
+
|
20
|
+
XXhash.xxh32(location_bytes, first_hash)
|
21
|
+
end
|
22
|
+
|
23
|
+
def generate_location_two(pos)
|
24
|
+
location_bytes = d2h(pos[0]) + d2h(pos[1]) + d2h(pos[2])
|
25
|
+
|
26
|
+
XXhash.xxh32(location_bytes, seed=0x1B845238)
|
27
|
+
end
|
28
|
+
|
29
|
+
def generate_request(auth_ticket, request)
|
30
|
+
first_hash = XXhash.xxh64(auth_ticket, 0x1B845238)
|
31
|
+
|
32
|
+
XXhash.xxh64(request, first_hash)
|
33
|
+
end
|
34
|
+
|
35
|
+
def d2h(input)
|
36
|
+
[input].pack('d').unpack('Q').first.to_s(16).split.pack('H*')
|
37
|
+
end
|
14
38
|
end
|
15
39
|
end
|
16
40
|
end
|
@@ -1,6 +1,10 @@
|
|
1
|
+
require 'ffi'
|
2
|
+
require 'securerandom'
|
3
|
+
|
1
4
|
module Poke
|
2
5
|
module API
|
3
6
|
class RequestBuilder
|
7
|
+
extend FFI::Library
|
4
8
|
include Logging
|
5
9
|
|
6
10
|
def initialize(auth, pos, endpoint)
|
@@ -9,11 +13,14 @@ module Poke
|
|
9
13
|
@endpoint = endpoint
|
10
14
|
@position = pos
|
11
15
|
@client = HTTPClient.new(agent_name: 'PokeAPI/0.0.1')
|
16
|
+
@start_time = (Time.now.to_f * 1000).to_i
|
17
|
+
@ffi_enabled = false
|
12
18
|
end
|
13
19
|
|
14
20
|
def request(reqs, client)
|
15
21
|
logger.debug '[+] Creating new request'
|
16
|
-
request_proto = build_main_request(reqs)
|
22
|
+
request_proto = build_main_request(reqs, client)
|
23
|
+
logger.debug "[+] Generated RPC protobuf encoded request \r\n#{request_proto.inspect}"
|
17
24
|
|
18
25
|
logger.info '[+] Executing RPC request'
|
19
26
|
resp = execute_rpc_request(request_proto)
|
@@ -26,7 +33,7 @@ module Poke
|
|
26
33
|
|
27
34
|
private
|
28
35
|
|
29
|
-
def build_main_request(sub_reqs)
|
36
|
+
def build_main_request(sub_reqs, client)
|
30
37
|
request_envelope = POGOProtos::Networking::Envelopes::RequestEnvelope
|
31
38
|
req = request_envelope.new(
|
32
39
|
status_code: 2,
|
@@ -35,15 +42,85 @@ module Poke
|
|
35
42
|
)
|
36
43
|
req.latitude, req.longitude, req.altitude = @position
|
37
44
|
|
38
|
-
token = request_envelope::AuthInfo::JWT.new(contents: @access_token, unknown2: 59)
|
39
|
-
req.auth_info = request_envelope::AuthInfo.new(provider: @provider, token: token)
|
40
|
-
|
41
45
|
build_sub_request(req, sub_reqs)
|
46
|
+
set_authentication(req, client, request_envelope)
|
42
47
|
|
43
48
|
logger.debug "[+] Generated RPC protobuf request \r\n#{req.inspect}"
|
44
49
|
req.to_proto
|
45
50
|
end
|
46
51
|
|
52
|
+
def set_authentication(req, client, request_envelope)
|
53
|
+
if client.ticket.get_ticket
|
54
|
+
logger.info '[+] Using Auth ticket'
|
55
|
+
|
56
|
+
req.auth_ticket = POGOProtos::Networking::Envelopes::AuthTicket.new(
|
57
|
+
start: client.ticket.start, end: client.ticket.ends,
|
58
|
+
expire_timestamp_ms: client.ticket.expire
|
59
|
+
)
|
60
|
+
|
61
|
+
load_library(client.sig_path) if client.sig_path && !@ffi_enabled
|
62
|
+
set_signature(req, request_envelope) if @ffi_enabled
|
63
|
+
else
|
64
|
+
logger.info '[+] Using Provider token'
|
65
|
+
token = request_envelope::AuthInfo::JWT.new(contents: @access_token, unknown2: 59)
|
66
|
+
req.auth_info = request_envelope::AuthInfo.new(provider: @provider, token: token)
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
def set_signature(req, _request_envelope)
|
71
|
+
signature = Signature.new(
|
72
|
+
location_hash1: Helpers.generate_location_one(req.auth_ticket.to_proto, @position),
|
73
|
+
location_hash2: Helpers.generate_location_two(@position),
|
74
|
+
unk22: SecureRandom.random_bytes(32),
|
75
|
+
timestamp: (Time.now.to_f * 1000).to_i,
|
76
|
+
timestamp_since_start: (Time.now.to_f * 1000).to_i - @start_time
|
77
|
+
)
|
78
|
+
|
79
|
+
req.requests.each do |r|
|
80
|
+
signature.request_hash << Helpers.generate_request(req.auth_ticket.to_proto, r.to_proto)
|
81
|
+
end
|
82
|
+
|
83
|
+
unknown6 = POGOProtos::Networking::Envelopes::Unknown6
|
84
|
+
|
85
|
+
req.unknown6 = unknown6.new(
|
86
|
+
unknown1: 6,
|
87
|
+
unknown2: unknown6::Unknown2.new(unknown1: generate_signature(signature.to_proto))
|
88
|
+
)
|
89
|
+
|
90
|
+
logger.info '[+] Setting Signature'
|
91
|
+
end
|
92
|
+
|
93
|
+
def generate_signature(signature)
|
94
|
+
attempts = 5
|
95
|
+
|
96
|
+
begin
|
97
|
+
logger.info '[+] Generating Signature'
|
98
|
+
output_size = FFI::MemoryPointer.new(:size_t)
|
99
|
+
|
100
|
+
iv = SecureRandom.random_bytes(32)
|
101
|
+
RequestBuilder.encrypt(signature, signature.length, iv, 32, nil, output_size)
|
102
|
+
|
103
|
+
output = FFI::MemoryPointer.new(output_size.read_int)
|
104
|
+
RequestBuilder.encrypt(signature, signature.length, iv, 32, output, output_size)
|
105
|
+
rescue StandardError => ex
|
106
|
+
raise ex if (attempts -= 1) == 0
|
107
|
+
retry
|
108
|
+
end
|
109
|
+
|
110
|
+
output.read_string
|
111
|
+
end
|
112
|
+
|
113
|
+
def load_library(path)
|
114
|
+
RequestBuilder.ffi_lib(path)
|
115
|
+
RequestBuilder.attach_function(
|
116
|
+
:encrypt,
|
117
|
+
[:string, :size_t, :string, :size_t, :pointer, :pointer],
|
118
|
+
:int
|
119
|
+
)
|
120
|
+
|
121
|
+
@ffi_enabled = true
|
122
|
+
end
|
123
|
+
|
47
124
|
def build_sub_request(req, sub_reqs)
|
48
125
|
sub_reqs.each do |sub_req|
|
49
126
|
if sub_req.is_a?(Symbol)
|
data/lib/poke-api/response.rb
CHANGED
@@ -16,6 +16,9 @@ module Poke
|
|
16
16
|
@response = POGOProtos::Networking::Envelopes::ResponseEnvelope.decode(@response)
|
17
17
|
logger.debug "[+] Decoded RPC response \r\n#{@response.inspect}"
|
18
18
|
|
19
|
+
store_ticket(client)
|
20
|
+
store_endpoint(client)
|
21
|
+
|
19
22
|
logger.info '[+] Decoding Sub RPC responses'
|
20
23
|
decoded_resp = parse_rpc_fields(decode_sub_responses)
|
21
24
|
|
@@ -24,7 +27,6 @@ module Poke
|
|
24
27
|
parse_rpc_fields(decoded_resp)
|
25
28
|
end
|
26
29
|
|
27
|
-
store_endpoint(client)
|
28
30
|
decoded_resp.merge!(status_code: @response.status_code,
|
29
31
|
api_url: @response.api_url, error: @response.error)
|
30
32
|
|
@@ -34,6 +36,17 @@ module Poke
|
|
34
36
|
|
35
37
|
private
|
36
38
|
|
39
|
+
def store_ticket(client)
|
40
|
+
return unless @response.auth_ticket
|
41
|
+
|
42
|
+
auth = @response.auth_ticket.to_hash
|
43
|
+
|
44
|
+
if client.ticket.is_new_ticket?(auth[:expire_timestamp_ms])
|
45
|
+
logger.debug "[+] Storing Auth Ticket\r\n#{auth}"
|
46
|
+
client.ticket.set_ticket(auth)
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
37
50
|
def store_endpoint(client)
|
38
51
|
logger.debug "[+] Current Endpoint #{client.endpoint}"
|
39
52
|
|
@@ -43,7 +56,7 @@ module Poke
|
|
43
56
|
|
44
57
|
return if @response.api_url.empty?
|
45
58
|
|
46
|
-
logger.debug "[+] Setting Endpoint to
|
59
|
+
logger.debug "[+] Setting Endpoint to https://#{@response.api_url}/rpc"
|
47
60
|
client.endpoint = "https://#{@response.api_url}/rpc"
|
48
61
|
end
|
49
62
|
|
data/lib/poke-api/testing.rb
CHANGED
@@ -1,24 +1,37 @@
|
|
1
1
|
# Load Poke-API related classes
|
2
2
|
require 'pp'
|
3
|
-
require '
|
4
|
-
require_relative 'logging'
|
5
|
-
require_relative 'client'
|
6
|
-
require_relative 'helpers'
|
7
|
-
require_relative 'request_builder'
|
8
|
-
require_relative 'response'
|
9
|
-
require_relative 'errors'
|
10
|
-
require_relative 'version'
|
11
|
-
require_relative 'auth/ptc'
|
12
|
-
require_relative 'auth/google'
|
3
|
+
require 'poke-api'
|
13
4
|
|
14
|
-
|
15
|
-
|
16
|
-
|
5
|
+
def get_cells(lat, lng, radius = 10)
|
6
|
+
s2_point = Poke::API::Geometry::S2LatLon.new(lat, lng).to_point
|
7
|
+
s2_cell = Poke::API::Geometry::S2CellId.from_point(s2_point).parent(15)
|
17
8
|
|
9
|
+
next_cell = s2_cell.next
|
10
|
+
prev_cell = s2_cell.prev
|
11
|
+
|
12
|
+
radius.times.reduce([s2_cell.id]) do |acc, el|
|
13
|
+
acc += [next_cell.id, prev_cell.id]
|
14
|
+
next_cell = next_cell.next
|
15
|
+
prev_cell = prev_cell.prev
|
16
|
+
acc
|
17
|
+
end.sort
|
18
|
+
end
|
19
|
+
|
20
|
+
#Poke::API::Logging.log_level = :DEBUG
|
18
21
|
client = Poke::API::Client.new
|
19
|
-
|
20
|
-
|
22
|
+
client.activate_signature('encrypt64bit.dll')
|
23
|
+
|
24
|
+
client.store_location('Glasgow')
|
21
25
|
client.login('srn720', 'illi0wnz', 'ptc')
|
22
|
-
|
23
|
-
#
|
24
|
-
|
26
|
+
|
27
|
+
#Get cells
|
28
|
+
cell_ids = get_cells(client.lat, client.lng)
|
29
|
+
|
30
|
+
# Construct map objects call
|
31
|
+
client.get_map_objects(
|
32
|
+
latitude: client.lat,
|
33
|
+
longitude: client.lng,
|
34
|
+
since_timestamp_ms: [0] * cell_ids.length,
|
35
|
+
cell_id: cell_ids
|
36
|
+
)
|
37
|
+
p client.call
|
data/lib/poke-api/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: poke-go-api
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0
|
4
|
+
version: 0.1.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Nabeel Amjad
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2016-08-
|
11
|
+
date: 2016-08-07 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: httpclient
|
@@ -66,6 +66,34 @@ dependencies:
|
|
66
66
|
- - '='
|
67
67
|
- !ruby/object:Gem::Version
|
68
68
|
version: 0.1.2
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: ruby-xxHash
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
72
|
+
requirements:
|
73
|
+
- - '='
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
version: 0.4.0.1
|
76
|
+
type: :runtime
|
77
|
+
prerelease: false
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
79
|
+
requirements:
|
80
|
+
- - '='
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: 0.4.0.1
|
83
|
+
- !ruby/object:Gem::Dependency
|
84
|
+
name: ffi
|
85
|
+
requirement: !ruby/object:Gem::Requirement
|
86
|
+
requirements:
|
87
|
+
- - '='
|
88
|
+
- !ruby/object:Gem::Version
|
89
|
+
version: 1.9.14
|
90
|
+
type: :runtime
|
91
|
+
prerelease: false
|
92
|
+
version_requirements: !ruby/object:Gem::Requirement
|
93
|
+
requirements:
|
94
|
+
- - '='
|
95
|
+
- !ruby/object:Gem::Version
|
96
|
+
version: 1.9.14
|
69
97
|
description: An API wrapper for Pokemon GO
|
70
98
|
email:
|
71
99
|
executables: []
|
@@ -294,6 +322,7 @@ files:
|
|
294
322
|
- lib/poke-api/POGOProtos/Settings/Master/PokemonSettings.rb
|
295
323
|
- lib/poke-api/POGOProtos/Settings/Master/PokemonUpgradeSettings.rb
|
296
324
|
- lib/poke-api/POGOProtos/Settings/Master/TypeEffectiveSettings.rb
|
325
|
+
- lib/poke-api/POGOProtos/Signature.rb
|
297
326
|
- lib/poke-api/POGOProtosSource/Data/AssetDigestEntry.proto
|
298
327
|
- lib/poke-api/POGOProtosSource/Data/Battle/BattleAction.proto
|
299
328
|
- lib/poke-api/POGOProtosSource/Data/Battle/BattleActionType.proto
|
@@ -518,10 +547,16 @@ files:
|
|
518
547
|
- lib/poke-api/POGOProtosSource/Settings/Master/PokemonSettings.proto
|
519
548
|
- lib/poke-api/POGOProtosSource/Settings/Master/PokemonUpgradeSettings.proto
|
520
549
|
- lib/poke-api/POGOProtosSource/Settings/Master/TypeEffectiveSettings.proto
|
550
|
+
- lib/poke-api/POGOProtosSource/Signature.proto
|
521
551
|
- lib/poke-api/auth/google.rb
|
522
552
|
- lib/poke-api/auth/ptc.rb
|
553
|
+
- lib/poke-api/auth/ticket.rb
|
523
554
|
- lib/poke-api/client.rb
|
524
555
|
- lib/poke-api/errors.rb
|
556
|
+
- lib/poke-api/geometry/s2_base.rb
|
557
|
+
- lib/poke-api/geometry/s2_cell_id.rb
|
558
|
+
- lib/poke-api/geometry/s2_lat_lon.rb
|
559
|
+
- lib/poke-api/geometry/s2_point.rb
|
525
560
|
- lib/poke-api/helpers.rb
|
526
561
|
- lib/poke-api/logging.rb
|
527
562
|
- lib/poke-api/request_builder.rb
|