read/write same sora cookie, avoid cloudflare heuristics

This commit is contained in:
Brandon Thomas committed 2025-04-07 21:17:26 -04:00
1 parent 09cf4529c0
commit b41b4f8e17
9 files changed
+114 -57

No files matched your search

@@ -6,39 +6,27 @@ use image::codecs::png::{CompressionType, FilterType, PngEncoder};
use image::{DynamicImage, ImageReader};
use std::io::Cursor;
use log::{error, info};
use tauri::{AppHandle, Manager};
use tauri::{AppHandle, Manager, State};
use openai_sora_client::credentials::SoraCredentials;
use openai_sora_client::image_gen::common::{ImageSize, NumImages};
use openai_sora_client::image_gen::sora_image_gen_remix::{sora_image_gen_remix, SoraImageGenRemixRequest};
use openai_sora_client::upload::upload_media_from_bytes::sora_media_upload_from_bytes;
use openai_sora_client::upload::upload_media_from_file::SoraMediaUploadRequest;
use crate::state::app_dir::AppDataRoot;
#[tauri::command]
pub async fn image_generation_command(
image: &str,
prompt: &str,
app: AppHandle,
app_data_root: State<'_, AppDataRoot>,
) -> Result<String, String> {
info!("image_generation_command called; processing image...");
for (w, webview) in app.webviews() {
info!("sending webview: {}", w);
//let result = webview.eval("window.location.replace('https://google.com');"); // works
//let result = webview.eval("document.body.innerHTML = 'hello'"); // works
let result = webview.eval("document.body.innerHTML = document.cookie");
if let Err(err) = result {
error!("Error with webview: {:?}", err)
}
}
if true {
return Ok("true".to_string());
}
let bytes = BASE64_STANDARD.decode(image)
.map_err(|err| format!("Base64 decode error: {}", err))?;
generate_image(bytes, prompt)
generate_image(bytes, prompt, &app_data_root)
.await
.map_err(|err| {
error!("error: {:?}", err);
@@ -48,8 +36,8 @@ pub async fn image_generation_command(
Ok("success".to_string())
}
pub async fn generate_image(file_bytes: Vec<u8>, prompt: &str) -> AnyhowResult<()> {
let sora_credentials = get_credentials()?;
pub async fn generate_image(file_bytes: Vec<u8>, prompt: &str, app_data_root: &AppDataRoot) -> AnyhowResult<()> {
let sora_credentials = get_credentials(app_data_root)?;
let filename = "image.png".to_string();
@@ -79,16 +67,21 @@ pub async fn generate_image(file_bytes: Vec<u8>, prompt: &str) -> AnyhowResult<(
Ok(())
}
fn get_credentials() -> AnyhowResult<SoraCredentials> {
fn get_credentials(app_data_root: &AppDataRoot) -> AnyhowResult<SoraCredentials> {
let cookie_file = app_data_root.get_sora_cookie_file_path();
let bearer = read_to_string("/Users/bt/dev/storyteller/storyteller-rust/test_data/temp/bearer.txt")?
.trim()
.to_string();
let cookie= read_to_string("/Users/bt/dev/storyteller/storyteller-rust/test_data/temp/cookie.txt")?
let cookie= read_to_string(cookie_file)?
.trim()
.to_string();
let sentinel = read_to_string("/Users/bt/dev/storyteller/storyteller-rust/test_data/temp/sentinel.txt")?
.trim()
.to_string();
Ok(SoraCredentials {
bearer_token: bearer,
cookie: cookie,
@@ -1,8 +1,23 @@
use std::time::Duration;
use log::{error, info};
use once_cell::sync::Lazy;
use tauri::{AppHandle, Manager, Url, WebviewUrl, WebviewWindowBuilder, WindowBuilder};
use tokio::time::sleep_until;
use errors::AnyhowResult;
use crate::threads::login_thread::{LOGIN_WINDOW_NAME, SORA_LOGIN_URL};
use crate::utils::clear_all_webview_cookies::clear_all_webview_cookies;
pub const START_URL_STR: &str = "https://storyteller.ai/";
pub static START_URL: Lazy<Url> = Lazy::new(|| {
Url::parse(START_URL_STR).expect("URL should parse")
});
pub const SORA_HOMEPAGE_URL_STR: &str = "https://sora.com/";
pub static SORA_HOMEPAGE_URL : Lazy<Url> = Lazy::new(|| {
Url::parse(SORA_HOMEPAGE_URL_STR).expect("URL should parse")
});
#[tauri::command]
pub async fn open_login_command(
@@ -23,9 +38,10 @@ pub async fn open_login_command(
async fn do_open_login(app: &AppHandle) -> AnyhowResult<()> {
info!("Building login window...");
let url = WebviewUrl::External(SORA_LOGIN_URL.clone());
let url = WebviewUrl::External(START_URL.clone());
let _window = WebviewWindowBuilder::new(app, LOGIN_WINDOW_NAME, url)
let window = WebviewWindowBuilder::new(app, LOGIN_WINDOW_NAME, url)
//.user_agent(openai_sora_client::credentials::USER_AGENT)
.always_on_top(true)
.title("Login to OpenAI")
.center()
@@ -36,12 +52,20 @@ async fn do_open_login(app: &AppHandle) -> AnyhowResult<()> {
.devtools(true)
.build()?;
//info!("Iterating webviews...");
//for (name, webview) in window.webviews() {
// info!("Webview URL: {:?}", webview.url());
// webview.navigate(LOGIN_URL.clone())?;
// webview.eval(&format!("window.location.replace('{}');", LOGIN_URL_STR))?;
//}
for (name, webview) in window.webviews() {
if name != LOGIN_WINDOW_NAME {
continue;
}
clear_all_webview_cookies(&webview)?;
// NB: We're starting to get Cloudflare protection screens. Let's try to avoid.
webview.navigate(SORA_HOMEPAGE_URL.clone())?;
tokio::time::sleep(Duration::from_millis(100)).await;
webview.navigate(SORA_LOGIN_URL.clone())?;
break;
}
info!("Done.");
Ok(())
+1 -2
View File
@@ -23,7 +23,6 @@ pub fn run() {
let config = AppConfig::init()
.expect("config should load");
let app_data_root = config.app_data_root.clone();
let app_data_root2 = config.app_data_root.clone();
@@ -50,7 +49,7 @@ pub fn run() {
//}
let app = app.handle().clone();
tauri::async_runtime::spawn(login_thread(app));
tauri::async_runtime::spawn(login_thread(app, app_data_root2));
Ok(())
})
@@ -114,6 +114,10 @@ impl AppDataRoot {
pub fn log_file_name_str(&self) -> &str {
&self.log_file_name_string
}
pub fn get_sora_cookie_file_path(&self) -> PathBuf {
self.path.join("sora_cookies.txt")
}
}
impl AppAssetsDir {
@@ -1,9 +1,13 @@
use std::fs::OpenOptions;
use std::io::Write;
use anyhow::anyhow;
use log::{error, info};
use once_cell::sync::Lazy;
use reqwest::Url;
use tauri::{AppHandle, Manager, Webview};
use errors::AnyhowResult;
use crate::state::app_dir::AppDataRoot;
use crate::utils::sora_webview_cookies::get_all_sora_cookies_as_string;
pub const LOGIN_WINDOW_NAME: &str = "login_window";
@@ -13,11 +17,17 @@ pub static SORA_LOGIN_URL: Lazy<Url> = Lazy::new(|| {
Url::parse(SORA_LOGIN_URL_STR).expect("URL should parse")
});
pub async fn login_thread(app: AppHandle) -> ! {
pub const SORA_ROOT_URL_STR: &str = "https://sora.com/";
pub static SORA_ROOT_URL: Lazy<Url> = Lazy::new(|| {
Url::parse(SORA_ROOT_URL_STR).expect("URL should parse")
});
pub async fn login_thread(app: AppHandle, app_data_root: AppDataRoot) -> ! {
loop {
for (window_name, webview) in app.webviews() {
if window_name == LOGIN_WINDOW_NAME {
let result = check_login_window(&webview).await;
let result = check_login_window(&webview, &app_data_root).await;
if let Err(err) = result {
error!("Error checking login window: {:?}", err);
}
@@ -28,9 +38,10 @@ pub async fn login_thread(app: AppHandle) -> ! {
}
}
async fn check_login_window(webview: &Webview) -> AnyhowResult<()> {
async fn check_login_window(webview: &Webview, app_data_root: &AppDataRoot) -> AnyhowResult<()> {
clear_browsing_data_on_test_domain(webview)?;
keep_on_task(webview)?;
//keep_on_task(webview)?;
extract_cookies_to_file(webview, app_data_root)?;
// TODO: Other maintenance tasks ...
Ok(())
}
@@ -73,29 +84,20 @@ fn clear_browsing_data_on_test_domain(webview: &Webview) -> AnyhowResult<()> {
Ok(())
}
pub fn random_behavior(webview: &Webview) -> AnyhowResult<()> {
let url = webview.url();
//webview.navigate(url)?;
//webview.cookies_for_url(url)?;
// TODO(bt,2025-04-07): Heuristic to detect when logged in. Only write when logged in.
fn extract_cookies_to_file(webview: &Webview, app_data_root: &AppDataRoot) -> AnyhowResult<()> {
let cookies = get_all_sora_cookies_as_string(webview)?;
let rand = rand::random_range(0..5u8);
match rand {
0..3 => {
redirect_google(&webview)?;
}
_ => {
write_cookies_to_body(&webview)?;
}
}
Ok(())
}
let cookie_file = app_data_root.get_sora_cookie_file_path();
pub fn redirect_google(webview: &Webview) -> AnyhowResult<()> {
webview.eval("window.location.replace('https://google.com');")?;
Ok(())
}
let mut file = OpenOptions::new()
.create(true)
.write(true)
.truncate(true)
.open(cookie_file)?;
file.write_all(cookies.as_bytes())?;
file.flush()?;
pub fn write_cookies_to_body(webview: &Webview) -> AnyhowResult<()> {
webview.eval("document.body.innerHTML = document.cookie")?;
Ok(())
}
@@ -0,0 +1,7 @@
use tauri::Webview;
use errors::AnyhowResult;
pub fn clear_all_webview_cookies(webview: &Webview) -> AnyhowResult<()> {
webview.clear_all_browsing_data()?;
Ok(())
}
+3 -1
View File
@@ -1 +1,3 @@
pub mod image;
pub mod clear_all_webview_cookies;
pub mod image;
pub mod sora_webview_cookies;
@@ -0,0 +1,26 @@
use once_cell::sync::Lazy;
use reqwest::Url;
use tauri::Webview;
use tauri::webview::Cookie;
use errors::AnyhowResult;
const SORA_ROOT_COOKIE_URL_STR: &str = "https://sora.com/";
static SORA_ROOT_COOKIE_URL: Lazy<Url> = Lazy::new(|| {
Url::parse(SORA_ROOT_COOKIE_URL_STR).expect("URL should parse")
});
pub fn get_all_sora_cookies(webview: &Webview) -> AnyhowResult<Vec<Cookie>> {
let cookies = webview.cookies_for_url(SORA_ROOT_COOKIE_URL.clone())?;
Ok(cookies)
}
pub fn get_all_sora_cookies_as_string(webview: &Webview) -> AnyhowResult<String> {
let cookies = get_all_sora_cookies(webview)?;
let cookie_string = cookies
.iter()
.map(|cookie| format!("{}={}", cookie.name(), cookie.value()))
.collect::<Vec<String>>()
.join("; ");
Ok(cookie_string)
}
@@ -4,7 +4,7 @@ use serde_derive::Deserialize;
use errors::AnyhowResult;
// NB: It appears that the sentinel may require a matching user agent.
pub (crate) const USER_AGENT : &str = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/127.0.0.0 Safari/537.36";
pub const USER_AGENT : &str = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/127.0.0.0 Safari/537.36";
#[derive(Clone, Deserialize)]
pub struct SoraCredentials {