ugh, user-agent header was scuffed

This commit is contained in:
Brandon Thomas committed 2025-10-17 03:15:37 -04:00
1 parent 89286ba459
commit cbe2a2a6d5
7 files changed
+165 -29

No files matched your search

@@ -0,0 +1,116 @@
use crate::error::grok_client_error::GrokClientError;
use crate::error::grok_error::GrokError;
use crate::error::grok_generic_api_error::GrokGenericApiError;
use log::info;
use std::ops::Deref;
use wreq::header::{ACCEPT, ACCEPT_ENCODING, ACCEPT_LANGUAGE, CACHE_CONTROL, CONNECTION, CONTENT_TYPE, COOKIE, ORIGIN, PRAGMA, REFERER, TE, UPGRADE, USER_AGENT};
use wreq::ws::message::Message;
use wreq::Client;
use wreq_util::Emulation;
// Not even sure what this endpoint just, just testing auth
const INDEX_URL: &str = "https://grok.com";
pub struct GetIndexArgs<'a> {
pub cookies: &'a str,
}
pub async fn get_index(args: GetIndexArgs<'_>) -> Result<(), GrokError> {
println!("Building client...");
info!("Building client...");
let client = Client::builder()
.emulation(Emulation::Firefox143)
.build()
.map_err(|err| GrokClientError::WreqClientError(err))?;
println!("Configuring client...");
info!("Configuring client...");
let cookies = args.cookies.to_string();
println!("Cookies: {}", cookies);
let builder = client.get(INDEX_URL)
.header("User-Agent", "Mozilla/5.0 (Macintosh; Intel Mac OS X 10.15; rv:144.0) Gecko/20100101 Firefox/144.0")
.header("Accept", "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8")
.header("Accept-Encoding", "gzip, deflate, br, zstd")
.header("Accept-Language", "en-US,en;q=0.5")
.header("Connection", "keep-alive")
.header("Sec-Fetch-Dest", "document")
.header("Sec-Fetch-Mode", "navigate")
.header("Sec-Fetch-Site", "none")
.header("Sec-Fetch-User", "?1")
.header("Sec-GPC", "1")
.header("priority", "u=0, i")
.header("Pragma", "no-cache")
.header("Cache-Control", "no-cache")
.header("TE", "trailers");
//.header("Sec-WebSocket-Version", "13")
//.header("Cookie", cookies)
//.header("Sec-WebSocket-Extensions", "permessage-deflate")
//.header(CONNECTION, "keep-alive, Upgrade")
//.header("Sec-WebSocket-Key", "BhBXbFSG6/1xcZVq4ySxcg==") // TODO
//.header(ORIGIN, "https://grok.com")
//.header("Referer", "https://grok.com/imagine")
//.header("Content-Type", "application/json")
// TODO: sentry-trace
// TODO: baggage
//.header("sentry-trace", "235eb6899dcb507c7993058e7055bf28-b37fd92f38d23c3f-0")
//.header("baggage", "sentry-environment=production,sentry-public_key=b311e0f2690c81f25e2c4cf6d4f7ce1c,sentry-trace_id=235eb6899dcb507c7993058e7055bf28,sentry-org_id=4508179396558848,sentry-sampled=false,sentry-sample_rand=0.5123249939079335,sentry-sample_rate=0")
println!("Sending...");
info!("Sending...");
let response = builder.send()
.await
.map_err(|err| GrokClientError::WreqClientError(err))?;
let status = response.status();
println!("Status: {}", status);
let body = response.text()
.await
.map_err(|err| GrokGenericApiError::WreqError(err))?;
println!("Body: {}", body);
//for (k, v) in response.headers().iter() {
// println!("Header: {}: {:?}", k, v);
//}
println!("Into websocket...");
info!("Into websocket...");
Ok(())
}
#[cfg(test)]
mod tests {
use super::*;
use crate::test_utils::get_test_cookies::get_test_cookies;
use errors::AnyhowResult;
#[tokio::test]
#[ignore] // manually test
async fn create() -> AnyhowResult<()> {
let cookies = get_test_cookies()?;
let args = GetIndexArgs {
cookies: &cookies,
};
let result = get_index(args).await;
match result {
Ok(ok) => {
println!("Okay");
}
Err(err) => {
println!("{:?}", err);
}
}
assert_eq!(1, 2);
Ok(())
}
}
@@ -29,7 +29,7 @@ pub async fn get_tasks(args: TasksArgs<'_>) -> Result<(), GrokError> {
let builder = wreq::get(TASKS_URL)
.header(ACCEPT, "*/*")
.header(USER_AGENT, "User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.15; rv:144.0) Gecko/20100101 Firefox/144.0")
.header(USER_AGENT, "Mozilla/5.0 (Macintosh; Intel Mac OS X 10.15; rv:144.0) Gecko/20100101 Firefox/144.0")
.header(ACCEPT_LANGUAGE, "en-US,en;q=0.5")
.header(ACCEPT_ENCODING, "gzip, deflate, br, zstd")
.header(ORIGIN, "https://grok.com")
@@ -1,2 +1,3 @@
mod get_tasks;
mod oauth_connectors;
mod oauth_connectors;
mod get_index;
@@ -20,33 +20,40 @@ pub async fn get_oauth_connectors(args: OauthConnectorsArgs<'_>) -> Result<(), G
info!("Building client...");
let client = Client::builder()
.emulation(Emulation::Firefox139)
.emulation(Emulation::Firefox143)
.build()
.map_err(|err| GrokClientError::WreqClientError(err))?;
println!("Configuring client...");
info!("Configuring client...");
let cookies = args.cookies.to_string();
println!("Cookies: {}", cookies);
let builder = client.get(OAUTH_CONNECTORS_URL)
.header(ACCEPT, "*/*")
.header(USER_AGENT, "User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.15; rv:144.0) Gecko/20100101 Firefox/144.0")
.header(ACCEPT_LANGUAGE, "en-US,en;q=0.5")
.header(ACCEPT_ENCODING, "gzip, deflate, br, zstd")
.header(ORIGIN, "https://grok.com")
.header(REFERER, "https://grok.com/imagine")
.header(CONTENT_TYPE, "application/json")
.header("User-Agent", "Mozilla/5.0 (Macintosh; Intel Mac OS X 10.15; rv:144.0) Gecko/20100101 Firefox/144.0")
.header("Accept", "*/*")
.header("Accept-Language", "en-US,en;q=0.5")
.header("Accept-Encoding", "gzip, deflate, br, zstd")
//.header(ORIGIN, "https://grok.com")
.header("Referer", "https://grok.com/imagine")
.header("Content-Type", "application/json")
// TODO: sentry-trace
// TODO: baggage
.header(CONNECTION, "keep-alive")
.header(COOKIE, args.cookies.to_string())
//.header(CONNECTION, "keep-alive, Upgrade")
//.header("sentry-trace", "235eb6899dcb507c7993058e7055bf28-b37fd92f38d23c3f-0")
//.header("baggage", "sentry-environment=production,sentry-public_key=b311e0f2690c81f25e2c4cf6d4f7ce1c,sentry-trace_id=235eb6899dcb507c7993058e7055bf28,sentry-org_id=4508179396558848,sentry-sampled=false,sentry-sample_rand=0.5123249939079335,sentry-sample_rate=0")
.header("Sec-GPC", "1")
.header("Connection", "keep-alive")
.header("Cookie", cookies)
//.header(CONNECTION, "keep-alive, Upgrade")
.header("Sec-Fetch-Dest", "empty")
.header("Sec-Fetch-Mode", "cors")
.header("Sec-Fetch-Site", "same-origin")
.header("priority", "u=4")
.header(PRAGMA, "no-cache")
.header(TE, "trailers");
.header("Pragma", "no-cache")
.header("Cache-Control", "no-cache")
.header("TE", "trailers");
//.header("Sec-WebSocket-Version", "13")
//.header("Sec-WebSocket-Extensions", "permessage-deflate")
//.header("Sec-WebSocket-Key", "BhBXbFSG6/1xcZVq4ySxcg==") // TODO
@@ -29,7 +29,7 @@ impl GrokCredentialManager {
let result = GrokSerializableState::read_from_disk(app_data_root);
match result {
Err(err) => {
warn!("Failed to read midjourney state from disk: {:?}", err);
warn!("Failed to read grok state from disk: {:?}", err);
cookies = Arc::new(RwLock::new(None));
//user_info = Arc::new(RwLock::new(None));
},
@@ -145,6 +145,10 @@ impl GrokCredentialManager {
// Ok(info) => info.clone(),
//};
let maybe_cookies_header= maybe_cookies
.as_ref()
.map(|cookies| cookies.to_cookie_string());
let maybe_cookies= maybe_cookies
.map(|cookies| cookies.to_serializable());
@@ -162,11 +166,17 @@ impl GrokCredentialManager {
user_cookies: maybe_cookies,
};
let path = self.app_data_root.credentials_dir().get_midjourney_state_path();
let path = self.app_data_root.credentials_dir().get_grok_state_path();
let serialized = serde_json::to_string(&state)?;
std::fs::write(path, serialized)?;
// TODO: This is just for building the client and testing.
if let Some(cookies_header) = maybe_cookies_header {
let path = self.app_data_root.credentials_dir().get_grok_cookies_path();
std::fs::write(path, cookies_header)?;
}
Ok(())
}
}
@@ -6,9 +6,9 @@ use std::collections::HashSet;
use tauri::webview::Cookie;
use tauri::WebviewWindow;
static WWW_COOKIE_URL: Lazy<Url> = Lazy::new(|| {
Url::parse("https://www.grok.com").expect("URL should parse")
});
//static WWW_COOKIE_URL: Lazy<Url> = Lazy::new(|| {
// Url::parse("https://www.grok.com").expect("URL should parse")
//});
static ROOT_COOKIE_URL: Lazy<Url> = Lazy::new(|| {
Url::parse("https://grok.com").expect("URL should parse")
@@ -27,18 +27,18 @@ pub fn grok_login_webview_extract_cookies(webview: &WebviewWindow) -> AnyhowResu
}
fn get_all_grok_cookies(webview: &WebviewWindow) -> AnyhowResult<Vec<Cookie>> {
let www_cookies = webview.cookies_for_url(WWW_COOKIE_URL.clone())?;
//let www_cookies = webview.cookies_for_url(WWW_COOKIE_URL.clone())?;
let root_cookies = webview.cookies_for_url(ROOT_COOKIE_URL.clone())?;
let mut all_cookies = www_cookies;
let mut cookie_names = HashSet::new();
let mut all_cookies = root_cookies;
//let mut cookie_names = HashSet::new();
for cookie in root_cookies.iter() {
if !cookie_names.contains(cookie.name()) {
cookie_names.insert(cookie.name().to_string());
all_cookies.push(cookie.clone());
}
}
//for cookie in root_cookies.iter() {
// if !cookie_names.contains(cookie.name()) {
// cookie_names.insert(cookie.name().to_string());
// all_cookies.push(cookie.clone());
// }
//}
Ok(all_cookies)
}
@@ -2,6 +2,7 @@ import { SoraAccountBlock } from "./SoraAccountBlock";
import { ArtcraftAccountBlock } from "./ArtcraftAccountBlock";
import { FalApiKeyBlock } from "./FalApiKeyBlock";
import { MidjourneyAccountBlock } from "./MidjourneyAccountBlock";
import { GrokAccountBlock } from "./GrokAccountBlock";
interface AccountSettingsPaneProps {
globalAccountLogoutCallback: () => void;
@@ -42,6 +43,7 @@ export const AccountSettingsPane = ({
globalAccountLogoutCallback={globalAccountLogoutCallback}
/>
<MidjourneyAccountBlock />
<GrokAccountBlock />
<SoraAccountBlock />
<FalApiKeyBlock />
{/*