pokeplot 0.2.0beta
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 +7 -0
- data/.rspec +4 -0
- data/LICENSE.txt +621 -0
- data/README.md +99 -0
- data/Rakefile +9 -0
- data/bin/pokeplot +223 -0
- data/lib/pokeplot/api.rb +109 -0
- data/lib/pokeplot/database.rb +22 -0
- data/lib/pokeplot/helpers/array.rb +5 -0
- data/lib/pokeplot/helpers/cell_ids.rb +14 -0
- data/lib/pokeplot/helpers/math.rb +20 -0
- data/lib/pokeplot/helpers/time.rb +15 -0
- data/lib/pokeplot/miner.rb +241 -0
- data/lib/pokeplot/pushbullet.rb +41 -0
- data/lib/pokeplot/socket.rb +65 -0
- data/lib/pokeplot/version.rb +3 -0
- data/lib/pokeplot/web/canvasjs.min.js +555 -0
- data/lib/pokeplot/web/index.html +158 -0
- data/lib/pokeplot/web.rb +26 -0
- data/lib/pokeplot.rb +7 -0
- data/spec/api_spec.rb +148 -0
- data/spec/database_spec.rb +33 -0
- data/spec/miner_spec.rb +110 -0
- data/spec/pushbullet_spec.rb +31 -0
- data/spec/socket_spec.rb +45 -0
- data/spec/spec_helper.rb +115 -0
- data/spec/web_spec.rb +18 -0
- metadata +240 -0
data/README.md
ADDED
@@ -0,0 +1,99 @@
|
|
1
|
+
# Pokeplot
|
2
|
+
|
3
|
+
[](https://badge.fury.io/rb/pokeplot) [](https://codeclimate.com/github/xssc/pokeplot/coverage) [](https://gemnasium.com/github.com/xssc/pokeplot) [](https://rubygems.org/gems/pokeplot)
|
4
|
+
|
5
|
+
Pokeplot is a gem to collect Pokemon Go spawning data and visualize it. It is currently a pre-release, expect frequent updates.
|
6
|
+
|
7
|
+

|
8
|
+
|
9
|
+
### Contents
|
10
|
+
|
11
|
+
[**Getting Started**](https://github.com/xssc/pokeplot#getting-started)
|
12
|
+
|
13
|
+
[**Usage**](https://github.com/xssc/pokeplot#usage)
|
14
|
+
|
15
|
+
[**Features**](https://github.com/xssc/pokeplot#features)
|
16
|
+
|
17
|
+
[**Notifications**](https://github.com/xssc/pokeplot#notifications)
|
18
|
+
|
19
|
+
[**Updating**](https://github.com/xssc/pokeplot#updating)
|
20
|
+
|
21
|
+
[**Future and TODO**](https://github.com/xssc/pokeplot#future--todo)
|
22
|
+
|
23
|
+
[**Contanct, Requests, and Issues**](https://github.com/xssc/pokeplot#contact-requests-and-issues)
|
24
|
+
|
25
|
+
[**Contributing**](https://github.com/xssc/pokeplot#contributing)
|
26
|
+
|
27
|
+
## Getting Started
|
28
|
+
|
29
|
+
Installing pokeplot is insanley easy. All you need is ruby 2.3.1. Don't have it? [Follow our easy Ruby install guide!](https://github.com/xssc/pokeplot/wiki/Install-Ruby-2.3.1)
|
30
|
+
|
31
|
+
We use MongoDB to quickly store large numbers of encounters. Download and install it from [HERE](https://www.mongodb.com/download-center?jmp=nav#community). Don't worry, it's easy!
|
32
|
+
|
33
|
+
Once done the only installation command is:
|
34
|
+
|
35
|
+
$ gem install pokeplot --pre
|
36
|
+
|
37
|
+
## Usage
|
38
|
+
|
39
|
+
Open a terminal/cmd and make a folder for Pokeplot configuration to be stored
|
40
|
+
|
41
|
+
$ mkdir pokeplot
|
42
|
+
$ cd pokeplot
|
43
|
+
|
44
|
+
Then to generate the default config.json file, run
|
45
|
+
|
46
|
+
$ pokeplot config
|
47
|
+
|
48
|
+
Then go to the pokeplot folder you just made and open config.json in your favorite text editor. There are `_info` lines to help you along the way.
|
49
|
+
|
50
|
+
Then simply run
|
51
|
+
|
52
|
+
$ pokeplot
|
53
|
+
|
54
|
+
Real time graphs will be available at `http://localhost:5001` while pokeplot is running.
|
55
|
+
|
56
|
+
## Features
|
57
|
+
* Single or Multithread
|
58
|
+
* Divides coordinates in a way that doesn't cause larger teleportations due to more accounts
|
59
|
+
* Multiple accounts (Combo lists also supported)
|
60
|
+
* Configurable config.json
|
61
|
+
* Real time website with graphs
|
62
|
+
* Ability to handle real time data yourslef with Ruby (Examples soon)
|
63
|
+
* Notifications
|
64
|
+
* A developer who has tons of freetime to work on this project!
|
65
|
+
|
66
|
+
|
67
|
+
## Notifications
|
68
|
+
|
69
|
+
Currently Pokeplt only supports Pushbullet. [Follow the easy setup guide here](https://github.com/xssc/pokeplot/wiki/Pushbullet)
|
70
|
+
|
71
|
+
|
72
|
+
## Updating
|
73
|
+
|
74
|
+
When a update is available for pokeplot, only one command is needed to install it
|
75
|
+
|
76
|
+
$ gem update pokeplot
|
77
|
+
|
78
|
+
Pokeplot will be updated frequently, I have lots of spare time.
|
79
|
+
|
80
|
+
## Future & TODO
|
81
|
+
The following is planned (but not guarenteed)
|
82
|
+
|
83
|
+
* Maps
|
84
|
+
* More graphs
|
85
|
+
* Get Cell Ids in Ruby
|
86
|
+
* Add more notification services
|
87
|
+
* Fix any issues that arrise
|
88
|
+
* Lots more
|
89
|
+
|
90
|
+
## Contact, Requests, and Issues
|
91
|
+
If you have any problems using this, I will do whatever I can to help you get up and running. Your options are
|
92
|
+
|
93
|
+
* Create an issue [HERE](https://github.com/xssc/pokeplot/issues)
|
94
|
+
* Email me @ xssc820@gmail.com
|
95
|
+
* Or PM me on reddit at [/u/xssc](https://www.reddit.com/message/compose?to=xssc)
|
96
|
+
|
97
|
+
## Contributing
|
98
|
+
|
99
|
+
Bug reports and pull requests are welcome on GitHub at https://github.com/xssc/pokeplot
|
data/Rakefile
ADDED
data/bin/pokeplot
ADDED
@@ -0,0 +1,223 @@
|
|
1
|
+
#!usr/bin/env ruby
|
2
|
+
require 'pokeplot'
|
3
|
+
require 'json'
|
4
|
+
|
5
|
+
|
6
|
+
default_config = %{ {
|
7
|
+
"_info": "Enter your accounts here, as many as you want",
|
8
|
+
"accounts": [
|
9
|
+
{
|
10
|
+
"username": "account1",
|
11
|
+
"password": "password1",
|
12
|
+
"provider": "ptc"
|
13
|
+
},
|
14
|
+
{
|
15
|
+
"username": "account2@gmail.com",
|
16
|
+
"password": "password2",
|
17
|
+
"provider": "google"
|
18
|
+
}
|
19
|
+
],
|
20
|
+
|
21
|
+
"_info": "Enter the origin scan coordinates below [lat, lng]",
|
22
|
+
"location": [
|
23
|
+
40.7829,
|
24
|
+
-73.9654
|
25
|
+
],
|
26
|
+
|
27
|
+
"_info": "settings for API",
|
28
|
+
"api": {
|
29
|
+
"encryption_path": "/path/to/encryption/file",
|
30
|
+
"log": true
|
31
|
+
},
|
32
|
+
|
33
|
+
"_info": "settings for mongoDB (default host is already set)",
|
34
|
+
"mongo": {
|
35
|
+
"host": "127.0.0.1:27017"
|
36
|
+
},
|
37
|
+
|
38
|
+
"_info": "settings for the data miner",
|
39
|
+
"miner": {
|
40
|
+
"enabled": true,
|
41
|
+
"threaded": true,
|
42
|
+
"range": 40,
|
43
|
+
"interval": 900,
|
44
|
+
"pokemon": true,
|
45
|
+
"forts": true,
|
46
|
+
"log": true
|
47
|
+
},
|
48
|
+
|
49
|
+
"_info": "Pushbullet settings - see the wiki for easy set-up guide",
|
50
|
+
"pushbullet": {
|
51
|
+
"enabled": false,
|
52
|
+
"api_key": "apiKey",
|
53
|
+
"pokemon": [
|
54
|
+
"SNORLAX",
|
55
|
+
"DRATINI",
|
56
|
+
"DRAGONITE",
|
57
|
+
"MEWTWO"
|
58
|
+
]
|
59
|
+
},
|
60
|
+
|
61
|
+
"_info": "settings for socket for real time webpage updates RECOMENDED YOU DONT CHANGE THIS",
|
62
|
+
"socket": {
|
63
|
+
"enabled": true,
|
64
|
+
"host": "0.0.0.0",
|
65
|
+
"port": "9090",
|
66
|
+
"log": true
|
67
|
+
},
|
68
|
+
|
69
|
+
"_info": "Web server settings",
|
70
|
+
"webserver": {
|
71
|
+
"enabled": true,
|
72
|
+
"host": "0.0.0.0",
|
73
|
+
"port": 5001
|
74
|
+
},
|
75
|
+
|
76
|
+
"_info": "optional ptc account combo list",
|
77
|
+
"combos": [
|
78
|
+
"SToCQSyJuVXj:BGyoYefXjQQZ",
|
79
|
+
"hdOMuITMabLF:kscSpsGGzBxu",
|
80
|
+
"vMpPCulIYkcT:GBbUdGlstxeW",
|
81
|
+
"FZmcNpLdbxha:CurAriesqPFZ",
|
82
|
+
"wVkKQBGmYJXK:XmZoKXLfvNvU",
|
83
|
+
"vgsqGbfVeawM:QhzXnffDjgAt",
|
84
|
+
"dJdUmaNsvuMC:HsHytSfNyvnS",
|
85
|
+
"UPmlEpbNFGYk:tZJMwBeDRAMs",
|
86
|
+
"xcxcPjUKRPal:iFCBrsSjHFRF",
|
87
|
+
"dldjzYhsQbLz:oaQaggnrVIjK",
|
88
|
+
"gZEekjgrBQCK:vUWhIaEHAclX",
|
89
|
+
"wLOToXHcLJBZ:RNIoYdwvDFTH",
|
90
|
+
"tBOjNYBHIJIo:CTqmQaCWaRRT",
|
91
|
+
"pbAGNZsvGnMC:TVWLsmdRRJjG",
|
92
|
+
"cneIEKBIGevh:CnFKUkBDJECj",
|
93
|
+
"WworruNrwycr:gYzkXQnHyPxy",
|
94
|
+
"YtbiVCtnYCIQ:jiBNmgTBWTBw",
|
95
|
+
"rwmUhrHCbWGW:gKdPdvUzbXEB",
|
96
|
+
"kdgqEBIsKMhO:rvESvQkNQtGs",
|
97
|
+
"PssVOTYjurWz:gSMXWHoFkvPq",
|
98
|
+
"kHlinSczQEim:rqFePFPryvUe",
|
99
|
+
"AIAVmolzTbQJ:mxvWoSJNrNRC",
|
100
|
+
"iBESkcpbrIdY:KQnQTqClDykQ",
|
101
|
+
"AXwyjTgvYIfn:vINTlbsjdtCx",
|
102
|
+
"yuHRAgIfVWTZ:VTTnyPBZSojM",
|
103
|
+
"nFrgKgQLzrRe:ooplsOvhQNFQ",
|
104
|
+
"iRFsCpCMUlte:koKrBewFLMxo",
|
105
|
+
"pOqWlFdPGYEl:gkhKikkcwpmh",
|
106
|
+
"NByvaUQkNchO:nPmVzbMPtXWY",
|
107
|
+
"RftfDbyWXmSe:wYLELjKLjkIJ",
|
108
|
+
"gLJMMYXGJibG:AnHNRvNmSkuA",
|
109
|
+
"zBCKrZlciUiV:SZJdvkMSkgRT",
|
110
|
+
"TyqcusJxatgm:EqKtdTEybJpz",
|
111
|
+
"fDDaoMvaOMOs:bmcEVoNcKyJC",
|
112
|
+
"dEgUOTTPOQpQ:elCgIExqkWOp",
|
113
|
+
"ZjZZftPIHKVj:gHzweZzDICAA",
|
114
|
+
"XuinqBhqynbE:PDfXbdSBkoJV",
|
115
|
+
"eYPkNTSSRngF:EShbqUEutCqQ",
|
116
|
+
"PvmFqqXdRnwG:IhDzJDSknest",
|
117
|
+
"CvbgGcNdKumE:gzmlCjYgybpZ",
|
118
|
+
"FiHNyzzpKmOs:tbIXrdCecmlB",
|
119
|
+
"dUsdcfxGJAlf:NTWKivTOeABd",
|
120
|
+
"BvVqSybVGuoD:xhCgeXTtsFST",
|
121
|
+
"GamYBkRElCCY:CFRHRROHlsrY",
|
122
|
+
"zeGrfdhyrtfY:AwSFrczizYsZ",
|
123
|
+
"bivTEnLISOyR:DQLoKikEWJON",
|
124
|
+
"FWMGCfVJcJjV:IJFxXGDqhDRK",
|
125
|
+
"yqDulLursWuk:CKieNAUmgcZM",
|
126
|
+
"TeXIZDsXBEJJ:gQSevIHOVxrd",
|
127
|
+
"iYgqvHkNlGjJ:WbSYJNhlJxbZ"
|
128
|
+
]
|
129
|
+
|
130
|
+
|
131
|
+
}
|
132
|
+
}
|
133
|
+
|
134
|
+
|
135
|
+
if ARGV[0] == 'config'
|
136
|
+
File.open('config.json', 'w+') do |f|
|
137
|
+
f.puts default_config
|
138
|
+
puts "[+] config.json made, you can now edit it"
|
139
|
+
exit
|
140
|
+
end
|
141
|
+
end
|
142
|
+
|
143
|
+
|
144
|
+
|
145
|
+
|
146
|
+
|
147
|
+
begin
|
148
|
+
$conf = JSON.parse(File.read("config.json"))
|
149
|
+
rescue Exception
|
150
|
+
puts "[-] Something went wrong loading your config.json file"
|
151
|
+
exit
|
152
|
+
end
|
153
|
+
|
154
|
+
#Make ctrl+c exit whole script
|
155
|
+
trap "INT" do
|
156
|
+
Thread.list.each do |thread|
|
157
|
+
thread.exit unless thread == Thread.current
|
158
|
+
end
|
159
|
+
exit
|
160
|
+
end
|
161
|
+
|
162
|
+
#get rid of annoying messages
|
163
|
+
ouput_manager = StringIO.new
|
164
|
+
$stdout = ouput_manager
|
165
|
+
$stderr = ouput_manager
|
166
|
+
|
167
|
+
module Kernel
|
168
|
+
def puts(msg)
|
169
|
+
#if msg[0] == "["
|
170
|
+
::STDOUT.printf(msg + "\n")
|
171
|
+
#end
|
172
|
+
end
|
173
|
+
end
|
174
|
+
|
175
|
+
|
176
|
+
module Pokeplot
|
177
|
+
include Database
|
178
|
+
|
179
|
+
Database.mongo_host = $conf["mongo"]["host"]
|
180
|
+
|
181
|
+
#Socket and notifications must come before miner to capture its database requests
|
182
|
+
if $conf["socket"]["enabled"]
|
183
|
+
s = Socket.new($conf["socket"]["host"], $conf["socket"]["port"], $conf["socket"]["log"])
|
184
|
+
Database.mongo_monitor(s)
|
185
|
+
end
|
186
|
+
|
187
|
+
if $conf["pushbullet"]["enabled"]
|
188
|
+
pb = Pushbullet.new($conf["pushbullet"]["api_key"], $conf["pushbullet"]["pokemon"])
|
189
|
+
Database.mongo_monitor(pb)
|
190
|
+
end
|
191
|
+
|
192
|
+
if $conf['combos'].is_a?(Array) && $conf['combos'].count > 0
|
193
|
+
$conf['combos'].each do |c|
|
194
|
+
c = c.split(':')
|
195
|
+
$conf['accounts'] << {'username' => c[0], 'password' => c[1], 'provider' => 'ptc'}
|
196
|
+
end
|
197
|
+
end
|
198
|
+
|
199
|
+
|
200
|
+
if $conf["miner"]["enabled"]
|
201
|
+
miner = Miner.new($conf['accounts'], $conf['location'][0], $conf['location'][1], $conf['miner']['range'], $conf['miner']['interval'], $conf['miner']['pokemon'], $conf['miner']['forts'], $conf['miner']['threaded'], $conf['api']['encryption_path'], $conf['miner']['log'], $conf['api']['log'])
|
202
|
+
miner.start
|
203
|
+
end
|
204
|
+
|
205
|
+
if $conf["webserver"]["enabled"]
|
206
|
+
web = Thread.new do
|
207
|
+
Web.config($conf["webserver"]["host"], $conf["webserver"]["port"])
|
208
|
+
Web.run!
|
209
|
+
end
|
210
|
+
end
|
211
|
+
|
212
|
+
# Join thread so it doesnt exit script
|
213
|
+
if miner.is_a?(Miner) && miner.miner.is_a?(Thread)
|
214
|
+
puts "[+] Joining thread"
|
215
|
+
miner.miner.join
|
216
|
+
end
|
217
|
+
|
218
|
+
if web && web.is_a?(Thread)
|
219
|
+
puts "[+] Joining thread"
|
220
|
+
web.join
|
221
|
+
end
|
222
|
+
|
223
|
+
end
|
data/lib/pokeplot/api.rb
ADDED
@@ -0,0 +1,109 @@
|
|
1
|
+
require 'poke-api'
|
2
|
+
require 'pokeplot/helpers/cell_ids'
|
3
|
+
|
4
|
+
module Pokeplot
|
5
|
+
class API
|
6
|
+
|
7
|
+
def initialize(lat, lng, encryption, logging = true)
|
8
|
+
Poke::API::Logging.log_level = :FATAL
|
9
|
+
@api = Poke::API::Client.new
|
10
|
+
set_location(lat, lng)
|
11
|
+
@encryption = encryption
|
12
|
+
@logging = logging
|
13
|
+
end
|
14
|
+
|
15
|
+
def login(username, password, provider)
|
16
|
+
puts "[+] Logging in #{username} with #{provider}" if @logging
|
17
|
+
loop do
|
18
|
+
begin
|
19
|
+
@username = username
|
20
|
+
@password = password
|
21
|
+
@provider = provider
|
22
|
+
@api.login(username, password, provider)
|
23
|
+
@api.activate_signature(@encryption)
|
24
|
+
basic_request
|
25
|
+
break
|
26
|
+
rescue Poke::API::Errors::UnknownProtoFault
|
27
|
+
|
28
|
+
puts "[-] Login for #{username} failed, retrying in 5 seconds" if @logging
|
29
|
+
sleep(5)
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
def map_heartbeat
|
35
|
+
|
36
|
+
loop do
|
37
|
+
@api.get_player
|
38
|
+
@api.get_hatched_eggs
|
39
|
+
@api.get_inventory(last_timestamp_ms: (Time.now.to_f * 1000).to_i)
|
40
|
+
@api.check_awarded_badges
|
41
|
+
@api.download_settings(hash: "05daf51635c82611d1aac95c0b051d3ec088a930")
|
42
|
+
|
43
|
+
cell_ids = Helpers::CellIds.get(@api.lat, @api.lng)
|
44
|
+
@api.get_map_objects(
|
45
|
+
latitude: lat,
|
46
|
+
longitude: lng,
|
47
|
+
since_timestamp_ms: [0] * cell_ids.count,
|
48
|
+
cell_id: cell_ids
|
49
|
+
)
|
50
|
+
|
51
|
+
begin
|
52
|
+
response = @api.call.response
|
53
|
+
rescue StandardError
|
54
|
+
puts "[-] Error.. Re-logging in" if @logging
|
55
|
+
login(@username, @password, @provider)
|
56
|
+
next
|
57
|
+
end
|
58
|
+
|
59
|
+
case response[:status_code]
|
60
|
+
when 1
|
61
|
+
return response
|
62
|
+
when 2
|
63
|
+
puts "[-] Error... Retrying..." if @logging
|
64
|
+
basic_request
|
65
|
+
when 102
|
66
|
+
puts "[-] Error, re-logging in" if @logging
|
67
|
+
login(@username, @password, @provider)
|
68
|
+
else
|
69
|
+
puts "[-] Heartbeat error: status code #{response[:status_code]}" if @logging
|
70
|
+
puts "[+] Retrying in 2 seconds..." if @logging
|
71
|
+
sleep(2)
|
72
|
+
end
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
76
|
+
def set_location(latitude, longitude)
|
77
|
+
@api.lat = latitude
|
78
|
+
@api.lng = longitude
|
79
|
+
end
|
80
|
+
|
81
|
+
def lat
|
82
|
+
return @api.lat
|
83
|
+
end
|
84
|
+
|
85
|
+
def lng
|
86
|
+
return @api.lng
|
87
|
+
end
|
88
|
+
|
89
|
+
def lat=(lat)
|
90
|
+
@api.lat = lat
|
91
|
+
end
|
92
|
+
|
93
|
+
def lng=(lng)
|
94
|
+
@api.lng = lng
|
95
|
+
end
|
96
|
+
|
97
|
+
|
98
|
+
private
|
99
|
+
|
100
|
+
def basic_request
|
101
|
+
@api.get_player
|
102
|
+
@api.get_hatched_eggs
|
103
|
+
@api.get_inventory
|
104
|
+
@api.check_awarded_badges
|
105
|
+
@api.call
|
106
|
+
end
|
107
|
+
|
108
|
+
end
|
109
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
require 'mongo'
|
2
|
+
|
3
|
+
module Pokeplot
|
4
|
+
module Database
|
5
|
+
|
6
|
+
@@mongo_host = '127.0.0.1:27017'
|
7
|
+
|
8
|
+
def self.mongo
|
9
|
+
Mongo::Logger.level = Logger::FATAL
|
10
|
+
return Mongo::Client.new([ @@mongo_host ], :database => 'pokeplot')
|
11
|
+
end
|
12
|
+
|
13
|
+
def self.mongo_host=(host)
|
14
|
+
@@mongo_host = host
|
15
|
+
end
|
16
|
+
|
17
|
+
def self.mongo_monitor(class_instance)
|
18
|
+
Mongo::Monitoring::Global.subscribe(Mongo::Monitoring::COMMAND, class_instance)
|
19
|
+
end
|
20
|
+
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
module Pokeplot
|
2
|
+
module Helpers
|
3
|
+
class Math
|
4
|
+
class << self
|
5
|
+
|
6
|
+
def deg_to_rad(deg)
|
7
|
+
return deg * (::Math::PI / 180)
|
8
|
+
end
|
9
|
+
|
10
|
+
def get_earth_radius(lat)
|
11
|
+
earth_radius_max = 6378137.0
|
12
|
+
earth_radius_min = 6356752.3
|
13
|
+
latrad = deg_to_rad(lat)
|
14
|
+
return (1.0/(((::Math.cos(latrad))/earth_radius_max)**(2) + ((::Math.sin(latrad))/earth_radius_min)**(2)))**(1.0/2)
|
15
|
+
end
|
16
|
+
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|