lhj-tools 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,303 @@
1
+ require 'net/https'
2
+ require 'uri'
3
+ require 'json'
4
+ require 'yaml'
5
+
6
+ module Lhj
7
+ class Command
8
+ class Yapi < Command
9
+ self.summary = '通过yapi接口生成请求'
10
+
11
+ def self.options
12
+ [
13
+ %w[--id api的id],
14
+ %w[--model-pre 模型的前缀],
15
+ %w[--save 保存生成文件]
16
+ ]
17
+ end
18
+
19
+ def initialize(argv)
20
+ @id = argv.option('id')
21
+ @model_pre_name = argv.option('model-pre')
22
+ @save = argv.flag?('save', false)
23
+ @http_url = ''
24
+ @http_headers = []
25
+ @data_json = {}
26
+ @models = []
27
+ @config_id = ''
28
+ @config_model_pre = 'ML'
29
+ @model_default_suffix = 'Model'
30
+ @type_trans = {}
31
+ @config_model_names = []
32
+ @model_names = []
33
+ super
34
+ end
35
+
36
+ def run
37
+ load_config
38
+ fetch_model
39
+ print_methods
40
+ save_to_file if @save
41
+ end
42
+
43
+ def test_ding
44
+ require 'net/http'
45
+ require 'uri'
46
+ body = { "msgtype" => "text", "text" => { "content" => "error:上传蒲公英超时失败!" } }.to_json
47
+ Net::HTTP.post(URI('https://oapi.dingtalk.com/robot/send?access_token=6a3519057170cdb1b7274edfe43934c84a0062ffe2c9bcced434699296a7e26e'), body, "Content-Type" => "application/json")
48
+ end
49
+
50
+ def puts_h(str)
51
+ puts str
52
+ @h_file_array ||= []
53
+ @h_file_array << str
54
+ end
55
+
56
+ def puts_m(str)
57
+ puts str
58
+ @m_file_array ||= []
59
+ @m_file_array << str
60
+ end
61
+
62
+ def save_to_file
63
+ @model_names = []
64
+ file_name = gen_model_name('')
65
+ h_file = File.join('.', "#{file_name}.h")
66
+ m_file = File.join('.', "#{file_name}.m")
67
+ File.write(h_file, @h_file_array.join("\n")) if @h_file_array.count > 0
68
+ File.write(m_file, @m_file_array.join("\n")) if @m_file_array.count > 0
69
+ puts "\n\n生成文件成功!所在路径:\n#{File.expand_path(h_file)} \n#{File.expand_path(m_file)}"
70
+ end
71
+
72
+ def url_str
73
+ "#{@http_url}#{api_id}"
74
+ end
75
+
76
+ def load_config
77
+ yml = File.join(Lhj::Config.instance.home_dir, 'yapi.yml')
78
+ config = YAML.load_file(yml)
79
+ config.each do |k, v|
80
+ @http_headers << "#{k}=#{v}" if (k.eql?('__wpkreporterwid_') || k.eql?('_yapi_token') || k.eql?('_yapi_uid'))
81
+ end
82
+ @http_url = config['url']
83
+ @config_id = config['id']
84
+ @config_model_pre = config['model_pre']
85
+ @config_model_suffix = config['model_suffix']
86
+ @config_model_names = config['model_names']
87
+ @type_trans = config['type_trans']
88
+ end
89
+
90
+ def api_id
91
+ @id || @config_id.to_s
92
+ end
93
+
94
+ def model_pre
95
+ @model_pre_name || @config_model_pre
96
+ end
97
+
98
+ def model_suffix
99
+ @config_model_suffix || @model_default_suffix
100
+ end
101
+
102
+ def req_model
103
+ uri = URI.parse(url_str)
104
+ req = Net::HTTP::Get.new(uri)
105
+ req['Cookie'] = @http_headers.join('; ')
106
+ res = Net::HTTP.start(uri.hostname, uri.port) do |http|
107
+ http.request(req)
108
+ end
109
+ puts res.body
110
+ JSON.parse(res.body)
111
+ end
112
+
113
+ def fetch_model
114
+ res_json = req_model
115
+ begin
116
+ puts "\n<===============打印返回数据模型-Begin=====================>\n"
117
+ fetch_res_boy(res_json)
118
+ print_models
119
+ print_models_implementation
120
+ puts "\n<===============打印返回数据模型-End=====================>\n"
121
+ end
122
+ begin
123
+ puts "\n<===============打印请求模型-Begin=====================>\n"
124
+ @models = []
125
+ @model_names = []
126
+ fetch_req_body(res_json)
127
+ print_models
128
+ print_models_implementation
129
+ puts "\n<===============打印请求模型-End=====================>\n"
130
+ end
131
+ end
132
+
133
+ def fetch_res_boy(res_json)
134
+ if res_json && res_json['data']
135
+ @data_json = res_json['data']
136
+ if @data_json['res_body']
137
+ begin
138
+ res_body = JSON.parse(@data_json['res_body'])
139
+ detail_obj = res_body['properties']['detailMsg'] || {}
140
+ detail_obj['name'] = gen_model_name('')
141
+ handle_model(detail_obj)
142
+ rescue => ex
143
+ puts ex
144
+ end
145
+ end
146
+ end
147
+ end
148
+
149
+ def fetch_req_body(res_json)
150
+ if res_json && res_json['data']
151
+ @data_json = res_json['data']
152
+ if @data_json['req_body_other']
153
+ begin
154
+ res_body = JSON.parse(@data_json['req_body_other'])
155
+ res_body['name'] = gen_model_name('')
156
+ handle_model(res_body)
157
+ rescue => ex
158
+ puts ex
159
+ end
160
+ end
161
+ end
162
+ end
163
+
164
+ def gen_model_name(name)
165
+ n = name.gsub(/vo|model|list/i, '').gsub(/(.*)s$/, '\1').gsub(/^\w/) { $&.upcase }
166
+ if n.length <= 0
167
+ n = @config_model_names.detect { |c| !@model_names.any? { |n| n.gsub(/#{model_pre}(.*)Model/, '\1').eql?(c) } }
168
+ end
169
+ model_name = "#{model_pre}#{n}#{model_suffix}"
170
+ @model_names << model_name
171
+ model_name
172
+ end
173
+
174
+ def handle_model(model)
175
+ p_type = model['type']
176
+ p_name = model['name']
177
+ p_properties = model['properties']
178
+ p_model = { name: p_name }
179
+
180
+ properties = []
181
+ if p_type.eql?('object')
182
+ p_properties.each do |k, v|
183
+ c_type = @type_trans[v['type']] || v['type']
184
+ c_model = { key: k, type: c_type, description: v['description'], default: '' }
185
+ if v['type'].eql?('object') || v['type'].eql?('array')
186
+ o = v['items'] || v
187
+ o['name'] = gen_model_name(k)
188
+ if v['type'].eql?('array') && v['items']['type'].eql?('string')
189
+ c_model[:type_name] = "NSString"
190
+ else
191
+ c_model[:type_name] = o['name']
192
+ handle_model(o)
193
+ end
194
+ end
195
+ properties << c_model
196
+ end
197
+ p_model[:properties] = properties
198
+ @models << p_model
199
+ elsif p_type.eql?('array')
200
+ t = model['items']
201
+ t['name'] = p_name
202
+ handle_model(t)
203
+ end
204
+ end
205
+
206
+ def print_models
207
+ @models.each do |model|
208
+ model_name = model[:name] || ''
209
+ model_properties = model[:properties]
210
+ puts_h "@interface #{model_name} : NSObject"
211
+ model_properties.each do |m|
212
+ print_model(m)
213
+ end
214
+ puts_h "@end\n\n\n"
215
+ end
216
+ end
217
+
218
+ def print_models_implementation
219
+ @models.each do |model|
220
+ puts_m "@implementation #{model[:name]}"
221
+ str = model[:properties].filter { |p| p[:type].eql?('array') && !p[:type_name].eql?('NSString') }.map { |p| "@\"#{p[:key]}\": #{p[:type_name]}.class" }.join(', ')
222
+ if str && str.length > 0
223
+ puts_m "+(NSDictionary *)modelContainerPropertyGenericClass {"
224
+ puts_m " return @{#{str}};"
225
+ puts_m "}"
226
+ end
227
+ puts_m "@end\n"
228
+ puts "\n\n"
229
+ end
230
+ end
231
+
232
+ def print_model(m)
233
+ key = m[:key]
234
+ type_name = m[:type_name]
235
+ type = m[:type]
236
+ des = m[:description] || ''
237
+ des.gsub!(/\n/, ' ')
238
+ default = m[:default]
239
+ puts_h "///#{des} #{default}"
240
+ if type.eql?('integer')
241
+ puts_h "@property (nonatomic, assign) NSInteger #{key};"
242
+ if des.include?('分')
243
+ puts_h "/////////==========删掉其中一个属性"
244
+ puts_h "@property (nonatomic, strong) MLCentNumber *#{key};"
245
+ end
246
+ elsif type.eql?('cent')
247
+ puts_h "@property (nonatomic, strong) MLCentNumber *#{key};"
248
+ elsif type.eql?('string')
249
+ puts_h "@property (nonatomic, copy) NSString *#{key};"
250
+ elsif type.eql?('number')
251
+ puts_h "@property (nonatomic, strong) NSNumber *#{key};"
252
+ elsif type.eql?('float')
253
+ puts_h "@property (nonatomic, assign) CGFloat #{key};"
254
+ elsif type.eql?('double')
255
+ puts_h "@property (nonatomic, assign) double #{key};"
256
+ elsif type.eql?('boolean')
257
+ puts_h "@property (nonatomic, assign) BOOL #{key};"
258
+ elsif type.eql?('object')
259
+ puts_h "@property (nonatomic, strong) #{type_name} *#{key};"
260
+ elsif type.eql?('array')
261
+ puts_h "@property (nonatomic, strong) NSArray<#{type_name} *> *#{key};"
262
+ else
263
+ puts_h "@property (nonatomic, copy) NSString *#{key};"
264
+ end
265
+ end
266
+
267
+ def print_methods
268
+ puts "\n<===============方法调用=====================>\n"
269
+ puts_m "/**"
270
+ puts_m " * #{@data_json['title']} -- #{@data_json['username']}"
271
+ puts_m " */"
272
+ key_str = @data_json['path'].split('/').map { |s| s.gsub(/[^A-Za-z0-9]/, '').gsub(/^\w/) { $&.upcase } }.join('')
273
+ key = "k#{key_str}URL"
274
+ puts_m "static NSString * const #{key} = @\"#{@data_json['path']}\";"
275
+ puts_m "\n\n"
276
+ puts_h "@interface MLParamModel : NSObject"
277
+ @data_json['req_query'].each do |h|
278
+ des = h['desc']
279
+ puts_h "///#{des} #{h['example']}"
280
+ puts_h "@property (nonatomic, copy) NSString *#{h['name']};"
281
+ end
282
+ puts_h "@end"
283
+ puts "\n\n"
284
+ model = @models.last
285
+ if @data_json['method'].eql?('GET')
286
+ puts_m " [MLNetworkingManager getWithUrl:#{key} params:nil response:^(MLResponseMessage *responseMessage) {"
287
+ puts_m " if (response.resultCode == 0 && !response.error){"
288
+ puts_m " NSDictionary *detailMsg = response.detailMsg"
289
+ puts_m " #{model[:name]} *model = [#{model[:name]} yy_modelWithDictionary:detailMsg];" if model
290
+ puts_m " }"
291
+ puts_m " }];"
292
+ else
293
+ puts_m " [MLNetworkingManager postWithUrl:#{key} params:nil response:^(MLResponseMessage *responseMessage) {"
294
+ puts_m " if (response.resultCode == 0 && !response.error){"
295
+ puts_m " NSDictionary *detailMsg = response.detailMsg"
296
+ puts_m " #{model[:name]} *model = [#{model[:name]} yy_modelWithDictionary:detailMsg];" if model
297
+ puts_m " }"
298
+ puts_m " }];"
299
+ end
300
+ end
301
+ end
302
+ end
303
+ end
@@ -0,0 +1,13 @@
1
+ require 'claide'
2
+
3
+ module Lhj
4
+ class Command < CLAide::Command
5
+ require 'lhj/command/view'
6
+ require 'lhj/command/rename_image'
7
+ require 'lhj/command/trans'
8
+ require 'lhj/command/yapi'
9
+
10
+ self.abstract_command = true
11
+ self.command = 'lhj'
12
+ end
13
+ end
data/lib/lhj/config.rb ADDED
@@ -0,0 +1,365 @@
1
+
2
+ module Lhj
3
+ # Stores the global configuration of CocoaPods.
4
+ #
5
+ class Config
6
+ # The default settings for the configuration.
7
+ #
8
+ # Users can specify custom settings in `~/.cocoapods/config.yaml`.
9
+ # An example of the contents of this file might look like:
10
+ #
11
+ # ---
12
+ # skip_repo_update: true
13
+ # new_version_message: false
14
+ #
15
+ DEFAULTS = {
16
+ :verbose => false,
17
+ :silent => false,
18
+ :skip_download_cache => !ENV['COCOAPODS_SKIP_CACHE'].nil?,
19
+
20
+ :new_version_message => ENV['COCOAPODS_SKIP_UPDATE_MESSAGE'].nil?,
21
+
22
+ :cache_root => Pathname.new(Dir.home) + 'Library/Caches/CocoaPods',
23
+ }
24
+
25
+ # Applies the given changes to the config for the duration of the given
26
+ # block.
27
+ #
28
+ # @param [Hash<#to_sym,Object>] changes
29
+ # the changes to merge temporarily with the current config
30
+ #
31
+ # @yield [] is called while the changes are applied
32
+ #
33
+ def with_changes(changes)
34
+ old = {}
35
+ changes.keys.each do |key|
36
+ key = key.to_sym
37
+ old[key] = send(key) if respond_to?(key)
38
+ end
39
+ configure_with(changes)
40
+ yield if block_given?
41
+ ensure
42
+ configure_with(old)
43
+ end
44
+
45
+ public
46
+
47
+ #-------------------------------------------------------------------------#
48
+
49
+ # @!group UI
50
+
51
+ # @return [Boolean] Whether CocoaPods should provide detailed output about the
52
+ # performed actions.
53
+ #
54
+ attr_accessor :verbose
55
+ alias_method :verbose?, :verbose
56
+
57
+ # @return [Boolean] Whether CocoaPods should produce not output.
58
+ #
59
+ attr_accessor :silent
60
+ alias_method :silent?, :silent
61
+
62
+ # @return [Boolean] Whether CocoaPods is allowed to run as root.
63
+ #
64
+ attr_accessor :allow_root
65
+ alias_method :allow_root?, :allow_root
66
+
67
+ # @return [Boolean] Whether a message should be printed when a new version of
68
+ # CocoaPods is available.
69
+ #
70
+ attr_accessor :new_version_message
71
+ alias_method :new_version_message?, :new_version_message
72
+
73
+ #-------------------------------------------------------------------------#
74
+
75
+ # @!group Installation
76
+
77
+ # @return [Boolean] Whether the installer should skip the download cache.
78
+ #
79
+ attr_accessor :skip_download_cache
80
+ alias_method :skip_download_cache?, :skip_download_cache
81
+
82
+ public
83
+
84
+ #-------------------------------------------------------------------------#
85
+
86
+ # @!group Cache
87
+
88
+ # @return [Pathname] The directory where CocoaPods should cache remote data
89
+ # and other expensive to compute information.
90
+ #
91
+ attr_accessor :cache_root
92
+
93
+ def cache_root
94
+ @cache_root.mkpath unless @cache_root.exist?
95
+ @cache_root
96
+ end
97
+
98
+ public
99
+
100
+ #-------------------------------------------------------------------------#
101
+
102
+ # @!group Initialization
103
+
104
+ def initialize(use_user_settings = true)
105
+ configure_with(DEFAULTS)
106
+
107
+ unless ENV['CP_HOME_DIR'].nil?
108
+ @cache_root = home_dir + 'cache'
109
+ end
110
+
111
+ if use_user_settings && user_settings_file.exist?
112
+ require 'yaml'
113
+ user_settings = YAML.load_file(user_settings_file)
114
+ configure_with(user_settings)
115
+ end
116
+
117
+ unless ENV['CP_CACHE_DIR'].nil?
118
+ @cache_root = Pathname.new(ENV['CP_CACHE_DIR']).expand_path
119
+ end
120
+ end
121
+
122
+ def verbose
123
+ @verbose && !silent
124
+ end
125
+
126
+ public
127
+
128
+ #-------------------------------------------------------------------------#
129
+
130
+ # @!group Paths
131
+
132
+ # @return [Pathname] the directory where repos, templates and configuration
133
+ # files are stored.
134
+ #
135
+ def home_dir
136
+ @home_dir ||= Pathname.new(ENV['CP_HOME_DIR'] || '~/.lhj').expand_path
137
+ end
138
+
139
+ # @return [Pathname] the directory where the CocoaPods sources are stored.
140
+ #
141
+ def repos_dir
142
+ @repos_dir ||= Pathname.new(ENV['CP_REPOS_DIR'] || (home_dir + 'repos')).expand_path
143
+ end
144
+
145
+ attr_writer :repos_dir
146
+
147
+ # @return [Source::Manager] the source manager for the spec repos in `repos_dir`
148
+ #
149
+ def sources_manager
150
+ return @sources_manager if @sources_manager && @sources_manager.repos_dir == repos_dir
151
+ @sources_manager = Source::Manager.new(repos_dir)
152
+ end
153
+
154
+ # @return [Pathname] the directory where the CocoaPods templates are stored.
155
+ #
156
+ def templates_dir
157
+ @templates_dir ||= Pathname.new(ENV['CP_TEMPLATES_DIR'] || (home_dir + 'templates')).expand_path
158
+ end
159
+
160
+ # @return [Pathname] the root of the CocoaPods installation where the
161
+ # Podfile is located.
162
+ #
163
+ def installation_root
164
+ @installation_root ||= begin
165
+ current_dir = Pathname.new(Dir.pwd.unicode_normalize(:nfkc))
166
+ current_path = current_dir
167
+ until current_path.root?
168
+ if podfile_path_in_dir(current_path)
169
+ installation_root = current_path
170
+ unless current_path == current_dir
171
+ UI.puts("[in #{current_path}]")
172
+ end
173
+ break
174
+ else
175
+ current_path = current_path.parent
176
+ end
177
+ end
178
+ installation_root || current_dir
179
+ end
180
+ end
181
+
182
+ attr_writer :installation_root
183
+ alias_method :project_root, :installation_root
184
+
185
+ # @return [Pathname] The root of the sandbox.
186
+ #
187
+ def sandbox_root
188
+ @sandbox_root ||= installation_root + 'Pods'
189
+ end
190
+
191
+ attr_writer :sandbox_root
192
+ alias_method :project_pods_root, :sandbox_root
193
+
194
+ # @return [Sandbox] The sandbox of the current project.
195
+ #
196
+ def sandbox
197
+ @sandbox ||= Sandbox.new(sandbox_root)
198
+ end
199
+
200
+ # @return [Podfile] The Podfile to use for the current execution.
201
+ # @return [Nil] If no Podfile is available.
202
+ #
203
+ def podfile
204
+ @podfile ||= Podfile.from_file(podfile_path) if podfile_path
205
+ end
206
+ attr_writer :podfile
207
+
208
+ # @return [Lockfile] The Lockfile to use for the current execution.
209
+ # @return [Nil] If no Lockfile is available.
210
+ #
211
+ def lockfile
212
+ @lockfile ||= Lockfile.from_file(lockfile_path) if lockfile_path
213
+ end
214
+
215
+ # Returns the path of the Podfile.
216
+ #
217
+ # @note The Podfile can be named either `CocoaPods.podfile.yaml`,
218
+ # `CocoaPods.podfile` or `Podfile`. The first two are preferred as
219
+ # they allow to specify an OS X UTI.
220
+ #
221
+ # @return [Pathname]
222
+ # @return [Nil]
223
+ #
224
+ def podfile_path
225
+ @podfile_path ||= podfile_path_in_dir(installation_root)
226
+ end
227
+
228
+ # Returns the path of the Lockfile.
229
+ #
230
+ # @note The Lockfile is named `Podfile.lock`.
231
+ #
232
+ def lockfile_path
233
+ @lockfile_path ||= installation_root + 'Podfile.lock'
234
+ end
235
+
236
+ # Returns the path of the default Podfile pods.
237
+ #
238
+ # @note The file is expected to be named Podfile.default
239
+ #
240
+ # @return [Pathname]
241
+ #
242
+ def default_podfile_path
243
+ @default_podfile_path ||= templates_dir + 'Podfile.default'
244
+ end
245
+
246
+ # Returns the path of the default Podfile test pods.
247
+ #
248
+ # @note The file is expected to be named Podfile.test
249
+ #
250
+ # @return [Pathname]
251
+ #
252
+ def default_test_podfile_path
253
+ @default_test_podfile_path ||= templates_dir + 'Podfile.test'
254
+ end
255
+
256
+ # @return [Pathname] The file to use to cache the search data.
257
+ #
258
+ def search_index_file
259
+ cache_root + 'search_index.json'
260
+ end
261
+
262
+ private
263
+
264
+ #-------------------------------------------------------------------------#
265
+
266
+ # @!group Private helpers
267
+
268
+ # @return [Pathname] The path of the file which contains the user settings.
269
+ #
270
+ def user_settings_file
271
+ home_dir + 'config.yaml'
272
+ end
273
+
274
+ # Sets the values of the attributes with the given hash.
275
+ #
276
+ # @param [Hash{String,Symbol => Object}] values_by_key
277
+ # The values of the attributes grouped by key.
278
+ #
279
+ # @return [void]
280
+ #
281
+ def configure_with(values_by_key)
282
+ return unless values_by_key
283
+ values_by_key.each do |key, value|
284
+ if key.to_sym == :cache_root
285
+ value = Pathname.new(value).expand_path
286
+ end
287
+ instance_variable_set("@#{key}", value)
288
+ end
289
+ end
290
+
291
+ # @return [Array<String>] The filenames that the Podfile can have ordered
292
+ # by priority.
293
+ #
294
+ PODFILE_NAMES = [
295
+ 'CocoaPods.podfile.yaml',
296
+ 'CocoaPods.podfile',
297
+ 'Podfile',
298
+ 'Podfile.rb',
299
+ ].freeze
300
+
301
+ public
302
+
303
+ # Returns the path of the Podfile in the given dir if any exists.
304
+ #
305
+ # @param [Pathname] dir
306
+ # The directory where to look for the Podfile.
307
+ #
308
+ # @return [Pathname] The path of the Podfile.
309
+ # @return [Nil] If not Podfile was found in the given dir
310
+ #
311
+ def podfile_path_in_dir(dir)
312
+ PODFILE_NAMES.each do |filename|
313
+ candidate = dir + filename
314
+ if candidate.file?
315
+ return candidate
316
+ end
317
+ end
318
+ nil
319
+ end
320
+
321
+ # Excludes the given dir from Time Machine backups.
322
+ #
323
+ # @param [Pathname] dir
324
+ # The directory to exclude from Time Machine backups.
325
+ #
326
+ # @return [void]
327
+ #
328
+ def exclude_from_backup(dir)
329
+ return if Gem.win_platform?
330
+ system('tmutil', 'addexclusion', dir.to_s, %i(out err) => File::NULL)
331
+ end
332
+
333
+ public
334
+
335
+ #-------------------------------------------------------------------------#
336
+
337
+ # @!group Singleton
338
+
339
+ # @return [Config] the current config instance creating one if needed.
340
+ #
341
+ def self.instance
342
+ @instance ||= new
343
+ end
344
+
345
+ # Sets the current config instance. If set to nil the config will be
346
+ # recreated when needed.
347
+ #
348
+ # @param [Config, Nil] the instance.
349
+ #
350
+ # @return [void]
351
+ #
352
+ class << self
353
+ attr_writer :instance
354
+ end
355
+
356
+ # Provides support for accessing the configuration instance in other
357
+ # scopes.
358
+ #
359
+ module Mixin
360
+ def config
361
+ Config.instance
362
+ end
363
+ end
364
+ end
365
+ end
@@ -0,0 +1,7 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Lhj
4
+ module Tools
5
+ VERSION = "0.1.0"
6
+ end
7
+ end
data/lib/lhj/tools.rb ADDED
@@ -0,0 +1,11 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "tools/version"
4
+
5
+ module Lhj
6
+ require 'lhj/config'
7
+ class Error < StandardError; end
8
+
9
+ autoload :Command, 'lhj/command'
10
+
11
+ end