Class: JPSClient::LazyClient

Inherits:
Object
  • Object
show all
Defined in:
lib/jpsclient/api/lazy_client.rb

Overview

延迟加载版本的Client 只在实际使用时才加载对应的API模块

Constant Summary collapse

CORE_MODULES =

核心模块 - 始终加载

%w[project file cert].freeze
API_MODULES =

API模块映射表

{
  app_level: 'AppLevel',
  app_resource: 'AppResource',
  app_resource_version: 'AppResourceVersion',
  apple_account: 'AppleAccount',
  application: 'Application',
  application_category: 'ApplicationCategory',
  application_design: 'ApplicationDesign',
  application_income: 'ApplicationIncome',
  application_sales: 'ApplicationSales',
  application_version: 'ApplicationVersion',
  assets_category: 'AssetsCategory',
  bug: 'Bug',
  cert: 'Cert',
  collect: 'Collect',
  collection: 'Collection',
  commit_log: 'CommitLog',
  creative: 'Creative',
  custom_application: 'CustomApplication',
  custom_application_web: 'CustomApplicationWeb',
  document_text: 'DocumentText',
  experience: 'Experience',
  experience_category: 'ExperienceCategory',
  fgui_export: 'FguiExport',
  file: 'File',
  game_assets: 'GameAssets',
  healthy: 'Healthy',
  icon_and_snapshot: 'IconAndSnapshot',
  idea: 'Idea',
  jssdk: 'Jssdk',
  lark_bitable: 'LarkBitable',
  lark_chat_group: 'LarkChatGroup',
  lark_comment: 'LarkComment',
  lark_task: 'LarkTask',
  lark_task_list: 'LarkTaskList',
  lark_task_section: 'LarkTaskSection',
  lark_user: 'LarkUser',
  lark_wiki_node: 'LarkWikiNode',
  lark_wiki_space: 'LarkWikiSpace',
  login: 'Login',
  m3u8: 'M3u8',
  menu: 'Menu',
  project: 'Project',
  project_package: 'ProjectPackage',
  publisher: 'Publisher',
  publisher_category: 'PublisherCategory',
  publisher_group: 'PublisherGroup',
  publisher_group_category: 'PublisherGroupCategory',
  requirements: 'Requirements',
  requirements_category: 'RequirementsCategory',
  resource_category: 'ResourceCategory',
  role: 'Role',
  simple_search: 'SimpleSearch',
  sketch: 'Sketch',
  sketch_category: 'SketchCategory',
  sov: 'Sov',
  statistics: 'Statistics',
  store: 'Store',
  survey: 'Survey',
  survey_category: 'SurveyCategory',
  tag: 'Tag',
  tool: 'Tool',
  tool_category: 'ToolCategory',
  trending: 'Trending',
  ud_id: 'UdId',
  user: 'User',
  util: 'Util',
  video_cover: 'VideoCover',
  webhook: 'Webhook',
  workflow: 'Workflow'
}.freeze

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(config_file:, preload_modules: nil) ⇒ LazyClient

Returns a new instance of LazyClient.



94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
# File 'lib/jpsclient/api/lazy_client.rb', line 94

def initialize(config_file:, preload_modules: nil)
  begin
    @config_file = config_file
    @loaded_modules = {}

    raise ExceptionError, "必须提供配置文件路径" unless @config_file
    raise ExceptionError, "配置文件不存在: #{@config_file}" unless File.exist?(@config_file)

    @config_json = JSON.parse(File.read(@config_file))
    @baseurl = @config_json["pgyerapps_base_url"]
    @request_config = @config_json["api_path_config"]

    # 初始化API配置管理器
    @api_config = ApiConfig.new(@config_json)

    # 从 auth_config 获取配置
    auth_config = @config_json["auth_config"]
    @pgyer_aes_key = auth_config["aes_key"]

    # 加载 JPS 登录配置
    @jps_config = LoginConfig.from_json(auth_config)

    # 初始化 token 管理器
    @token_manager = Token.new(@jps_config)

    # 尝试加载已保存的 token
    if @token_manager.load && @token_manager.loaded?
      @token = @token_manager.to_h
    end

    # 初始化共享的 HTTP 客户端
    @http_client = HttpClient.new(base_url: @baseurl)
    @http_client.update_token(@token["token"]) if @token && @token["token"]

    # 预加载核心模块
    CORE_MODULES.each { |mod| load_module(mod) }

    # 预加载用户指定的模块
    if preload_modules
      Array(preload_modules).each { |mod| load_module(mod.to_s) }
    end

  rescue JSON::ParserError => error
    raise ExceptionError.new("配置文件格式错误 (#{@config_file}): #{error.message}")
  rescue ExceptionError
    raise  # 重新抛出 JPS 异常
  rescue => error
    raise ExceptionError.new("加载配置文件失败 (#{@config_file}): #{error.message}")
  end
end

Dynamic Method Handling

This class handles dynamic methods through the method_missing method

#method_missing(method_name, *args, **kwargs, &block) ⇒ Object

重写 method_missing 来实现延迟加载



210
211
212
213
214
215
216
217
218
219
220
221
222
# File 'lib/jpsclient/api/lazy_client.rb', line 210

def method_missing(method_name, *args, **kwargs, &block)
  # 尝试根据方法名猜测模块
  module_name = guess_module_from_method(method_name)

  if module_name && load_module(module_name)
    # 模块加载成功,再次尝试调用方法
    if respond_to?(method_name)
      return send(method_name, *args, **kwargs, &block)
    end
  end

  super
end

Instance Attribute Details

#api_configObject

Returns the value of attribute api_config.



91
92
93
# File 'lib/jpsclient/api/lazy_client.rb', line 91

def api_config
  @api_config
end

#baseurlObject

Returns the value of attribute baseurl.



91
92
93
# File 'lib/jpsclient/api/lazy_client.rb', line 91

def baseurl
  @baseurl
end

#config_fileObject (readonly)

Returns the value of attribute config_file.



92
93
94
# File 'lib/jpsclient/api/lazy_client.rb', line 92

def config_file
  @config_file
end

#config_jsonObject (readonly)

Returns the value of attribute config_json.



92
93
94
# File 'lib/jpsclient/api/lazy_client.rb', line 92

def config_json
  @config_json
end

#http_clientObject

Returns the value of attribute http_client.



91
92
93
# File 'lib/jpsclient/api/lazy_client.rb', line 91

def http_client
  @http_client
end

#request_configObject

Returns the value of attribute request_config.



91
92
93
# File 'lib/jpsclient/api/lazy_client.rb', line 91

def request_config
  @request_config
end

#tokenObject

Returns the value of attribute token.



91
92
93
# File 'lib/jpsclient/api/lazy_client.rb', line 91

def token
  @token
end

Instance Method Details

#do_login(force_login: false) ⇒ Object

核心登录功能token 有效性由服务端 401 响应判断,本地不做过期检查



152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
# File 'lib/jpsclient/api/lazy_client.rb', line 152

def (force_login: false)
  if 
    @token_manager.clear
  else
    # 本地存在 token,直接使用
    if @token_manager.load && @token_manager.loaded?
      update_token_everywhere
      return true
    end
  end

  # 需要重新登录
  auth = Auth.new(@jps_config)
  result = auth.

  if result == :user_cancelled
    Logger.instance.fancyinfo_error("用户取消了登录操作")
    return false
  elsif result == true
    unless @token_manager.save(auth.get_token_data)
      Logger.instance.fancyinfo_error("Token 保存失败,下次启动需要重新登录")
    end
    update_token_everywhere
    return true
  else
    Logger.instance.fancyinfo_error("登录失败,未能获取有效token")
    return false
  end
end

#load_module(module_name) ⇒ Object

手动加载指定模块



188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
# File 'lib/jpsclient/api/lazy_client.rb', line 188

def load_module(module_name)
  module_key = module_name.to_sym
  return true if @loaded_modules[module_key]

  begin
    require "jpsclient/api/#{module_name}"
    module_class = API_MODULES[module_key]
    if module_class
      self.class.send(:include, API.const_get(module_class))
      @loaded_modules[module_key] = true
      # Logger.instance.fancyinfo_info("Loaded module: #{module_name}")
      true
    else
      false
    end
  rescue LoadError => e
    Logger.instance.fancyinfo_error("Failed to load module #{module_name}: #{e.message}")
    false
  end
end

#loaded_modulesObject

获取已加载的模块列表



183
184
185
# File 'lib/jpsclient/api/lazy_client.rb', line 183

def loaded_modules
  @loaded_modules.keys
end

#request_with_auth(method, path, **opts) ⇒ Object

带 401 重试的统一请求方法



230
231
232
233
234
235
236
237
238
239
240
241
242
# File 'lib/jpsclient/api/lazy_client.rb', line 230

def request_with_auth(method, path, **opts)
  response = @http_client.send(method, path, **opts)
  result = JPSClient::Response.new(response)

  if result.need_login?
    if (force_login: true)
      response = @http_client.send(method, path, **opts)
      result = JPSClient::Response.new(response)
    end
  end

  result.to_h
end

#respond_to_missing?(method_name, include_private = false) ⇒ Boolean

Returns:

  • (Boolean)


224
225
226
227
# File 'lib/jpsclient/api/lazy_client.rb', line 224

def respond_to_missing?(method_name, include_private = false)
  module_name = guess_module_from_method(method_name)
  module_name && API_MODULES.key?(module_name.to_sym) || super
end

#shared_http_clientObject

提供共享的HTTP客户端给其他模块



146
147
148
# File 'lib/jpsclient/api/lazy_client.rb', line 146

def shared_http_client
  @http_client
end