poke-go-api 0.0.8 → 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|