mirror of
https://github.com/Yuyi-Oak/BlueArchiveToolkit.git
synced 2026-09-18 06:34:54 +08:00
272 lines
12 KiB
Rust
272 lines
12 KiB
Rust
use super::*;
|
||
|
||
pub(super) fn run_readonly_query_command(options: &CliOptions) -> anyhow::Result<()> {
|
||
run_readonly_query_command_with_rpc(options, daemon_rpc_available, daemon_rpc_call)
|
||
}
|
||
|
||
pub(super) fn run_readonly_query_command_with_rpc(
|
||
options: &CliOptions,
|
||
rpc_available: impl Fn(&Path) -> bool,
|
||
rpc_call: impl Fn(&Path, &str, Option<serde_json::Value>) -> anyhow::Result<serde_json::Value>,
|
||
) -> anyhow::Result<()> {
|
||
let method = readonly_query_rpc_method(options.command)
|
||
.ok_or_else(|| anyhow::anyhow!("不是只读查询命令"))?;
|
||
if rpc_available(&options.state_dir) && !readonly_query_requires_local_config(options) {
|
||
let _control_lock = DaemonControlLock::acquire(&options.state_dir)?;
|
||
let report = rpc_call(
|
||
&options.state_dir,
|
||
method,
|
||
readonly_query_rpc_params(options),
|
||
)?;
|
||
print_json_value(options.output_format, &report)?;
|
||
return Ok(());
|
||
}
|
||
|
||
let report = build_readonly_query_report(options, method)?;
|
||
print_json_value(options.output_format, &report)
|
||
}
|
||
|
||
fn readonly_query_rpc_method(command: CliCommand) -> Option<&'static str> {
|
||
match command {
|
||
CliCommand::ParseStatus => Some(RPC_METHOD_PARSE_STATUS),
|
||
CliCommand::ParseTextUnits => Some(RPC_METHOD_PARSE_TEXT_UNITS),
|
||
CliCommand::ParseErrors => Some(RPC_METHOD_PARSE_ERRORS),
|
||
CliCommand::TranslationTasks => Some(RPC_METHOD_TRANSLATION_TASKS),
|
||
CliCommand::TranslationHandoff => Some(RPC_METHOD_TRANSLATION_HANDOFF),
|
||
CliCommand::LocalizedStatus => Some(RPC_METHOD_LOCALIZED_STATUS),
|
||
CliCommand::ResourceIndex => Some(RPC_METHOD_RESOURCE_INDEX),
|
||
_ => None,
|
||
}
|
||
}
|
||
|
||
fn readonly_query_rpc_params(options: &CliOptions) -> Option<serde_json::Value> {
|
||
let mut params = serde_json::Map::new();
|
||
match options.command {
|
||
CliCommand::ResourceIndex
|
||
| CliCommand::ParseTextUnits
|
||
| CliCommand::ParseErrors
|
||
| CliCommand::TranslationTasks => {
|
||
params.insert(
|
||
"offset".to_string(),
|
||
serde_json::json!(options.query_offset),
|
||
);
|
||
params.insert("limit".to_string(), serde_json::json!(options.query_limit));
|
||
}
|
||
_ => return None,
|
||
}
|
||
match options.command {
|
||
CliCommand::ResourceIndex => {
|
||
if let Some(resource_type) = options.query_resource_type {
|
||
params.insert(
|
||
"resource_type".to_string(),
|
||
serde_json::json!(resource_type_rpc_label(resource_type)),
|
||
);
|
||
}
|
||
if let Some(hash) = options.query_hash.as_ref() {
|
||
params.insert("hash".to_string(), serde_json::json!(hash));
|
||
}
|
||
if let Some(path_pattern) = options.query_path_pattern.as_ref() {
|
||
params.insert("path_pattern".to_string(), serde_json::json!(path_pattern));
|
||
}
|
||
if let Some(release_id) = options.query_official_release_id.as_ref() {
|
||
params.insert(
|
||
"official_release_id".to_string(),
|
||
serde_json::json!(release_id),
|
||
);
|
||
}
|
||
if let Some(platform) = options.query_platform.as_ref() {
|
||
params.insert("platform".to_string(), serde_json::json!(platform));
|
||
}
|
||
if let Some(destination) = options.query_destination.as_ref() {
|
||
params.insert("destination".to_string(), serde_json::json!(destination));
|
||
}
|
||
if let Some(bundle_path) = options.query_bundle_path.as_ref() {
|
||
params.insert("bundle_path".to_string(), serde_json::json!(bundle_path));
|
||
}
|
||
if let Some(archive_entry) = options.query_archive_entry.as_ref() {
|
||
params.insert(
|
||
"archive_entry".to_string(),
|
||
serde_json::json!(archive_entry),
|
||
);
|
||
}
|
||
if let Some(parse_status) = options.query_parse_status.as_ref() {
|
||
params.insert("parse_status".to_string(), serde_json::json!(parse_status));
|
||
}
|
||
if let Some(format) = options.query_format.as_ref() {
|
||
params.insert("text_unit_format".to_string(), serde_json::json!(format));
|
||
}
|
||
}
|
||
CliCommand::ParseTextUnits | CliCommand::ParseErrors => {
|
||
if let Some(destination) = options.query_destination.as_ref() {
|
||
params.insert("destination".to_string(), serde_json::json!(destination));
|
||
}
|
||
if let Some(path_pattern) = options.query_path_pattern.as_ref() {
|
||
params.insert("path_pattern".to_string(), serde_json::json!(path_pattern));
|
||
}
|
||
if let Some(archive_entry) = options.query_archive_entry.as_ref() {
|
||
params.insert(
|
||
"archive_entry".to_string(),
|
||
serde_json::json!(archive_entry),
|
||
);
|
||
}
|
||
if let Some(path_id) = options.query_path_id {
|
||
params.insert("path_id".to_string(), serde_json::json!(path_id));
|
||
}
|
||
if let Some(class_id) = options.query_class_id {
|
||
params.insert("class_id".to_string(), serde_json::json!(class_id));
|
||
}
|
||
if let Some(field_path) = options.query_field_path.as_ref() {
|
||
params.insert("field_path".to_string(), serde_json::json!(field_path));
|
||
}
|
||
if let Some(format) = options.query_format.as_ref() {
|
||
params.insert("format".to_string(), serde_json::json!(format));
|
||
}
|
||
}
|
||
CliCommand::TranslationTasks => {
|
||
if let Some(task_id) = options.query_task_id.as_ref() {
|
||
params.insert("task_id".to_string(), serde_json::json!(task_id));
|
||
}
|
||
if let Some(release_id) = options.query_official_release_id.as_ref() {
|
||
params.insert(
|
||
"official_release_id".to_string(),
|
||
serde_json::json!(release_id),
|
||
);
|
||
}
|
||
if let Some(destination) = options.query_destination.as_ref() {
|
||
params.insert("destination".to_string(), serde_json::json!(destination));
|
||
}
|
||
if let Some(path_pattern) = options.query_path_pattern.as_ref() {
|
||
params.insert("path_pattern".to_string(), serde_json::json!(path_pattern));
|
||
}
|
||
if let Some(archive_entry) = options.query_archive_entry.as_ref() {
|
||
params.insert(
|
||
"archive_entry".to_string(),
|
||
serde_json::json!(archive_entry),
|
||
);
|
||
}
|
||
if let Some(status) = options.query_task_status.as_ref() {
|
||
params.insert("status".to_string(), serde_json::json!(status));
|
||
}
|
||
if let Some(status) = options.query_worker_status.as_ref() {
|
||
params.insert("worker_status".to_string(), serde_json::json!(status));
|
||
}
|
||
if let Some(parse_status) = options.query_parse_status.as_ref() {
|
||
params.insert("parse_status".to_string(), serde_json::json!(parse_status));
|
||
}
|
||
if let Some(format) = options.query_format.as_ref() {
|
||
params.insert("text_unit_format".to_string(), serde_json::json!(format));
|
||
}
|
||
if let Some(has_reason) = options.query_has_reason {
|
||
params.insert("has_reason".to_string(), serde_json::json!(has_reason));
|
||
}
|
||
if let Some(has_failure_reason) = options.query_has_failure_reason {
|
||
params.insert(
|
||
"has_failure_reason".to_string(),
|
||
serde_json::json!(has_failure_reason),
|
||
);
|
||
}
|
||
}
|
||
_ => {}
|
||
}
|
||
Some(serde_json::Value::Object(params))
|
||
}
|
||
|
||
fn readonly_query_requires_local_config(options: &CliOptions) -> bool {
|
||
matches!(options.command, CliCommand::ResourceIndex)
|
||
&& options.config.import_resource_repository_path.is_some()
|
||
}
|
||
|
||
fn build_readonly_query_report(
|
||
options: &CliOptions,
|
||
method: &str,
|
||
) -> anyhow::Result<serde_json::Value> {
|
||
match method {
|
||
RPC_METHOD_PARSE_STATUS => build_parse_status_report(&options.state_dir),
|
||
RPC_METHOD_PARSE_TEXT_UNITS => build_parse_text_units_report(
|
||
&options.state_dir,
|
||
textunit_query_from_options(options),
|
||
options.query_offset,
|
||
options.query_limit,
|
||
),
|
||
RPC_METHOD_PARSE_ERRORS => build_parse_errors_report(
|
||
&options.state_dir,
|
||
textunit_query_from_options(options),
|
||
options.query_offset,
|
||
options.query_limit,
|
||
),
|
||
RPC_METHOD_TRANSLATION_TASKS => build_translation_tasks_report(
|
||
&options.state_dir,
|
||
translation_task_query_from_options(options),
|
||
options.query_offset,
|
||
options.query_limit,
|
||
),
|
||
RPC_METHOD_TRANSLATION_HANDOFF => build_translation_handoff_report(&options.state_dir),
|
||
RPC_METHOD_LOCALIZED_STATUS => {
|
||
build_localized_status_report(&options.state_dir, &options.config)
|
||
}
|
||
RPC_METHOD_RESOURCE_INDEX => build_resource_index_report(
|
||
&options.state_dir,
|
||
&options.config,
|
||
resource_index_query_from_options(options),
|
||
options.query_offset,
|
||
options.query_limit,
|
||
),
|
||
_ => Err(anyhow::anyhow!("不支持的只读查询方法:{method}")),
|
||
}
|
||
}
|
||
|
||
pub(super) fn validate_readonly_query_options(options: &CliOptions) -> anyhow::Result<()> {
|
||
let has_resource_index_only_filter = options.query_resource_type.is_some()
|
||
|| options.query_hash.is_some()
|
||
|| options.query_platform.is_some()
|
||
|| options.query_bundle_path.is_some();
|
||
let has_parse_object_filter = options.query_path_id.is_some()
|
||
|| options.query_class_id.is_some()
|
||
|| options.query_field_path.is_some();
|
||
let has_translation_task_filter = options.query_task_id.is_some()
|
||
|| options.query_task_status.is_some()
|
||
|| options.query_worker_status.is_some()
|
||
|| options.query_has_reason.is_some()
|
||
|| options.query_has_failure_reason.is_some();
|
||
|
||
match options.command {
|
||
CliCommand::ResourceIndex => {
|
||
if has_parse_object_filter || has_translation_task_filter {
|
||
return Err(anyhow::anyhow!(
|
||
"--path-id/--class-id/--field-path 只适用于 parse-text-units 或 parse-errors;--task-id/--task-status/--worker-status/--has-reason/--has-failure-reason 只适用于 translation-tasks"
|
||
));
|
||
}
|
||
}
|
||
CliCommand::ParseTextUnits | CliCommand::ParseErrors => {
|
||
if has_resource_index_only_filter
|
||
|| has_translation_task_filter
|
||
|| options.query_official_release_id.is_some()
|
||
|| options.query_parse_status.is_some()
|
||
{
|
||
return Err(anyhow::anyhow!(
|
||
"--resource-type/--hash/--release-id/--platform/--bundle-path/--parse-status 只适用于 resource-index 或 translation-tasks;--task-id/--task-status/--worker-status/--has-reason/--has-failure-reason 只适用于 translation-tasks"
|
||
));
|
||
}
|
||
}
|
||
CliCommand::TranslationTasks => {
|
||
if has_resource_index_only_filter || has_parse_object_filter {
|
||
return Err(anyhow::anyhow!(
|
||
"--resource-type/--hash/--platform/--bundle-path 只适用于 resource-index;--path-id/--class-id/--field-path 只适用于 parse-text-units 或 parse-errors"
|
||
));
|
||
}
|
||
}
|
||
CliCommand::TranslationHandoff if options.query_option_explicit => {
|
||
return Err(anyhow::anyhow!(
|
||
"translation-handoff 不接受查询过滤参数;请使用 translation-tasks 查询单项任务"
|
||
));
|
||
}
|
||
CliCommand::ParseStatus | CliCommand::LocalizedStatus if options.query_option_explicit => {
|
||
return Err(anyhow::anyhow!(
|
||
"查询过滤参数只适用于 resource-index、parse-text-units、parse-errors 或 translation-tasks"
|
||
));
|
||
}
|
||
_ => {}
|
||
}
|
||
Ok(())
|
||
}
|