civility 1

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.
Files changed (4) hide show
  1. checksums.yaml +7 -0
  2. data/bin/civility +5 -0
  3. data/lib/civility.rb +195 -0
  4. metadata +61 -0
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 1df76ba40aea50dec8f246b036906e5f27dc002d
4
+ data.tar.gz: e4e16a66f545ae76eb60c719170730853392f213
5
+ SHA512:
6
+ metadata.gz: eef89961b15e37fca9565cd636057f6012e2eb8132fea08d112ac2ffc235875212cbd06927042ab341e4cf4dcf2644d9f9a4f7df99de75d38a7e60e441d6ef76
7
+ data.tar.gz: f84cd67d695ec79d6ecf4adc4dae5a9658dce3b4e411b013e741ce9b8a97abd843d84f679f69d741f85825f3a9cdecd9f916736f31d60a5e02c66470a68a80f1
@@ -0,0 +1,5 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require '/Users/abraham/dev/civility/lib/civility'
4
+
5
+ Civility.start(ARGV)
@@ -0,0 +1,195 @@
1
+ require 'net/http'
2
+ require 'uri'
3
+ require 'json'
4
+ require 'yaml'
5
+ require 'thor'
6
+
7
+ class Civility < Thor
8
+ VERSION = '1'
9
+ SAVE_DIRECTORY = "/Documents/Aspyr/Sid\ Meier\'s\ Civilization\ 5/Saves/hotseat/"
10
+ FILE_PREFIX = 'civility'
11
+ FILE_EXT = 'Civ5Save'
12
+ API = 'http://multiplayerrobot.com/api/Diplomacy/'
13
+ CONFIG_FILE = '.civility.yml'
14
+
15
+ def initialize(*args)
16
+ @config = load_config
17
+ super(*args)
18
+ end
19
+
20
+ desc 'auth', 'Save auth key'
21
+ def auth(key = nil)
22
+ if key.nil?
23
+ url = 'http://multiplayerrobot.com/download'
24
+ puts "Grab your Authentication Key from #{url}"
25
+ system('open', url)
26
+ else
27
+ @config[:version] = VERSION
28
+ @config[:auth] = key
29
+ @config[:user] = user
30
+ self.config = @config
31
+ puts "Hello, #{user['PersonaName']}, your auth is all configured!"
32
+ end
33
+ end
34
+
35
+ desc "games", "List your current games"
36
+ def games
37
+ return missing_auth_error unless auth_key
38
+ response = get('GetGamesAndPlayers', {authKey: auth_key, playerIDText: user_id})
39
+ response = JSON.parse(response)
40
+ output_games(response['Games'])
41
+ self.config = @config.merge(games: response['Games'], updated_at: Time.now.to_i)
42
+ end
43
+
44
+ desc 'play', 'Download a game to play'
45
+ def play(name)
46
+ return missing_auth_error unless auth_key
47
+ game = game_by_name(name)
48
+ return missing_game_error unless game
49
+ path = game_path(game)
50
+ file('GetLatestSaveFileBytes', {authKey: auth_key, gameID: game['GameId']}, path)
51
+ puts "Saved #{game['Name']} to #{path}"
52
+ end
53
+
54
+ desc 'complete', 'Upload a completed turn'
55
+ def complete(name)
56
+ return missing_auth_error unless auth_key
57
+ game = game_by_name(name)
58
+ return missing_game_error unless game
59
+ path = game_path(game)
60
+ response = upload_file('SubmitTurn', {authKey: auth_key, turnId: game['CurrentTurn']['TurnId']}, path)
61
+ response = JSON.parse(response)
62
+ case response['ResultType']
63
+ when 0
64
+ puts "UnexpectedError: #{response}"
65
+ when 1
66
+ puts "You earned #{response['PointsEarned']} points completing #{game['Name']} from #{path}"
67
+ when 2
68
+ puts "It's not your turn"
69
+ when 3
70
+ puts 'You already submitted your turn'
71
+ else
72
+ puts 'UnexpectedError'
73
+ end
74
+ end
75
+
76
+ private
77
+
78
+ def game_path(game)
79
+ "#{Dir.home}#{SAVE_DIRECTORY}#{FILE_PREFIX}-#{normalize(game['Name'])}-#{game['GameId']}.#{FILE_EXT}"
80
+ end
81
+
82
+ def auth_key
83
+ @config[:auth]
84
+ end
85
+
86
+ def user_id
87
+ @config[:user]['SteamID']
88
+ end
89
+
90
+ def games_list
91
+ @config[:games]
92
+ end
93
+
94
+ def output_games(games)
95
+ for game in games
96
+ turn = (user_id == game['CurrentTurn']['UserId'] ? " and it's your turn" : '')
97
+ puts "#{game['Name']} with #{game['Players'].size} other players#{turn}"
98
+ end
99
+ puts "If your games are missing, try again" if games.size == 0
100
+ end
101
+
102
+ def game_by_name(name)
103
+ name = normalize(name)
104
+ games_list.find {|game| normalize(game['Name']) == name}
105
+ end
106
+
107
+ def user
108
+ user_id = get('AuthenticateUser', {authKey: auth_key})
109
+ response = get('GetGamesAndPlayers', {authKey: auth_key, playerIDText: user_id})
110
+ players = JSON.parse(response)['Players']
111
+ user_from_players(user_id, players)
112
+ end
113
+
114
+ def user_from_players(user_id, players)
115
+ user_id = user_id.to_i
116
+ players.find {|player| player['SteamID'] == user_id }
117
+ end
118
+
119
+ def normalize(name)
120
+ name.downcase.strip.gsub(/[^\w]/, '')
121
+ end
122
+
123
+ def get(method, params)
124
+ uri = URI.join(API, method)
125
+ uri.query = URI.encode_www_form(params)
126
+ response = Net::HTTP.get_response(uri)
127
+ fail error_message(response) unless response.code == '200'
128
+ response.body
129
+ end
130
+
131
+ def file(method, params, path)
132
+ uri = URI.parse("#{API}#{method}")
133
+ uri.query = URI.encode_www_form(params)
134
+ f = open(path, "wb")
135
+ Net::HTTP.start(uri.host) do |http|
136
+ http.request_get(uri.request_uri) do |response|
137
+ fail error_message(response) unless response.code == '200'
138
+ response.read_body do |segment|
139
+ f.write(segment)
140
+ end
141
+ end
142
+ end
143
+ ensure
144
+ f.close()
145
+ end
146
+
147
+ def upload_file(method, params, path)
148
+ uri = URI.parse("#{API}#{method}")
149
+ uri.query = URI.encode_www_form(params)
150
+ data = File.read(path)
151
+ http = Net::HTTP.new(uri.host)
152
+ request = Net::HTTP::Post.new(uri.request_uri)
153
+ request.body = data
154
+ response = http.request(request)
155
+ fail error_message(response) unless response.code == '200'
156
+ response.body
157
+ end
158
+
159
+ def load_config
160
+ if config_file?
161
+ @config = YAML::load_file config_path
162
+ else
163
+ self.config = {}
164
+ end
165
+ end
166
+
167
+ def error_message(response)
168
+ body = JSON.parse(response.body)
169
+ "Code: #{response.code}\nBody: #{body}"
170
+ rescue JSON::ParserError
171
+ "Unable to parse response\nCode: #{response.code}\nBody: #{response.body}"
172
+ end
173
+
174
+ def missing_game_error
175
+ puts 'Unable to find that game'
176
+ end
177
+
178
+ def missing_auth_error
179
+ puts 'Please run `civility auth` first'
180
+ end
181
+
182
+ def config=(settings)
183
+ File.open(config_path, 'w') do |file|
184
+ file.write settings.to_yaml
185
+ end
186
+ end
187
+
188
+ def config_path
189
+ "#{Dir.home}/#{CONFIG_FILE}"
190
+ end
191
+
192
+ def config_file?
193
+ File.exist?(config_path)
194
+ end
195
+ end
metadata ADDED
@@ -0,0 +1,61 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: civility
3
+ version: !ruby/object:Gem::Version
4
+ version: '1'
5
+ platform: ruby
6
+ authors:
7
+ - Abraham Williams
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2016-02-23 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: thor
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '0'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '0'
27
+ description: Civility is the easiest way to manage your Civ5 hotseat games hosted
28
+ on Giant Multiplayer Robot
29
+ email: abraham@abrah.am
30
+ executables:
31
+ - civility
32
+ extensions: []
33
+ extra_rdoc_files: []
34
+ files:
35
+ - bin/civility
36
+ - lib/civility.rb
37
+ homepage: https://github.com/abraham/civility
38
+ licenses:
39
+ - MIT
40
+ metadata: {}
41
+ post_install_message:
42
+ rdoc_options: []
43
+ require_paths:
44
+ - lib
45
+ required_ruby_version: !ruby/object:Gem::Requirement
46
+ requirements:
47
+ - - ">="
48
+ - !ruby/object:Gem::Version
49
+ version: '0'
50
+ required_rubygems_version: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ">="
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
55
+ requirements: []
56
+ rubyforge_project:
57
+ rubygems_version: 2.5.1
58
+ signing_key:
59
+ specification_version: 4
60
+ summary: The easiest way to manage your Civ5 hotseat games on GMR
61
+ test_files: []