lhj-tools 0.1.0

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.
@@ -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