pokeplot 0.2.0beta

Sign up to get free protection for your applications and to get access to all the features.
data/README.md ADDED
@@ -0,0 +1,99 @@
1
+ # Pokeplot
2
+
3
+ [![Gem Version](https://badge.fury.io/rb/pokeplot.svg)](https://badge.fury.io/rb/pokeplot) [![Test Coverage](https://codeclimate.com/github/xssc/pokeplot/badges/coverage.svg)](https://codeclimate.com/github/xssc/pokeplot/coverage) [![Dependency Status](https://gemnasium.com/badges/github.com/xssc/pokeplot.svg)](https://gemnasium.com/github.com/xssc/pokeplot) [![Gem](https://img.shields.io/gem/dt/pokeplot.svg?maxAge=2592000)](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
+ ![Graph Example](http://i.imgur.com/XRp14KV.png)
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
@@ -0,0 +1,9 @@
1
+ require "bundler/gem_tasks"
2
+
3
+ begin
4
+ require 'rspec/core/rake_task'
5
+ RSpec::Core::RakeTask.new(:spec)
6
+ task :default => :spec
7
+ rescue LoadError
8
+ # no rspec available
9
+ end
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
@@ -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,5 @@
1
+ class Array; def in_groups(num_groups)
2
+ return [] if num_groups == 0
3
+ slice_size = (self.size/Float(num_groups)).ceil
4
+ self.each_slice(slice_size).to_a
5
+ end; end
@@ -0,0 +1,14 @@
1
+ require 'poke-api/helpers'
2
+ module Pokeplot
3
+ module Helpers
4
+ class CellIds
5
+ class << self
6
+
7
+ def get(lat, long)
8
+ return ::Poke::API::Helpers.get_cells(lat, long)
9
+ end
10
+
11
+ end
12
+ end
13
+ end
14
+ 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
@@ -0,0 +1,15 @@
1
+ module Pokeplot
2
+ module Helpers
3
+ class Time
4
+ class << self
5
+
6
+ def to_s(seconds)
7
+ m = (seconds / 60).floor
8
+ s = seconds % 60
9
+ return "#{m} minutes and #{s} seconds"
10
+ end
11
+
12
+ end
13
+ end
14
+ end
15
+ end