mirror of
https://github.com/storytold/artcraft.git
synced 2026-11-03 14:53:45 +00:00
Seedance Pro client
This commit is contained in:
@@ -0,0 +1,31 @@
|
||||
[package]
|
||||
name = "seedance2pro"
|
||||
edition = "2024"
|
||||
version = "0.0.1"
|
||||
publish = false
|
||||
|
||||
[package.metadata.cargo-udeps.ignore]
|
||||
normal = ["workspace-build-acceleration"]
|
||||
|
||||
[lib]
|
||||
name = "seedance2pro"
|
||||
path = "src/lib.rs"
|
||||
|
||||
[dependencies]
|
||||
# Workspace hack (faster compile times)
|
||||
workspace-build-acceleration.workspace = true
|
||||
|
||||
# Internal
|
||||
errors.workspace = true
|
||||
|
||||
# External
|
||||
cloudflare_errors.workspace = true
|
||||
log.workspace = true
|
||||
serde.workspace = true
|
||||
serde_json.workspace = true
|
||||
wreq.workspace = true
|
||||
wreq-util.workspace = true
|
||||
url.workspace = true
|
||||
|
||||
[dev-dependencies]
|
||||
testing = { path = "../../lib/testing" }
|
||||
@@ -0,0 +1,2 @@
|
||||
pub mod seedance2pro_cookies;
|
||||
pub mod seedance2pro_session;
|
||||
@@ -0,0 +1,24 @@
|
||||
/// Cookies are the credential required to interact with the Seedance2 Pro API.
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct Seedance2ProCookies {
|
||||
cookies: String,
|
||||
}
|
||||
|
||||
impl Seedance2ProCookies {
|
||||
pub fn new(cookies: String) -> Self {
|
||||
Seedance2ProCookies { cookies }
|
||||
}
|
||||
|
||||
pub fn as_str(&self) -> &str {
|
||||
&self.cookies
|
||||
}
|
||||
|
||||
pub fn as_bytes(&self) -> &[u8] {
|
||||
self.cookies.as_bytes()
|
||||
}
|
||||
|
||||
pub fn to_string(&self) -> String {
|
||||
self.cookies.clone()
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
use crate::creds::seedance2pro_cookies::Seedance2ProCookies;
|
||||
|
||||
/// Holds the full session data needed to make authenticated requests to Seedance2 Pro.
|
||||
#[derive(Clone)]
|
||||
pub struct Seedance2ProSession {
|
||||
pub cookies: Seedance2ProCookies,
|
||||
}
|
||||
|
||||
impl Seedance2ProSession {
|
||||
pub fn new(cookies: Seedance2ProCookies) -> Self {
|
||||
Seedance2ProSession { cookies }
|
||||
}
|
||||
|
||||
pub fn from_cookies_string(cookies: String) -> Self {
|
||||
Seedance2ProSession {
|
||||
cookies: Seedance2ProCookies::new(cookies),
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,4 @@
|
||||
pub mod seedance2pro_client_error;
|
||||
pub mod seedance2pro_error;
|
||||
pub mod seedance2pro_generic_api_error;
|
||||
pub mod seedance2pro_specific_api_error;
|
||||
@@ -0,0 +1,22 @@
|
||||
use std::error::Error;
|
||||
use std::fmt::{Display, Formatter};
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum Seedance2ProClientError {
|
||||
/// No cookies are present in the session.
|
||||
NoCookiesPresent,
|
||||
|
||||
/// An error was encountered in building the Wreq client.
|
||||
WreqClientError(wreq::Error),
|
||||
}
|
||||
|
||||
impl Error for Seedance2ProClientError {}
|
||||
|
||||
impl Display for Seedance2ProClientError {
|
||||
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
|
||||
match self {
|
||||
Self::NoCookiesPresent => write!(f, "No cookies present in the session."),
|
||||
Self::WreqClientError(err) => write!(f, "Wreq client error (during client creation): {}", err),
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,54 @@
|
||||
use crate::error::seedance2pro_client_error::Seedance2ProClientError;
|
||||
use crate::error::seedance2pro_generic_api_error::Seedance2ProGenericApiError;
|
||||
use crate::error::seedance2pro_specific_api_error::Seedance2ProSpecificApiError;
|
||||
use cloudflare_errors::cloudflare_error::CloudflareError;
|
||||
use std::error::Error;
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum Seedance2ProError {
|
||||
Client(Seedance2ProClientError),
|
||||
ApiSpecific(Seedance2ProSpecificApiError),
|
||||
ApiGeneric(Seedance2ProGenericApiError),
|
||||
}
|
||||
|
||||
impl Seedance2ProError {
|
||||
pub fn is_having_downtime_issues(&self) -> bool {
|
||||
match self {
|
||||
Self::ApiGeneric(Seedance2ProGenericApiError::Http502ErrorBadGateway(_)) => true,
|
||||
Self::ApiGeneric(Seedance2ProGenericApiError::CloudflareError(CloudflareError::BadGateway502)) => true,
|
||||
Self::ApiGeneric(Seedance2ProGenericApiError::CloudflareError(CloudflareError::GatewayTimeout504)) => true,
|
||||
Self::ApiGeneric(Seedance2ProGenericApiError::CloudflareError(CloudflareError::TimeoutOccurred524)) => true,
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Error for Seedance2ProError {}
|
||||
|
||||
impl std::fmt::Display for Seedance2ProError {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
match self {
|
||||
Self::Client(e) => write!(f, "Seedance2ProClientError: {:?}", e),
|
||||
Self::ApiSpecific(e) => write!(f, "Seedance2ProSpecificApiError: {:?}", e),
|
||||
Self::ApiGeneric(e) => write!(f, "Seedance2ProGenericApiError: {:?}", e),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<Seedance2ProClientError> for Seedance2ProError {
|
||||
fn from(error: Seedance2ProClientError) -> Self {
|
||||
Self::Client(error)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<Seedance2ProSpecificApiError> for Seedance2ProError {
|
||||
fn from(error: Seedance2ProSpecificApiError) -> Self {
|
||||
Self::ApiSpecific(error)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<Seedance2ProGenericApiError> for Seedance2ProError {
|
||||
fn from(error: Seedance2ProGenericApiError) -> Self {
|
||||
Self::ApiGeneric(error)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,50 @@
|
||||
use cloudflare_errors::cloudflare_error::CloudflareError;
|
||||
use std::error::Error;
|
||||
use std::fmt::{Display, Formatter};
|
||||
use wreq::StatusCode;
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum Seedance2ProGenericApiError {
|
||||
/// Specific Cloudflare errors.
|
||||
CloudflareError(CloudflareError),
|
||||
|
||||
/// HTTP 502 Bad Gateway.
|
||||
/// We preserve the message for debugging.
|
||||
Http502ErrorBadGateway(String),
|
||||
|
||||
/// serde_json::Error, likely from JSON deserialization schema mismatch.
|
||||
/// Includes the original body.
|
||||
SerdeResponseParseErrorWithBody(serde_json::Error, String),
|
||||
|
||||
/// serde_json::Error on a non-200 (error) response.
|
||||
/// Includes the original body.
|
||||
SerdeParseErrorWithBodyOnNon200(serde_json::Error, String),
|
||||
|
||||
/// An uncategorized bad HTTP response.
|
||||
UncategorizedBadResponse(String),
|
||||
|
||||
/// An uncategorized bad HTTP response with status code and body.
|
||||
UncategorizedBadResponseWithStatusAndBody {
|
||||
status_code: StatusCode,
|
||||
body: String,
|
||||
},
|
||||
|
||||
/// An uncaught error from the HTTP client.
|
||||
WreqError(wreq::Error),
|
||||
}
|
||||
|
||||
impl Error for Seedance2ProGenericApiError {}
|
||||
|
||||
impl Display for Seedance2ProGenericApiError {
|
||||
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
|
||||
match self {
|
||||
Self::CloudflareError(err) => write!(f, "Cloudflare error: {}", err),
|
||||
Self::Http502ErrorBadGateway(msg) => write!(f, "HTTP 502 Bad Gateway: {}", msg),
|
||||
Self::SerdeResponseParseErrorWithBody(err, body) => write!(f, "Failed to parse response body: {:?}. Body: {}", err, body),
|
||||
Self::SerdeParseErrorWithBodyOnNon200(err, body) => write!(f, "Failed to parse non-200 response body: {:?}. Body: {}", err, body),
|
||||
Self::UncategorizedBadResponse(msg) => write!(f, "Uncategorized bad response: {}", msg),
|
||||
Self::UncategorizedBadResponseWithStatusAndBody { status_code, body } => write!(f, "Uncategorized bad response: status code {}, body: {}", status_code, body),
|
||||
Self::WreqError(err) => write!(f, "Wreq client error: {}", err),
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
use std::error::Error;
|
||||
use std::fmt::{Display, Formatter};
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum Seedance2ProSpecificApiError {
|
||||
/// The session cookies are expired or invalid.
|
||||
UnauthorizedSessionExpired,
|
||||
}
|
||||
|
||||
impl Error for Seedance2ProSpecificApiError {}
|
||||
|
||||
impl Display for Seedance2ProSpecificApiError {
|
||||
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
|
||||
match self {
|
||||
Self::UnauthorizedSessionExpired => write!(f, "Unauthorized: session cookies expired or invalid."),
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
// User API
|
||||
pub mod creds;
|
||||
pub mod error;
|
||||
Reference in New Issue
Block a user