mirror of
https://github.com/storytold/artcraft.git
synced 2026-11-05 01:38:44 +00:00
launch login thread with command instead
This commit is contained in:
1 parent
357cf59266
commit
a32905da06
12 files changed
+119
-73
No files matched your search
@@ -1,32 +1,21 @@
|
||||
use crate::threads::sora_session_login_thread::{LOGIN_WINDOW_NAME, SORA_LOGIN_URL};
|
||||
use crate::utils::clear_all_webview_cookies::clear_all_webview_cookies;
|
||||
use crate::state::app_preferences::app_preferences_manager::AppPreferencesManager;
|
||||
use crate::state::data_dir::app_data_root::AppDataRoot;
|
||||
use crate::state::sora::sora_credential_manager::SoraCredentialManager;
|
||||
use crate::windows::sora_login_window::open_sora_login_window::open_sora_login_window;
|
||||
use errors::AnyhowResult;
|
||||
use log::{error, info};
|
||||
use once_cell::sync::Lazy;
|
||||
use std::time::Duration;
|
||||
use anyhow::anyhow;
|
||||
use tauri::{AppHandle, Manager, Url, WebviewUrl, WebviewWindowBuilder, WindowBuilder};
|
||||
use tokio::time::sleep_until;
|
||||
|
||||
pub const START_URL_STR: &str = "https://google.com";
|
||||
|
||||
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")
|
||||
});
|
||||
use tauri::{AppHandle, State};
|
||||
|
||||
#[tauri::command]
|
||||
pub async fn open_sora_login_command(
|
||||
app: AppHandle,
|
||||
app_data_root: State<'_, AppDataRoot>,
|
||||
sora_creds_manager: State<'_, SoraCredentialManager>,
|
||||
) -> Result<String, String> {
|
||||
info!("open_login_command called");
|
||||
|
||||
do_open_login(&app)
|
||||
do_open_login(&app, &app_data_root, &sora_creds_manager)
|
||||
.await
|
||||
.map_err(|err| {
|
||||
error!("Error opening login: {:?}", err);
|
||||
@@ -36,35 +25,14 @@ pub async fn open_sora_login_command(
|
||||
Ok("result".to_string())
|
||||
}
|
||||
|
||||
async fn do_open_login(app: &AppHandle) -> AnyhowResult<()> {
|
||||
async fn do_open_login(
|
||||
app: &AppHandle,
|
||||
app_data_root: &AppDataRoot,
|
||||
sora_creds_manager: &SoraCredentialManager,
|
||||
) -> AnyhowResult<()> {
|
||||
info!("Building login window...");
|
||||
|
||||
let url = WebviewUrl::External(START_URL.clone());
|
||||
|
||||
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()
|
||||
.resizable(true)
|
||||
.visible(true)
|
||||
.closable(true)
|
||||
.min_inner_size(200.0, 800.0)
|
||||
.focused(true)
|
||||
.devtools(true)
|
||||
.build()?;
|
||||
|
||||
let webview = window.get_webview(LOGIN_WINDOW_NAME)
|
||||
.ok_or_else(|| anyhow!("no webview found"))?;
|
||||
|
||||
clear_all_webview_cookies(&webview)?;
|
||||
|
||||
webview.navigate(SORA_HOMEPAGE_URL.clone())?;
|
||||
|
||||
// NB: We're starting to get Cloudflare protection screens. Let's try to avoid.
|
||||
tokio::time::sleep(Duration::from_millis(100)).await;
|
||||
|
||||
webview.navigate(SORA_LOGIN_URL.clone())?;
|
||||
open_sora_login_window(app, app_data_root, sora_creds_manager).await?;
|
||||
|
||||
info!("Done.");
|
||||
Ok(())
|
||||
|
||||
@@ -3,16 +3,18 @@ pub mod events;
|
||||
pub mod state;
|
||||
pub mod threads;
|
||||
pub mod utils;
|
||||
pub mod windows;
|
||||
|
||||
use tauri::Manager;
|
||||
|
||||
use crate::commands::flip_image::flip_image;
|
||||
use crate::commands::app_preferences::get_app_preferences_command::get_app_preferences_command;
|
||||
use crate::commands::app_preferences::update_app_preference_command::update_app_preferences_command;
|
||||
use crate::commands::flip_image::flip_image;
|
||||
use crate::commands::platform_info_command::platform_info_command;
|
||||
use crate::commands::sora::open_sora_login_command::open_sora_login_command;
|
||||
use crate::commands::sora::sora_image_generation_command::sora_image_generation_command;
|
||||
use crate::commands::sora::sora_image_remix_command::sora_image_remix_command;
|
||||
use crate::state::app_preferences::app_preferences_manager::load_app_preferences_or_default;
|
||||
use crate::state::data_dir::app_data_root::AppDataRoot;
|
||||
use crate::state::main_window_size::MainWindowSize;
|
||||
use crate::state::sora::sora_credential_manager::SoraCredentialManager;
|
||||
@@ -20,13 +22,11 @@ use crate::state::sora::sora_task_queue::SoraTaskQueue;
|
||||
use crate::state::storyteller::storyteller_credential_manager::StorytellerCredentialManager;
|
||||
use crate::threads::discord_presence_thread::discord_presence_thread;
|
||||
use crate::threads::main_window_thread::main_window_thread::main_window_thread;
|
||||
use crate::threads::sora_session_login_thread::sora_session_login_thread;
|
||||
use crate::threads::sora_task_polling_thread::sora_task_polling_thread;
|
||||
use crate::utils::webview_unsafe::webview_unsafe_for_app;
|
||||
|
||||
use crate::state::app_preferences::app_preferences_manager::load_app_preferences_or_default;
|
||||
use tauri_plugin_http;
|
||||
use tauri_plugin_dialog;
|
||||
use tauri_plugin_http;
|
||||
use tauri_plugin_log::Target;
|
||||
use tauri_plugin_log::TargetKind;
|
||||
|
||||
@@ -108,7 +108,7 @@ pub fn run() {
|
||||
}
|
||||
}
|
||||
|
||||
tauri::async_runtime::spawn(sora_session_login_thread(app_2, app_data_root_2, sora_creds_manager_2));
|
||||
//tauri::async_runtime::spawn(sora_session_login_thread(app_2, app_data_root_2, sora_creds_manager_2));
|
||||
tauri::async_runtime::spawn(main_window_thread(app_3, app_data_root_3, storyteller_creds_manager_2));
|
||||
tauri::async_runtime::spawn(sora_task_polling_thread(app_4, app_data_root_4, sora_creds_manager_3, storyteller_creds_manager_3, sora_task_queue_2));
|
||||
tauri::async_runtime::spawn(discord_presence_thread());
|
||||
|
||||
-1
@@ -1,7 +1,6 @@
|
||||
use crate::state::app_startup_time::AppStartupTime;
|
||||
use crate::state::data_dir::app_data_root::AppDataRoot;
|
||||
use crate::state::storyteller::storyteller_credential_manager::StorytellerCredentialManager;
|
||||
use crate::threads::sora_session_login_thread::LOGIN_WINDOW_NAME;
|
||||
use anyhow::anyhow;
|
||||
use chrono::TimeDelta;
|
||||
use errors::AnyhowResult;
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
pub mod discord_presence_thread;
|
||||
pub mod main_window_thread;
|
||||
pub mod sora_session_login_thread;
|
||||
pub mod sora_login_thread;
|
||||
pub mod sora_task_polling_thread;
|
||||
@@ -0,0 +1 @@
|
||||
pub mod sora_login_thread;
|
||||
+19
-12
@@ -33,25 +33,32 @@ pub static SORA_ROOT_URL: Lazy<Url> = Lazy::new(|| {
|
||||
Url::parse(SORA_ROOT_URL_STR).expect("URL should parse")
|
||||
});
|
||||
|
||||
pub async fn sora_session_login_thread(
|
||||
pub async fn sora_login_thread(
|
||||
app: AppHandle,
|
||||
app_data_root: AppDataRoot,
|
||||
sora_creds_manager: SoraCredentialManager
|
||||
) -> ! {
|
||||
loop {
|
||||
for (window_name, webview) in app.webviews() {
|
||||
if window_name == LOGIN_WINDOW_NAME {
|
||||
let result = check_login_window(
|
||||
&webview,
|
||||
&app_data_root,
|
||||
&sora_creds_manager,
|
||||
).await;
|
||||
if let Err(err) = result {
|
||||
error!("Error checking login window: {:?}", err);
|
||||
}
|
||||
break;
|
||||
info!(">>> SORA LOGIN THREAD <<<");
|
||||
|
||||
let login_webview = match app.get_webview(LOGIN_WINDOW_NAME) {
|
||||
Some(webview) => webview,
|
||||
None => {
|
||||
tokio::time::sleep(std::time::Duration::from_millis(2_000)).await;
|
||||
continue;
|
||||
}
|
||||
};
|
||||
|
||||
let result = check_login_window(
|
||||
&login_webview,
|
||||
&app_data_root,
|
||||
&sora_creds_manager,
|
||||
).await;
|
||||
|
||||
if let Err(err) = result {
|
||||
error!("Error checking login window: {:?}", err);
|
||||
}
|
||||
|
||||
tokio::time::sleep(std::time::Duration::from_millis(2_000)).await;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
pub mod sora_login_window;
|
||||
@@ -0,0 +1 @@
|
||||
pub mod open_sora_login_window;
|
||||
@@ -0,0 +1,69 @@
|
||||
use crate::state::data_dir::app_data_root::AppDataRoot;
|
||||
use crate::state::sora::sora_credential_manager::SoraCredentialManager;
|
||||
use crate::threads::sora_login_thread::sora_login_thread::{sora_login_thread, LOGIN_WINDOW_NAME, SORA_LOGIN_URL};
|
||||
use crate::utils::clear_all_webview_cookies::clear_all_webview_cookies;
|
||||
use anyhow::anyhow;
|
||||
use errors::AnyhowResult;
|
||||
use once_cell::sync::Lazy;
|
||||
use reqwest::Url;
|
||||
use std::time::Duration;
|
||||
use tauri::{AppHandle, Manager, WebviewUrl, WebviewWindowBuilder};
|
||||
|
||||
pub const START_URL_STR: &str = "https://google.com";
|
||||
|
||||
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")
|
||||
});
|
||||
|
||||
pub async fn open_sora_login_window(
|
||||
app: &AppHandle,
|
||||
app_data_root: &AppDataRoot,
|
||||
sora_creds_manager: &SoraCredentialManager,
|
||||
) -> AnyhowResult<()> {
|
||||
if app.get_window(LOGIN_WINDOW_NAME).is_some() {
|
||||
return Err(anyhow!("Login window already open"));
|
||||
}
|
||||
|
||||
let url = WebviewUrl::External(START_URL.clone());
|
||||
|
||||
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's Sora")
|
||||
.center()
|
||||
.resizable(true)
|
||||
.visible(true)
|
||||
.closable(true)
|
||||
.min_inner_size(200.0, 800.0)
|
||||
.focused(true)
|
||||
.devtools(true)
|
||||
.build()?;
|
||||
|
||||
let webview = window.get_webview(LOGIN_WINDOW_NAME)
|
||||
.ok_or_else(|| anyhow!("no webview found"))?;
|
||||
|
||||
clear_all_webview_cookies(&webview)?;
|
||||
|
||||
webview.navigate(SORA_HOMEPAGE_URL.clone())?;
|
||||
|
||||
// NB: We're starting to get Cloudflare protection screens. Let's try to avoid.
|
||||
tokio::time::sleep(Duration::from_millis(100)).await;
|
||||
|
||||
webview.navigate(SORA_LOGIN_URL.clone())?;
|
||||
|
||||
let app_handle = app.clone();
|
||||
let app_data_root = app_data_root.clone();
|
||||
let sora_creds_manager = sora_creds_manager.clone();
|
||||
|
||||
let _ = tauri::async_runtime::spawn(async move {
|
||||
sora_login_thread(app_handle, app_data_root, sora_creds_manager).await;
|
||||
});
|
||||
|
||||
Ok(())
|
||||
}
|
||||
@@ -30,6 +30,8 @@ pub struct TaskResponse {
|
||||
pub height: u32,
|
||||
pub width: u32,
|
||||
pub operation: String,
|
||||
|
||||
// There are many more fields [...]
|
||||
}
|
||||
|
||||
/// Note: this request only requires a valid bearer token, and it doesn't require a cookie payload at all!
|
||||
@@ -71,10 +73,9 @@ pub async fn list_media(credentials: &SoraCredentialSet) -> Result<ListMediaResp
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use errors::AnyhowResult;
|
||||
use crate::creds::sora_jwt_bearer_token::SoraJwtBearerToken;
|
||||
use crate::recipes::maybe_upgrade_or_renew_session::maybe_upgrade_or_renew_session;
|
||||
use super::*;
|
||||
use crate::creds::sora_jwt_bearer_token::SoraJwtBearerToken;
|
||||
use errors::AnyhowResult;
|
||||
|
||||
#[tokio::test]
|
||||
#[ignore] // Don't run in CI. Requires valid cookie
|
||||
|
||||
@@ -9,8 +9,6 @@ pub async fn classify_general_http_error(response: reqwest::Response) -> SoraErr
|
||||
Err(err) => return SoraError::ReqwestError(err),
|
||||
};
|
||||
|
||||
println!("Failed to fetch media list: {}", status);
|
||||
println!("Message: {}", message);
|
||||
/*
|
||||
|
||||
Old cookie -
|
||||
@@ -36,6 +34,7 @@ Message: {
|
||||
}
|
||||
*/
|
||||
|
||||
// TODO: I *think* this is just the bearer token, not the cookie.
|
||||
let cookie_expired =
|
||||
message.contains("Your authentication token has expired. Please try signing in again.")
|
||||
|| message.contains("token_expired");
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
//! Adapted from 'jwt' crate
|
||||
|
||||
use crate::sora_error::SoraError;
|
||||
use anyhow::anyhow;
|
||||
use base64::Engine;
|
||||
use base64::prelude::BASE64_URL_SAFE_NO_PAD;
|
||||
use base64::Engine;
|
||||
use chrono::{DateTime, Utc};
|
||||
use errors::AnyhowResult;
|
||||
use log::warn;
|
||||
use serde_json::Value;
|
||||
use errors::AnyhowResult;
|
||||
use crate::sora_error::SoraError;
|
||||
|
||||
const SEPARATOR: &str = ".";
|
||||
|
||||
|
||||
Reference in new issue
Block a user