fir-cli 0.0.1 → 0.0.3

Sign up to get free protection for your applications and to get access to all the features.
Files changed (4) hide show
  1. checksums.yaml +4 -4
  2. data/lib/fir-cli.rb +268 -0
  3. data/lib/lagunitas.ext.rb +26 -0
  4. metadata +3 -1
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 6a2a40586779623fdcb4e00c9e33ee646fb3e601
4
- data.tar.gz: d13c1b240b0846bb9a79812930053da22ab39f9d
3
+ metadata.gz: 83254124e7786b02524d0f9e71959d485fa2c0d5
4
+ data.tar.gz: ab7e4fb4fff850ecdd9e77c11cda079b9d9c21f8
5
5
  SHA512:
6
- metadata.gz: 467a11d0e61dac2781637a8036cfe9ce2f850313996e176b2cd1f1112860b9f3b5879f84a204d5ce1230ed94db76670f7c6812daf7e8063dc0ecd14da81bcdd5
7
- data.tar.gz: 660f8b5539ba9480e81fd1ca99e3013bb422ad6e196e5a17f92201a79c03c7f9d0b68dd31b4a32390d93557b431d576b31a266899512048fbdd959d45aec2307
6
+ metadata.gz: 66cc17ddaaa3c2a40b558d6d345d310e1eed7752a61c18d9078963dc37a8f46e82c09951c44b4619bf52718c9f2dc15c54bcc9a2c2176ef1fa355b6133b16400
7
+ data.tar.gz: e902ebef6f9858250f0e51612134684c8bb8982a3bb348c9667dcd8da07e119454555bf2c151c06367ff9bfbebed17d187ce626e274e9bbd4915448d53319faa
data/lib/fir-cli.rb ADDED
@@ -0,0 +1,268 @@
1
+ require 'uri'
2
+ require 'json'
3
+ require 'pathname'
4
+ require 'tempfile'
5
+ require 'securerandom'
6
+
7
+ require 'thor'
8
+ require 'paint'
9
+ require 'pngdefry'
10
+ require 'user_config'
11
+ require 'rest_client'
12
+ require 'lagunitas'
13
+ require 'lagunitas.ext'
14
+
15
+ # p Lagunitas::App.new('').respond_to? :mobileprovision
16
+
17
+ class FirCli < Thor
18
+ def initialize(*args)
19
+ super
20
+ @uconfig = UserConfig.new '.fir'
21
+ @ipa_config = @uconfig['ipa.yaml']
22
+ if @ipa_config['resign'] == nil then @ipa_config['resign'] = false end
23
+ end
24
+
25
+ desc 'login USER_TOKEN', '以 USER_TOKEN 身份登陆'
26
+ def login(token)
27
+ ot = @ipa_config['token']
28
+ if ot && ot != token
29
+ puts "> 替换用户 #{ot} => #{token}"
30
+ end
31
+ @ipa_config['token'] = token
32
+ @ipa_config.save
33
+ puts "> 当前用户:#{token}"
34
+ end
35
+
36
+ desc 'config', '配置全局设置'
37
+ option :resign, :aliases => '-r', :desc => '是否以企业签名发布,默认为否', :type => :boolean, :default => false
38
+ option :token, :aliases => '-t', :desc => '用户令牌'
39
+ option :email, :aliases => '-e', :desc => '邮件地址'
40
+ option :verbose, :aliases => '-v', :desc => '输出配置项', :type => :boolean
41
+ def config
42
+ if !options[:verbose]
43
+ options.each do |conf|
44
+ puts "> #{ Paint[conf[0].to_s.rjust(10), :blue] } : #{ @ipa_config[conf[0].to_s] } => #{ conf[1] }"
45
+ @ipa_config[conf[0]] = conf[1]
46
+ end
47
+ @ipa_config.save
48
+ end
49
+ puts "> 当前设置:"
50
+ @ipa_config.each {|conf| puts "> #{ Paint[conf[0].to_s.rjust(10), :blue] } => #{conf[1]}"}
51
+ end
52
+
53
+ desc 'update IPA_FILE_PATH', '更新 fir.im 的应用信息'
54
+ option :short, :aliases => '-s', :desc => '自定义短地址'
55
+ option :token, :aliases => '-t', :desc => '用户令牌,不写则使用已经登陆信息'
56
+ def update(path)
57
+ app = info path, false, true
58
+ fir_app = fir_info app[:identifier]
59
+ opt_short = options[:short]
60
+ post = {}
61
+ post[:public] = options[:public] != nil ? options[:public] : @ipa_config['public']
62
+ if opt_short then post[:short] = opt_short end
63
+
64
+ post.each { |i| if i[1] == fir_app[i[0]] then post.delete i[0] end }
65
+
66
+ if post.length == 0 then puts '> 没有可以更新的项目'; return end
67
+ fir_put fir_app[:id], post
68
+
69
+ fir_app = fir_info app[:identifier]
70
+ if opt_short && opt_short != fir_app[:short]
71
+ puts "> 短地址 #{ opt_short } 被占用,FIR.im 自动更新短地址为 #{ fir_app[:short] }"
72
+ end
73
+ puts "> http://fir.im/#{fir_app[:short]}"
74
+ end
75
+
76
+ desc 'publish IPA_FILE_PATH', '将 .ipa 文件发布至 FIR.im'
77
+ option :resign, :aliases => '-r', :desc => '进行企业签名', :type => :boolean
78
+ option :short, :aliases => '-s', :desc => '自定义短地址'
79
+ option :token, :aliases => '-t', :desc => '用户令牌,不写则使用已经登陆信息'
80
+ option :changelog, :aliases => '-c', :desc => '修改纪录,默认为空字符串', :default => ''
81
+ def publish(path)
82
+ if opt_resign
83
+ tfile = Tempfile.new SecureRandom.hex
84
+ resign path, tfile.path
85
+ path = tfile.path
86
+ end
87
+ app = info path
88
+ fir_app = fir_info app[:identifier]
89
+
90
+ id = fir_app[:id]
91
+ short = fir_app[:short]
92
+ bundle_app = fir_app[:bundle][:pkg]
93
+ bundle_icon = fir_app[:bundle][:icon]
94
+
95
+ puts '> 上传应用...'
96
+ res = RestClient.post bundle_app[:url],
97
+ :key => bundle_app[:key],
98
+ :token => bundle_app[:token],
99
+ :file => File.new(path, 'rb')
100
+ puts '> 上传应用成功'
101
+ upload_res = JSON.parse res.body, :symbolize_names => true
102
+
103
+ if app[:icons] != nil
104
+ icon_path = app[:icons][0][:path]
105
+
106
+ puts '> 转换图标...'
107
+ Pngdefry.defry icon_path, icon_path
108
+
109
+ puts "> 上传图标..."
110
+ RestClient.post bundle_icon[:url],
111
+ :key => bundle_icon[:key],
112
+ :token => bundle_icon[:token],
113
+ :file => File.new(icon_path, 'rb')
114
+
115
+ puts '上传图标成功'
116
+ end
117
+
118
+ fir_put fir_app[:id],
119
+ :name => app[:display_name] || app[:name],
120
+ :short => options[:short] || fir_app[:short],
121
+ :version => app[:version],
122
+ :versionShort => app[:short_version]
123
+
124
+ fir_vput upload_res[:versionOid],
125
+ :version => app[:version],
126
+ :versionShort => app[:short_version],
127
+ :devices => app[:devices],
128
+ :release_type => app[:release_type],
129
+ :changelog => options[:changelog]
130
+
131
+
132
+ puts "> http://fir.im/#{short}"
133
+ end
134
+
135
+ desc 'digg IPA_FILE_PATH', '获取 .ipa 文件的信息'
136
+ option 'verbose', :aliases => '-v', :desc => '显示更多信息', :type => :boolean
137
+ option 'fir', :aliases => '-f', :desc => '显示托管在 fir.im 的信息', :type => :boolean
138
+ def digg(path)
139
+ app = info path, false, options['verbose']
140
+ app.each { |i| puts "#{ Paint[i[0].to_s.rjust(15), :blue] } #{ i[1] }" }
141
+ if options[:fir]
142
+ fir_app = fir_info app[:identifier]
143
+ fir_app.each { |i| puts "#{ Paint[i[0].to_s.rjust(15), :blue] } #{ i[1] }" }
144
+ end
145
+ end
146
+
147
+ desc 'resign IPA_FILE_PATH OUTPUT_PATH', '使用 resign.tapbeta.com 进行企业签名'
148
+ option 'email', :aliases => '-e', :desc => '邮件地址'
149
+ def resign(ipath, opath)
150
+ puts '! resign.tapbeta.com 签名服务风险提示'
151
+ puts '! 无法保证签名证书的长期有效性,当某种条件满足后'
152
+ puts '! 苹果会禁止该企业账号,所有由该企业账号所签发的'
153
+ puts '! 证书都会失效。您如果使用该网站提供的服务进行应'
154
+ puts "! 用分发,请注意:#{ Paint['当证书失效后,所有安装以失效证', :red ] }"
155
+ puts "! #{ Paint['书签名的的用户都会无法正常运行应用;同时托管在', :red ] }"
156
+ puts "! #{ Paint['fir.im 的应用将无法正常安装。', :red ] }"
157
+ if opt_email == nil
158
+ puts Paint['! 您需要提供邮件地址才能使用 resign.tapbeta.com 的签名服务', :red]
159
+ puts Paint['! 使用 fir config --email=EMAIL 进行设置', :green]
160
+ exit
161
+ end
162
+ if !/\.ipa$/.match ipath
163
+ puts Paint['! 只能给以 ipa 为扩展名的文件签名', :red]
164
+ exit
165
+ end
166
+ puts '> 正在申请上传令牌...'
167
+ upload_res = RestClient.post 'http://api.resign.tapbeta.com/public/upload',
168
+ :email => @email,
169
+ :file => File.basename(ipath)
170
+ form = JSON.parse upload_res.body, :symbolize_names => true
171
+ tapbeta = {}
172
+ form.each do |f|
173
+ if /^tb_/.match f[0]
174
+ tapbeta[f[0]] = f[1]
175
+ form.delete f[0]
176
+ end
177
+ end
178
+ form[:file] = File.new Pathname.new(Dir.pwd).join(ipath).cleanpath, 'rb'
179
+ puts '> 正在上传...'
180
+ RestClient.post tapbeta[:tb_upload_url], form
181
+ puts '> 正在排队...'
182
+ nped = true
183
+ info = {}
184
+ loop do
185
+ res = RestClient.get "http://api.resign.tapbeta.com/public/#{ tapbeta[:tb_upload_key] }",
186
+ :params => { :__mr => 'eyJ1cmwiOiIkKHVybCkiLCAicmVzaWduU3RhdHVzIjogIiQocmVzaWduU3RhdHVzKSJ9' }
187
+ info = JSON.parse res.body, :symbolize_names => true
188
+ if nped && info[:resignStatus] == 'doing'
189
+ puts '> 正在签名...'
190
+ nped = false
191
+ end
192
+ if info[:url] != '' then break end
193
+ sleep 5
194
+ end
195
+ opath = Pathname.new(Dir.pwd).join(opath).cleanpath
196
+ puts "> 正在下载到 #{ opath }..."
197
+ `curl #{info[:url]} -o #{opath} -s`
198
+ end
199
+
200
+ private
201
+ def info(path, quiet = false, more = false)
202
+ path = Pathname.new(Dir.pwd).join(path).cleanpath
203
+ ipa = Lagunitas::IPA.new path
204
+ if !quiet then puts '> 正在解析 ipa 文件...' end
205
+ app = ipa.app
206
+ info = {
207
+ :identifier => app.identifier,
208
+ :name => app.name,
209
+ :display_name => app.display_name,
210
+ :version => app.version,
211
+ :short_version => app.short_version,
212
+ :devices => app.devices,
213
+ :release_type => app.release_type
214
+ # :distribution_name => app.distribution_name
215
+ }
216
+ if more
217
+ begin
218
+ info[:icons] = app.icons
219
+ rescue
220
+ end
221
+ info[:plist] = app.info
222
+ end
223
+ ipa.cleanup
224
+ info
225
+ end
226
+ def fir_info(identifier, quiet = false)
227
+ if !opt_token
228
+ puts Paint['! 您还没有登录', :red]
229
+ puts Paint['! 请 fir login USER_TOKEN 登录', :green]
230
+ exit
231
+ end
232
+ body = { :token => @token }
233
+ if !quiet then puts '> 正在获取 fir 的应用信息...' end
234
+ res = RestClient.get "http://fir.im/api/v2/app/info/#{identifier}?#{URI.encode_www_form body}"
235
+ JSON.parse res.body, :symbolize_names => true
236
+ end
237
+ def fir_put(id, body, quiet = false)
238
+ if !opt_token
239
+ puts Paint['! 您还没有登录', :red]
240
+ puts Paint['! 请 fir login USER_TOKEN 登录', :green]
241
+ exit
242
+ end
243
+ body[:token] = @token
244
+ if !quiet then puts '> 正在更新 fir 的应用信息...' end
245
+ RestClient.put "http://fir.im/api/v2/app/#{id}?#{URI.encode_www_form body}", body
246
+ puts '> 更新成功'
247
+ end
248
+ def fir_vput(id, body, quiet = false)
249
+ if !opt_token
250
+ puts Paint['! 您还没有登录', :red]
251
+ puts Paint['! 请 fir login USER_TOKEN 登录', :green]
252
+ exit
253
+ end
254
+ body[:token] = @token
255
+ if !quiet then puts '> 正在更新 fir 的应用版本信息...' end
256
+ RestClient.put "http://fir.im/api/v2/appVersion/#{id}/complete?#{URI.encode_www_form body}", body
257
+ puts '> 更新成功'
258
+ end
259
+ def opt_token
260
+ @token = options[:token] || @ipa_config['token'] || nil
261
+ end
262
+ def opt_email
263
+ @email = options[:email] || @ipa_config['email'] || nil
264
+ end
265
+ def opt_resign
266
+ @resign = options[:resign] || @ipa_config['resign'] || nil
267
+ end
268
+ end
@@ -0,0 +1,26 @@
1
+ require 'cfpropertylist'
2
+ require 'lagunitas'
3
+ module Lagunitas
4
+ class App
5
+ def name
6
+ @info['CFBundleName']
7
+ end
8
+ def mobileprovision
9
+ @mobileprovision = CFPropertyList.native_types CFPropertyList::List.new(:data => `security cms -D -i #{File.join @path, 'embedded.mobileprovision'}`).value
10
+ end
11
+ def devices
12
+ mobileprovision['ProvisionedDevices']
13
+ end
14
+ def distribution_name
15
+ mobileprovision['DeveloperCertificates']
16
+ end
17
+ def release_type
18
+ if devices == nil
19
+ 'inhouse'
20
+ else
21
+ 'adhoc'
22
+ end
23
+ end
24
+
25
+ end
26
+ end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: fir-cli
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.1
4
+ version: 0.0.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - Yan
@@ -101,6 +101,8 @@ executables:
101
101
  extensions: []
102
102
  extra_rdoc_files: []
103
103
  files:
104
+ - lib/fir-cli.rb
105
+ - lib/lagunitas.ext.rb
104
106
  - bin/fir
105
107
  homepage: https://github.com/idy/fir-cli
106
108
  licenses: