appsendr 0.0.6 → 1.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,258 +0,0 @@
1
- require 'rubygems'
2
- require 'rest_client'
3
- require 'uri'
4
- require 'time'
5
- require 'appsendr/constants'
6
- require 'json/pure' unless {}.respond_to?(:to_json)
7
-
8
- # A Ruby class to call the AppSendr REST API.
9
- #
10
- # Example:
11
- #
12
- # require 'appsendr'
13
- # droppr = AppSendr::Client.new('me@example.com', 'mypass')
14
- # droppr.create('myapp')
15
- #
16
-
17
- class AppSendr::Client
18
- def self.version
19
- AppSendr::VERSION
20
- end
21
-
22
- def self.gem_version_string
23
- "appsendr-gem/#{version}"
24
- end
25
-
26
- def self.auth(user,pass,host)
27
- @resource = RestClient::Resource.new "http://#{host}"
28
- resp = @resource['/api/user/authenticate'].post({:username=>user, :password=>pass})
29
- json_resp = JSON.parse(resp)
30
- return nil unless json_resp
31
- return json_resp["message"] if json_resp["status"].to_i == 200
32
-
33
- end
34
-
35
- attr_reader :host, :user, :password, :api_key
36
-
37
- def initialize(api_key,host='appsendr.com')
38
- @api_key = api_key
39
- @host = host
40
- @resource = RestClient::Resource.new "http://#{@host}"
41
-
42
- end
43
-
44
- def authenticate
45
- post('/api/user/authenticate.json');
46
- end
47
-
48
- def list
49
- get('/api/user/apps.json')
50
- end
51
-
52
- def link(id)
53
- get('/api/app/show/'+id.to_s+'.json');
54
- end
55
- def current_version(app_id)
56
- get('/api/app/versions/'+app_id.to_s+'.json',{:limit=>1})
57
- end
58
-
59
- def versions(app_id)
60
- get('/api/app/versions/'+app_id.to_s+'.json')
61
- end
62
-
63
- def create(name)
64
- post('/api/app/create.json', {:name=>name})
65
- end
66
-
67
- def devices(app_id,plist=true)
68
- format = "json"
69
- format = "plist" if plist
70
-
71
- if app_id
72
- get("/api/tester/devices.#{format}", {:app_id=>app_id})
73
- else
74
- get("/api/tester/devices.#{format}")
75
- end
76
- end
77
-
78
- def add_tester(app_id,email,name,udid=nil)
79
- post('/api/tester/create.json',{:email=>email, :name=>name, :app_id=>app_id.to_s});
80
- end
81
-
82
- def remove_tester(app_id,email)
83
- post('/api/tester/destroy.json',{:email=>email, :app_id=>app_id.to_s});
84
- end
85
-
86
- def clear_testers(app_id)
87
- delete('/api/tester/clear.json',{:app_id=>app_id.to_s});
88
- end
89
-
90
- def add_group(app_id,name)
91
- post('/api/group/create.json',{:name=>name,:app_id=>app_id.to_s});
92
- end
93
-
94
- def remove_group(app_id, name)
95
- post('/api/group/destroy.json',{:name=>name,:app_id=>app_id.to_s});
96
- end
97
-
98
- def groups(app_id)
99
- get('/api/app/groups/'+app_id.to_s+'.json')
100
- end
101
-
102
-
103
- def add_group_tester(app_id,name, email)
104
- post('/api/group/add_tester.json',{:name=>name,:app_id=>app_id.to_s, :email=>email});
105
- end
106
-
107
- def remove_group_tester(app_id, name, email)
108
- post('/api/group/remove_tester.json',{:name=>name,:app_id=>app_id.to_s, :email=>email});
109
- end
110
-
111
-
112
- ### add_collaborator
113
-
114
- def add_collaborator(app_id,emaill)
115
- post('/api/collaborator/create.json',{:email=>email,:app_id=>app_id.to_s});
116
- end
117
-
118
- def remove_collaborator(app_id,email)
119
- post('/api/collaborator/destroy.json',{:email=>email,:app_id=>app_id.to_s});
120
- end
121
-
122
- def collaborators(app_id)
123
- get('/api/app/collaborators/'+app_id.to_s+'.json')
124
- end
125
-
126
- def testers(app_id)
127
- get('/api/app/testers/'+app_id.to_s+'.json')
128
- end
129
- def notify(app_id,group=nil)
130
- post('/api/app/notify/'+app_id.to_s+'.json',{:group=>group})
131
- end
132
-
133
- def upload(app_id, ipa,provisioning, is_public, notify, notes, bundle_id, icon, later=false)
134
- params = {
135
- :provisioning_profile => File.new(provisioning, 'rb'),
136
- :notes=>notes,
137
- :bundle_identifier => bundle_id,
138
- :built_at=>Time.now,
139
- :notify=>notify,
140
- :public=>is_public,
141
- :app_id => app_id.to_s
142
- # :ipa=>
143
- }
144
- if icon
145
- params[:icon] = File.new(icon,'rb')
146
- end
147
-
148
- if later
149
- params[:upload_later] = File.basename(ipa)
150
-
151
- else
152
- params[:ipa] = File.new(ipa, 'rb')
153
-
154
- end
155
-
156
- post('/api/version/create.json', {:version=>params})
157
- end
158
-
159
- def initialize_multipart(app_id, version_id, ipa)
160
- ipa_name = File.basename(ipa)
161
-
162
- params = {}
163
- params[:ipa_path] = upload_path(app_id,version_id,ipa_name)
164
- params[:ipa_name] = ipa_name
165
- params[:id] = version_id
166
-
167
- post('/api/version/multipart_init.json', {:version=>params})
168
- end
169
-
170
- def upload_part(app_id, version_id, ipa, upload_id, part_number, chunk)
171
- ipa_name = File.basename(ipa)
172
- ipa_size = File.size(ipa)
173
-
174
- params = {}
175
- params[:ipa_chunk] = File.new(chunk,'rb')
176
- params[:ipa_size] = ipa_size
177
- params[:ipa_path] = upload_path(app_id,version_id,ipa_name)
178
- params[:upload_id] = upload_id
179
- params[:part_number] = part_number
180
- params[:id] = version_id
181
-
182
- retryable( :tries => 5 ) do
183
- resp = post('/api/version/multipart_upload_part.json', {:version=>params})
184
- return resp
185
- end
186
- end
187
-
188
- def finish_multipart(app_id, version_id, ipa, upload_id, parts, notify)
189
- ipa_name = File.basename(ipa)
190
- ipa_size = File.size(ipa)
191
-
192
- params = {}
193
- params[:ipa_size] = ipa_size
194
- params[:ipa_path] = upload_path(app_id,version_id,ipa_name)
195
- params[:upload_id] = upload_id
196
- params[:parts] = parts
197
- params[:id] = version_id
198
- params[:notify] = notify
199
- post('/api/version/multipart_finished.json', {:version=>params})
200
-
201
-
202
- end
203
-
204
- def abort_multipart(app_id, version_id, ipa, upload_id)
205
- params = { :version=> {
206
- :ipa_path=>upload_path(app_id,version_id,File.basename(ipa)),
207
- :upload_id=>upload_id,
208
- :id=>version_id
209
- }
210
- }
211
- post('/api/version/abort_multipart.json',params)
212
-
213
- end
214
-
215
- protected
216
-
217
-
218
- def upload_path(app_id,version_id,ipa_name)
219
- "app/#{app_id}/#{version_id}/ipa/#{ipa_name}"
220
- end
221
-
222
- def api_params(params={})
223
- params[:api_key] ||= @api_key
224
-
225
- end
226
-
227
- def retryable(options = {}, &block)
228
- opts = { :tries => 1, :on => Exception }.merge(options)
229
-
230
- retry_exception, retries = opts[:on], opts[:tries]
231
-
232
- begin
233
- return yield
234
- rescue retry_exception
235
- retry if (retries -= 1) > 0
236
- end
237
-
238
- yield
239
- end
240
-
241
- def get(uri,params={})
242
- params[:api_key] ||= @api_key
243
- resp = RestClient.get @resource.url+uri, {:params=>params}
244
- JSON.parse(resp)
245
- #@resource[uri].get(api_params(params))#, :content_type => 'application/json')
246
- end
247
- def post(uri,params={})
248
- params[:api_key] ||= @api_key
249
- resp = @resource[uri].post(params)#, :content_type => 'application/json')
250
- JSON.parse(resp)
251
- end
252
-
253
- def delete(uri,params={})
254
- params[:api_key] ||= @api_key
255
- print params
256
- @resource[uri].delete(params)#, :content_type => 'application/json')
257
- end
258
- end
@@ -1,81 +0,0 @@
1
- require 'appsendr/helpers'
2
- require 'appsendr/binary_plist'
3
- require 'appsendr/commands/base'
4
- require 'appsendr/progressbar'
5
-
6
- Dir["#{File.dirname(__FILE__)}/commands/*.rb"].each { |c| require c }
7
-
8
- module AppSendr
9
- module Command
10
- class InvalidCommand < RuntimeError; end
11
- class CommandFailed < RuntimeError; end
12
-
13
- extend AppSendr::Helpers
14
-
15
- class << self
16
-
17
- def run(command, args, retries=0)
18
- begin
19
- run_internal 'auth:login', args.dup if (retries > 0 or !credentials_setup?)
20
- run_internal(command, args.dup)
21
- rescue InvalidCommand
22
- error "Unknown command. Run 'appsendr help' for usage information."
23
- rescue RestClient::Unauthorized
24
- if retries < 3
25
- STDERR.puts "Authentication failure"
26
- run(command, args, retries+1)
27
- else
28
- error "Authentication failure"
29
- end
30
- rescue RestClient::ResourceNotFound
31
- error "Record not found. Are you allowed to access this record?"
32
- rescue RestClient::RequestFailed => e
33
- begin
34
- response = JSON.parse(e.http_body)
35
- display "=== Errors"
36
- response['message'].each{|err|
37
- display err.join(" ")
38
- }
39
- rescue
40
- error "Something went wrong with the server."
41
- end
42
- rescue CommandFailed => e
43
- error e.message
44
- rescue Interrupt => e
45
- error "\n[canceled]"
46
- rescue Exception => e
47
- error e
48
- end
49
- end
50
-
51
- def run_internal(command, args, appsendr=nil)
52
- klass, method = parse(command)
53
- runner = klass.new(args, appsendr)
54
- raise InvalidCommand unless runner.respond_to?(method)
55
- runner.send(method)
56
- end
57
-
58
- def parse(command)
59
- parts = command.split(':')
60
- case parts.size
61
- when 1
62
- begin
63
- return eval("AppSendr::Command::#{command.capitalize}"), :index
64
- rescue NameError, NoMethodError
65
- return AppSendr::Command::App, command.to_sym
66
- end
67
- else
68
- begin
69
- const = AppSendr::Command
70
- command = parts.pop
71
- parts.each { |part| const = const.const_get(part.capitalize) }
72
- return const, command.to_sym
73
- rescue NameError
74
- raise InvalidCommand
75
- end
76
- end
77
- end
78
-
79
- end
80
- end
81
- end
@@ -1,241 +0,0 @@
1
- require 'readline'
2
-
3
- module AppSendr::Command
4
- class App < Base
5
- attr_accessor :app_id, :app_name, :app
6
-
7
- def list
8
- list = appsendr.list
9
- if list["message"].size > 0
10
- message "Your apps"
11
- i = 0
12
- display list["message"].map {|app, id|
13
- "#{i+=1}. #{app['name'].ljust(35)}"
14
- }.join("\n")
15
- else
16
- display "You have no apps."
17
- end
18
- end
19
-
20
- def create
21
- # username = extract_option('--username')
22
- # display username
23
- # password = extract_option('--password')
24
- # display password
25
- #
26
- name = args.join(" ").strip
27
-
28
- error "You must include an app name" if name.empty?
29
- require_project_dir("add an app")
30
-
31
- if has_project_droppr?
32
- list = appsendr.list
33
- if list["message"].size > 0
34
- list["message"].each{|app|
35
- if app['name'] == name
36
- remove_appsendr_dir
37
- make_appsendr_dir
38
-
39
- @app = [ app['id'], app['name']]
40
- write_app
41
- display "Your app has been linked."
42
- return
43
- end
44
- }
45
-
46
- resp = appsendr.create(name)
47
- remove_appsendr_dir
48
- make_appsendr_dir if resp['message']
49
- @app = [resp['message']['id'],resp['message']['name']]
50
- write_app
51
- display "Your app has been created."
52
-
53
- else
54
- error "This app is linked to another account's app"
55
- end
56
- else
57
- resp = appsendr.create(name)
58
- make_appsendr_dir if resp['message']
59
- @app = [resp['message']['id'],resp['message']['name']]
60
- write_app
61
- display "Your app has been created."
62
- end
63
-
64
- end
65
-
66
- def url
67
- if in_project_dir?
68
-
69
- resp = appsendr.current_version(get_app_id)
70
- if resp["message"].size > 0
71
- message "Your last install url is:"
72
- url = resp["message"][0]['install_url']
73
- display url
74
- do_copy = option_exists?('--copy', false)
75
- if do_copy
76
- display "Copied URL"
77
- IO.popen('pbcopy', 'w') { |clipboard| clipboard.write url }
78
- end
79
- else
80
- display "No versions available"
81
- end
82
- else
83
- error("You are not in a project directory")
84
- end
85
-
86
- end
87
-
88
- def link
89
- if in_project_dir?
90
- error "This app is already linked to an appsendr." unless !has_project_droppr?
91
-
92
- app = list_apps_and_ask
93
- return unless app
94
-
95
- link = appsendr.link(app['id'])
96
- make_appsendr_dir if link
97
- name = link['message']['name'] || app['name']
98
- aid = link['message']['id'] || app['id']
99
-
100
- @app = [aid,name]
101
- write_app
102
- display "Your app has been linked."
103
-
104
- else
105
- error("You are not in a project directory")
106
- end
107
- end
108
-
109
- def list_apps_and_ask
110
- apps = []
111
- lines = []
112
- list = appsendr.list
113
- if list["message"].size > 0
114
- message "Your apps"
115
- i = 0
116
- list["message"].each{|app|
117
- apps.push({"name"=>app['name'], "id"=>app['id']})
118
- lines.push("#{i+=1}. #{app['name'].ljust(35)}")
119
- }
120
- display lines.join("\n")
121
- print "\n"
122
- print "Enter the # for the app you wish to link to: "
123
- app_number = ask
124
-
125
- return apps[app_number.to_i-1]
126
-
127
- else
128
- display "You have no apps."
129
- end
130
- end
131
-
132
- def versions
133
- if in_project_dir?
134
-
135
- groups = appsendr.versions(get_app_id)
136
- if groups["message"].size > 0
137
- message "Your versions"
138
- i = 0
139
- display groups["message"].map {|app, id|
140
- "#{i+=1}. #{app['notes']} #{app['install_url']}"
141
- }.join("\n")
142
- else
143
- display "You have no version."
144
- end
145
- else
146
- error("You are not in a project directory")
147
- end
148
- end
149
- # def info
150
- # name = (args.first && !args.first =~ /^\-\-/) ? args.first : extract_app
151
- # attrs = appsendr.info(name)
152
- #
153
- # attrs[:web_url] ||= "http://#{attrs[:name]}.#{heroku.host}/"
154
- # attrs[:git_url] ||= "git@#{heroku.host}:#{attrs[:name]}.git"
155
- #
156
- # display "=== #{attrs[:name]}"
157
- # display "Web URL: #{attrs[:web_url]}"
158
- # display "Domain name: http://#{attrs[:domain_name]}/" if attrs[:domain_name]
159
- # display "Git Repo: #{attrs[:git_url]}"
160
- # display "Dynos: #{attrs[:dynos]}"
161
- # display "Workers: #{attrs[:workers]}"
162
- # display "Repo size: #{format_bytes(attrs[:repo_size])}" if attrs[:repo_size]
163
- # display "Slug size: #{format_bytes(attrs[:slug_size])}" if attrs[:slug_size]
164
- # display "Stack: #{attrs[:stack]}" if attrs[:stack]
165
- # if attrs[:database_size]
166
- # data = format_bytes(attrs[:database_size])
167
- # if tables = attrs[:database_tables]
168
- # data = data.gsub('(empty)', '0K') + " in #{quantify("table", tables)}"
169
- # end
170
- # display "Data size: #{data}"
171
- # end
172
- #
173
- # if attrs[:cron_next_run]
174
- # display "Next cron: #{format_date(attrs[:cron_next_run])} (scheduled)"
175
- # end
176
- # if attrs[:cron_finished_at]
177
- # display "Last cron: #{format_date(attrs[:cron_finished_at])} (finished)"
178
- # end
179
- #
180
- # unless attrs[:addons].empty?
181
- # display "Addons: " + attrs[:addons].map { |a| a['description'] }.join(', ')
182
- # end
183
- #
184
- # display "Owner: #{attrs[:owner]}"
185
- # collaborators = attrs[:collaborators].delete_if { |c| c[:email] == attrs[:owner] }
186
- # unless collaborators.empty?
187
- # first = true
188
- # lead = "Collaborators:"
189
- # attrs[:collaborators].each do |collaborator|
190
- # display "#{first ? lead : ' ' * lead.length} #{collaborator[:email]}"
191
- # first = false
192
- # end
193
- # end
194
- #
195
- # if attrs[:create_status] != "complete"
196
- # display "Create Status: #{attrs[:create_status]}"
197
- # end
198
- # end
199
-
200
- protected
201
- def remove_appsendr_dir
202
- if in_project_dir?
203
- FileUtils.rm_r(Dir.pwd+"/"+AppSendr::PROJECT_DIR)
204
- end
205
- end
206
-
207
- def make_appsendr_dir
208
- if in_project_dir?
209
- FileUtils.mkdir_p(Dir.pwd+"/"+AppSendr::PROJECT_DIR)
210
- end
211
- end
212
-
213
- def get_app
214
- return if @app
215
- unless @app = read_app
216
- end
217
- @app
218
- end
219
-
220
- def get_app_id
221
- return if @app_id
222
- unless @app_id = read_app_id
223
- end
224
- @app_id
225
- end
226
-
227
-
228
- def write_app
229
- FileUtils.mkdir_p(File.dirname(project_appsendr_app))
230
- File.open(project_appsendr_app, 'w') do |f|
231
- f.puts self.app.join("\n")
232
- end
233
- set_app_permissions
234
- end
235
-
236
- def set_app_permissions
237
- FileUtils.chmod 0700, File.dirname(project_appsendr_app)
238
- FileUtils.chmod 0600, project_appsendr_app
239
- end
240
- end
241
- end