mirror of
https://github.com/Yuyi-Oak/BlueArchiveToolkit.git
synced 2026-09-18 06:34:54 +08:00
233 lines
9.4 KiB
Rust
233 lines
9.4 KiB
Rust
use super::*;
|
|
|
|
pub(super) fn build_translation_tasks_report(
|
|
state_dir: &Path,
|
|
query: OfficialTextUnitTaskQuery,
|
|
offset: usize,
|
|
limit: usize,
|
|
) -> anyhow::Result<serde_json::Value> {
|
|
let (_, version_state) = read_daemon_resource_state(state_dir)?;
|
|
let current = version_state
|
|
.as_ref()
|
|
.and_then(|state| state.current_completed_version.as_ref());
|
|
let Some(record) = current else {
|
|
return Ok(serde_json::json!({ "available": false }));
|
|
};
|
|
let task_queue_path = record
|
|
.resource_root
|
|
.join(bat_infrastructure::OFFICIAL_TEXTUNIT_TASK_QUEUE_FILE);
|
|
let task_repository_path =
|
|
SqliteTranslationTaskRepository::repository_path(&record.resource_root);
|
|
let Some(queue) = bat_infrastructure::read_textunit_task_queue_at(&record.resource_root)
|
|
.map_err(anyhow::Error::msg)?
|
|
else {
|
|
return Ok(serde_json::json!({
|
|
"available": false,
|
|
"current_version_id": record.id,
|
|
"resource_root": record.resource_root,
|
|
"textunit_task_queue_path": task_queue_path,
|
|
"task_repository_path": task_repository_path,
|
|
"task_repository_available": false,
|
|
}));
|
|
};
|
|
let task_repository_available =
|
|
sqlite_file_exists_no_symlink(&task_repository_path, "翻译任务状态数据库")?;
|
|
let (total_entries, entries) = if task_repository_available {
|
|
query_translation_task_repository(&task_repository_path, &query, offset, limit)?
|
|
} else {
|
|
let mut queue_query = query.clone();
|
|
queue_query.task_status = None;
|
|
queue_query.has_failure_reason = None;
|
|
let matches = bat_infrastructure::query_textunit_tasks(&queue, &queue_query);
|
|
let persisted = matches
|
|
.into_iter()
|
|
.cloned()
|
|
.map(|task| {
|
|
bat_infrastructure::PersistedTranslationTask::from_queued_task(
|
|
task,
|
|
queue.generated_unix_seconds,
|
|
)
|
|
})
|
|
.filter(|task| {
|
|
query
|
|
.task_status
|
|
.as_ref()
|
|
.is_none_or(|status| task.task_status.as_str() == status)
|
|
})
|
|
.filter(|task| {
|
|
query
|
|
.has_failure_reason
|
|
.is_none_or(|has_reason| task.failure_reason.is_some() == has_reason)
|
|
})
|
|
.collect::<Vec<_>>();
|
|
let total_entries = persisted.len();
|
|
let entries = persisted
|
|
.into_iter()
|
|
.skip(offset)
|
|
.take(limit)
|
|
.collect::<Vec<_>>();
|
|
(total_entries as u64, entries)
|
|
};
|
|
Ok(serde_json::json!({
|
|
"available": true,
|
|
"current_version_id": record.id,
|
|
"resource_root": record.resource_root,
|
|
"textunit_task_queue_path": task_queue_path,
|
|
"task_repository_path": task_repository_path,
|
|
"task_repository_available": task_repository_available,
|
|
"task_repository_schema_version": bat_infrastructure::TRANSLATION_TASK_SCHEMA_VERSION,
|
|
"summary": queue.summary,
|
|
"total_entries": total_entries,
|
|
"offset": offset,
|
|
"limit": limit,
|
|
"query": translation_task_query_json(&query),
|
|
"entries": entries,
|
|
}))
|
|
}
|
|
|
|
pub(super) fn build_translation_handoff_report(
|
|
state_dir: &Path,
|
|
) -> anyhow::Result<serde_json::Value> {
|
|
let (_, version_state) = read_daemon_resource_state(state_dir)?;
|
|
let current = version_state
|
|
.as_ref()
|
|
.and_then(|state| state.current_completed_version.as_ref());
|
|
let Some(record) = current else {
|
|
return Ok(serde_json::json!({ "available": false }));
|
|
};
|
|
let resource_root = &record.resource_root;
|
|
let task_queue_path = resource_root.join(bat_infrastructure::OFFICIAL_TEXTUNIT_TASK_QUEUE_FILE);
|
|
let handoff_path = resource_root.join(bat_infrastructure::TRANSLATION_HANDOFF_FILE);
|
|
let repository_path = SqliteTranslationTaskRepository::repository_path(resource_root);
|
|
let Some(queue) = bat_infrastructure::read_textunit_task_queue_at(resource_root)
|
|
.map_err(anyhow::Error::msg)?
|
|
else {
|
|
return Ok(serde_json::json!({
|
|
"available": false,
|
|
"current_version_id": record.id,
|
|
"resource_root": resource_root,
|
|
"textunit_task_queue_path": task_queue_path,
|
|
"translation_handoff_path": handoff_path,
|
|
"task_repository_path": repository_path,
|
|
}));
|
|
};
|
|
let task_repository_available =
|
|
sqlite_file_exists_no_symlink(&repository_path, "翻译任务状态数据库")?;
|
|
let tasks = if task_repository_available {
|
|
let runtime = tokio::runtime::Builder::new_current_thread()
|
|
.enable_all()
|
|
.build()?;
|
|
runtime.block_on(async {
|
|
let repository = SqliteTranslationTaskRepository::open(&repository_path)
|
|
.await
|
|
.map_err(|error| anyhow::anyhow!("{error}"))?;
|
|
repository
|
|
.list(&OfficialTextUnitTaskQuery::default())
|
|
.await
|
|
.map_err(|error| anyhow::anyhow!("{error}"))
|
|
})?
|
|
} else {
|
|
queue
|
|
.tasks
|
|
.iter()
|
|
.cloned()
|
|
.map(|task| {
|
|
bat_infrastructure::PersistedTranslationTask::from_queued_task(
|
|
task,
|
|
queue.generated_unix_seconds,
|
|
)
|
|
})
|
|
.collect::<Vec<_>>()
|
|
};
|
|
let handoff = bat_infrastructure::build_translation_handoff(&queue, &tasks);
|
|
let handoff_file_available = sqlite_file_exists_no_symlink(&handoff_path, "翻译 handoff")?;
|
|
Ok(serde_json::json!({
|
|
"available": true,
|
|
"current_version_id": record.id,
|
|
"resource_root": resource_root,
|
|
"textunit_task_queue_path": task_queue_path,
|
|
"translation_handoff_path": handoff_path,
|
|
"translation_handoff_file_available": handoff_file_available,
|
|
"task_repository_path": repository_path,
|
|
"task_repository_available": task_repository_available,
|
|
"task_repository_schema_version": bat_infrastructure::TRANSLATION_TASK_SCHEMA_VERSION,
|
|
"handoff_schema_version": bat_infrastructure::TRANSLATION_HANDOFF_SCHEMA_VERSION,
|
|
"handoff": handoff,
|
|
}))
|
|
}
|
|
|
|
pub(super) fn update_translation_task_status_report(
|
|
state_dir: &Path,
|
|
params: Option<&serde_json::Value>,
|
|
) -> anyhow::Result<serde_json::Value> {
|
|
let task_id = rpc_string_param(params, "task_id")
|
|
.ok_or_else(|| anyhow::anyhow!("translation.task.update 缺少 task_id"))?;
|
|
let status_label = rpc_string_param(params, "status")
|
|
.ok_or_else(|| anyhow::anyhow!("translation.task.update 缺少 status"))?;
|
|
let status = TranslationTaskStatus::parse(status_label)
|
|
.ok_or_else(|| anyhow::anyhow!("不支持的翻译任务 worker 状态:{status_label}"))?;
|
|
let failure_reason = rpc_string_param(params, "failure_reason")
|
|
.or_else(|| rpc_string_param(params, "reason"))
|
|
.map(str::to_string);
|
|
let provider_run_id = rpc_string_param(params, "provider_run_id").map(str::to_string);
|
|
let (_, version_state) = read_daemon_resource_state(state_dir)?;
|
|
let current = version_state
|
|
.as_ref()
|
|
.and_then(|state| state.current_completed_version.as_ref())
|
|
.ok_or_else(|| anyhow::anyhow!("没有可更新翻译任务的当前官方 release"))?;
|
|
let repository_path = SqliteTranslationTaskRepository::repository_path(¤t.resource_root);
|
|
if !sqlite_file_exists_no_symlink(&repository_path, "翻译任务状态数据库")? {
|
|
return Err(anyhow::anyhow!(
|
|
"翻译任务状态数据库不存在:{}",
|
|
repository_path.display()
|
|
));
|
|
}
|
|
|
|
let runtime = tokio::runtime::Builder::new_current_thread()
|
|
.enable_all()
|
|
.build()?;
|
|
let task = runtime.block_on(async {
|
|
let repository = SqliteTranslationTaskRepository::open(&repository_path)
|
|
.await
|
|
.map_err(|error| anyhow::anyhow!("{error}"))?;
|
|
repository
|
|
.update_status(task_id, status, failure_reason, provider_run_id)
|
|
.await
|
|
.map_err(|error| anyhow::anyhow!("{error}"))
|
|
})?;
|
|
Ok(serde_json::json!({
|
|
"available": true,
|
|
"current_version_id": current.id,
|
|
"task_repository_path": repository_path,
|
|
"entry": task,
|
|
}))
|
|
}
|
|
|
|
pub(super) fn textunit_query_json(query: &OfficialTextUnitQuery) -> serde_json::Value {
|
|
serde_json::json!({
|
|
"destination": query.destination.clone(),
|
|
"path_pattern": query.path_pattern.clone(),
|
|
"archive_entry": query.archive_entry.clone(),
|
|
"path_id": query.path_id,
|
|
"class_id": query.class_id,
|
|
"field_path": query.field_path.clone(),
|
|
"format": query.format.clone(),
|
|
})
|
|
}
|
|
|
|
pub(super) fn translation_task_query_json(query: &OfficialTextUnitTaskQuery) -> serde_json::Value {
|
|
serde_json::json!({
|
|
"task_id": query.task_id.clone(),
|
|
"official_release_id": query.official_release_id.clone(),
|
|
"destination": query.destination.clone(),
|
|
"path_pattern": query.path_pattern.clone(),
|
|
"archive_entry": query.archive_entry.clone(),
|
|
"status": query.status.clone(),
|
|
"task_status": query.task_status.clone(),
|
|
"parse_status": query.parse_status.clone(),
|
|
"text_unit_format": query.text_unit_format.clone(),
|
|
"has_reason": query.has_reason,
|
|
"has_failure_reason": query.has_failure_reason,
|
|
})
|
|
}
|