Compare commits

...
Author SHA1 Message Date
Brandon Thomas 5c3138d70f refactor job 2026-03-10 17:05:39 -04:00
Brandon Thomas bf188682ba start building cli tool 2026-03-10 16:55:08 -04:00
12 changed files with 205 additions and 20 deletions
+1
View File
@@ -6,6 +6,7 @@
.env-elasticsearch-secrets
.env-migration-tool-secrets
.env-secrets
.env-support-tool-secrets
_develop/tools/.secrets
_develop/tools/db_secrets.toml
crates/service/web/storyteller_web/config/storyteller-web.development-secrets.env
Generated
+34 -20
View File
@@ -578,9 +578,9 @@ dependencies = [
[[package]]
name = "anstyle"
version = "1.0.7"
version = "1.0.13"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "038dfcf04a5feb68e9c60b21c9625a54c2c0616e79b72b0fd87075a056ae1d1b"
checksum = "5192cca8006f1fd4f7237516f40fa183bb07f8fbdfedaa0036de5ea9b0b45e78"
[[package]]
name = "anstyle-parse"
@@ -2225,9 +2225,9 @@ dependencies = [
[[package]]
name = "clap"
version = "4.5.13"
version = "4.5.60"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0fbb260a053428790f3de475e304ff84cdbc4face759ea7a3e64c1edd938a7fc"
checksum = "2797f34da339ce31042b27d23607e051786132987f595b02ba4f6a6dffb7030a"
dependencies = [
"clap_builder",
"clap_derive",
@@ -2235,21 +2235,21 @@ dependencies = [
[[package]]
name = "clap_builder"
version = "4.5.13"
version = "4.5.60"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "64b17d7ea74e9f833c7dbf2cbe4fb12ff26783eda4782a8975b72f895c9b4d99"
checksum = "24a241312cea5059b13574bb9b3861cabf758b879c15190b37b6d6fd63ab6876"
dependencies = [
"anstream",
"anstyle",
"clap_lex 0.7.4",
"clap_lex 1.0.0",
"strsim 0.11.1",
]
[[package]]
name = "clap_derive"
version = "4.5.13"
version = "4.5.55"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "501d359d5f3dcaf6ecdeee48833ae73ec6e42723a1e52419c79abf9507eec0a0"
checksum = "a92793da1a46a5f2a02a6f4c46c6496b28c43638adea8306fcb0caa1634f24e5"
dependencies = [
"heck 0.5.0",
"proc-macro2",
@@ -2268,9 +2268,9 @@ dependencies = [
[[package]]
name = "clap_lex"
version = "0.7.4"
version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f46ad14479a25103f283c0f10005961cf086d8dc42205bb44c46ac563475dca6"
checksum = "3a822ea5bc7590f9d40f1ba12c0dc3c2760f3482c6984db1573ad11031420831"
[[package]]
name = "cloud_storage"
@@ -3068,7 +3068,7 @@ version = "0.0.1"
dependencies = [
"anyhow",
"chrono",
"clap 4.5.13",
"clap 4.5.60",
"datetimes",
"dotenv",
"easyenv",
@@ -3103,7 +3103,7 @@ name = "db-cleanup"
version = "0.0.1"
dependencies = [
"bucket_paths",
"clap 4.5.13",
"clap 4.5.60",
"dotenv",
"easyenv",
"enums",
@@ -3263,7 +3263,7 @@ name = "dev-database-seed"
version = "0.0.1"
dependencies = [
"bucket_paths",
"clap 4.5.13",
"clap 4.5.60",
"cloud_storage",
"config",
"easyenv",
@@ -3289,7 +3289,7 @@ name = "dev-upload-media-file"
version = "0.0.1"
dependencies = [
"bucket_paths",
"clap 4.5.13",
"clap 4.5.60",
"cloud_storage",
"config",
"easyenv",
@@ -3763,7 +3763,7 @@ name = "elasticsearch-cli"
version = "0.0.1"
dependencies = [
"bucket_paths",
"clap 4.5.13",
"clap 4.5.60",
"config",
"easyenv",
"elasticsearch",
@@ -6744,7 +6744,7 @@ dependencies = [
name = "lru-delete-models"
version = "0.0.1"
dependencies = [
"clap 4.5.13",
"clap 4.5.60",
"errors",
"logging",
"walkdir",
@@ -7054,7 +7054,7 @@ name = "migration-tool"
version = "0.0.1"
dependencies = [
"bucket_paths",
"clap 4.5.13",
"clap 4.5.60",
"cloud_storage",
"config",
"easyenv",
@@ -10316,7 +10316,7 @@ checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49"
name = "scrape-test"
version = "0.0.1"
dependencies = [
"clap 4.5.13",
"clap 4.5.60",
"errors",
"tokio",
"web_scrapers",
@@ -11749,6 +11749,20 @@ dependencies = [
"rsa",
]
[[package]]
name = "support-tool"
version = "0.0.1"
dependencies = [
"anyhow",
"clap 4.5.60",
"easyenv",
"errors",
"log",
"seedance2pro",
"serde_json",
"tokio",
]
[[package]]
name = "swift-rs"
version = "1.0.7"
@@ -14914,7 +14928,7 @@ dependencies = [
"bytes",
"cc",
"chrono",
"clap 4.5.13",
"clap 4.5.60",
"cookie 0.18.1",
"core-foundation-sys",
"crossbeam-utils",
+3
View File
@@ -33,6 +33,7 @@ members = [
"crates/cli/production/kubectl-pod-cleanup",
"crates/cli/production/lru-delete-models",
"crates/cli/production/migration-tool",
"crates/cli/production/support-tool",
# Desktop apps
"crates/desktop/artcraft",
@@ -222,6 +223,7 @@ component_traits = { path = "crates/service/plugins/component_traits" }
cookie_store = { path = "crates/lib/cookie_store" }
cookies = { path = "crates/lib/cookies" }
crockford = { path = "crates/lib/data/crockford" }
easyenv = { path = "crates/lib/easyenv" }
enums = { path = "crates/schema/public/enums" }
enums_public = { path = "crates/schema/public/enums_public" }
errors = { path = "crates/lib/errors" }
@@ -271,6 +273,7 @@ base64 = "0.22.1"
bstr = "1.12.1"
bytes = "1.10.1"
chrono = { version = "0.4.41", features = ["serde"] }
clap = { version = "4.5.60", features = ["derive"] }
cookie = "0.18.1"
env = "1.0.1"
env_logger = "0.11.9"
@@ -0,0 +1,22 @@
[package]
name = "support-tool"
edition = "2024"
version = "0.0.1"
[[bin]]
name = "support-tool"
path = "src/main.rs"
[dependencies]
easyenv.workspace = true
# Internal
errors.workspace = true
seedance2pro.workspace = true
# External
anyhow.workspace = true
clap.workspace = true
log.workspace = true
serde_json.workspace = true
tokio.workspace = true
@@ -0,0 +1,27 @@
pub mod seedance2pro;
use clap::{Parser, Subcommand};
#[derive(Parser)]
#[command(name = "support-tool", about = "Production support CLI")]
pub struct Cli {
#[command(subcommand)]
pub command: TopLevelCommand,
}
#[derive(Subcommand)]
pub enum TopLevelCommand {
/// Seedance2 Pro support commands
Seedance2pro {
#[command(subcommand)]
command: seedance2pro::Seedance2proCommand,
},
}
pub async fn run(cli: Cli) -> anyhow::Result<()> {
match cli.command {
TopLevelCommand::Seedance2pro { command } => {
seedance2pro::run(command).await
}
}
}
@@ -0,0 +1,22 @@
use anyhow::anyhow;
use clap::Subcommand;
use super::state::Seedance2ProState;
use super::subcommands;
#[derive(Subcommand)]
pub enum Seedance2proCommand {
/// Find a job by its order ID across all pages
Findjob(subcommands::findjob::FindjobArgs),
}
pub async fn run(command: Seedance2proCommand) -> anyhow::Result<()> {
let cookies = easyenv::get_env_string_required("SEEDANCE2PRO_COOKIES")
.map_err(|err| anyhow!("Missing SEEDANCE2PRO_COOKIES env var: {:?}", err))?;
let state = Seedance2ProState { cookies };
match command {
Seedance2proCommand::Findjob(args) => subcommands::findjob::run(&state, args).await,
}
}
@@ -0,0 +1,6 @@
mod dispatch;
mod state;
mod subcommands;
pub use dispatch::Seedance2proCommand;
pub use dispatch::run;
@@ -0,0 +1,3 @@
pub struct Seedance2ProState {
pub cookies: String,
}
@@ -0,0 +1,66 @@
use anyhow::anyhow;
use clap::Args;
use log::info;
use seedance2pro::creds::seedance2pro_session::Seedance2ProSession;
use seedance2pro::requests::poll_orders::poll_orders::{poll_orders, PollOrdersArgs};
use super::super::state::Seedance2ProState;
#[derive(Args)]
pub struct FindjobArgs {
/// The order ID (job token) to search for
#[arg(long)]
pub token: String,
}
pub async fn run(state: &Seedance2ProState, args: FindjobArgs) -> anyhow::Result<()> {
let session = Seedance2ProSession::from_cookies_string(state.cookies.clone());
let mut cursor: Option<u64> = None;
let mut page = 0usize;
loop {
page += 1;
info!("Fetching page {} (cursor: {:?})...", page, cursor);
let result = poll_orders(PollOrdersArgs {
session: &session,
cursor,
}).await
.map_err(|err| anyhow!("Error polling orders on page {}: {:?}", page, err))?;
for order in &result.orders {
if order.order_id == args.token {
println!("{}", serde_json::to_string_pretty(&order_to_json(order))?);
return Ok(());
}
}
info!("Page {}: checked {} orders, no match.", page, result.orders.len());
cursor = result.next_cursor;
if cursor.is_none() {
break;
}
}
eprintln!("Order '{}' not found after {} pages.", args.token, page);
std::process::exit(1);
}
fn order_to_json(order: &seedance2pro::requests::poll_orders::poll_orders::OrderStatus) -> serde_json::Value {
serde_json::json!({
"order_id": order.order_id,
"task_status": format!("{:?}", order.task_status),
"result_url": order.result_url,
"fail_reason": order.fail_reason,
"created_at": order.created_at,
"results": order.results.iter().map(|r| {
serde_json::json!({
"url": r.url,
"width": r.width,
"height": r.height,
})
}).collect::<Vec<_>>(),
})
}
@@ -0,0 +1 @@
pub mod findjob;
@@ -0,0 +1,19 @@
mod commands;
mod utils;
use clap::Parser;
use commands::Cli;
#[tokio::main]
async fn main() -> anyhow::Result<()> {
// Parse CLI args first so --help works without the env file.
let cli = Cli::parse();
// Load secrets from .env file.
easyenv::from_filename(".env-support-tool-secrets")
.expect("Failed to load .env-support-tool-secrets");
easyenv::init_env_logger(Some("info"));
commands::run(cli).await
}
@@ -0,0 +1 @@
// Shared utilities for support-tool commands.