mirror of
https://github.com/storytold/artcraft.git
synced 2026-11-08 19:11:29 +00:00
wreq websocket wip
This commit is contained in:
1 parent
b867df290a
commit
201dcb0192
7 files changed
+200
-2
No files matched your search
Generated
+30
@@ -11871,6 +11871,18 @@ dependencies = [
|
||||
"tokio-reactor",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tokio-tungstenite"
|
||||
version = "0.27.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "489a59b6730eda1b0171fcfda8b121f4bee2b35cba8645ca35c5f7ba3eb736c1"
|
||||
dependencies = [
|
||||
"futures-util",
|
||||
"log",
|
||||
"tokio",
|
||||
"tungstenite",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tokio-uds"
|
||||
version = "0.2.7"
|
||||
@@ -12301,6 +12313,23 @@ dependencies = [
|
||||
"workspace-build-acceleration",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tungstenite"
|
||||
version = "0.27.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "eadc29d668c91fcc564941132e17b28a7ceb2f3ebf0b9dae3e03fd7a6748eb0d"
|
||||
dependencies = [
|
||||
"bytes 1.10.1",
|
||||
"data-encoding",
|
||||
"http 1.3.1",
|
||||
"httparse",
|
||||
"log",
|
||||
"rand 0.9.1",
|
||||
"sha1 0.10.6",
|
||||
"thiserror 2.0.12",
|
||||
"utf-8",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "typed-builder"
|
||||
version = "0.22.0"
|
||||
@@ -13869,6 +13898,7 @@ dependencies = [
|
||||
"sync_wrapper 1.0.2",
|
||||
"tokio",
|
||||
"tokio-boring2",
|
||||
"tokio-tungstenite",
|
||||
"tower 0.5.2",
|
||||
"tower-http",
|
||||
"want",
|
||||
|
||||
+1
-1
@@ -269,5 +269,5 @@ url = { version = "2.5.4", features = ["serde"] }
|
||||
# choco install pkgconfiglite -y
|
||||
# choco install llvm -y
|
||||
# choco install nasm -y
|
||||
wreq = { version = "6.0.0-rc.20", features = ["json", "multipart", "cookies"] }
|
||||
wreq = { version = "6.0.0-rc.20", features = ["json", "multipart", "cookies", "ws"] }
|
||||
wreq-util = "3.0.0-rc.5"
|
||||
@@ -1,5 +1,9 @@
|
||||
//! A Grok API client.
|
||||
|
||||
#[cfg(test)]
|
||||
pub (crate) mod test_utils;
|
||||
|
||||
// User lib
|
||||
pub mod credentials;
|
||||
pub mod error;
|
||||
pub mod requests;
|
||||
pub mod requests;
|
||||
+152
@@ -0,0 +1,152 @@
|
||||
use log::info;
|
||||
use wreq::Client;
|
||||
use wreq::header::{ACCEPT, ACCEPT_ENCODING, ACCEPT_LANGUAGE, CACHE_CONTROL, CONNECTION, COOKIE, ORIGIN, PRAGMA, UPGRADE, USER_AGENT};
|
||||
use wreq::ws::message::Message;
|
||||
use wreq_util::Emulation;
|
||||
use crate::error::grok_client_error::GrokClientError;
|
||||
use crate::error::grok_error::GrokError;
|
||||
use crate::error::grok_generic_api_error::GrokGenericApiError;
|
||||
|
||||
const WEBSOCKET_URL: &str = "wss://grok.com/ws/imagine/listen";
|
||||
|
||||
pub struct CreateListenWebsocketArgs<'a> {
|
||||
pub cookies: &'a str,
|
||||
}
|
||||
|
||||
pub async fn create_listen_websocket(args: CreateListenWebsocketArgs<'_>) -> Result<(), GrokError> {
|
||||
println!("Building client...");
|
||||
info!("Building client...");
|
||||
|
||||
let client = Client::builder()
|
||||
.emulation(Emulation::Firefox139)
|
||||
.build()
|
||||
.map_err(|err| GrokClientError::WreqClientError(err))?;
|
||||
|
||||
println!("Configuring client...");
|
||||
info!("Configuring client...");
|
||||
|
||||
let builder = client.get(WEBSOCKET_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("Sec-WebSocket-Version", "13")
|
||||
.header(ORIGIN, "https://grok.com")
|
||||
.header("Sec-WebSocket-Extensions", "permessage-deflate")
|
||||
// Sec-WebSocket-Key: BhBXbFSG6/1xcZVq4ySxcg==
|
||||
.header("Sec-GPC", "1")
|
||||
.header(CONNECTION, "keep-alive, Upgrade")
|
||||
.header(COOKIE, args.cookies.to_string())
|
||||
.header("Sec-Fetch-Dest", "empty")
|
||||
.header("Sec-Fetch-Mode", "websocket")
|
||||
.header("Sec-Fetch-Site", "same-origin")
|
||||
.header(PRAGMA, "no-cache")
|
||||
.header(CACHE_CONTROL, "no-cache")
|
||||
//.header(UPGRADE, "websocket")
|
||||
//.map_err(|err| GrokClientError::WreqClientError(err))?;
|
||||
|
||||
println!("Sending...");
|
||||
info!("Sending...");
|
||||
|
||||
let response = builder.send()
|
||||
.await
|
||||
.map_err(|err| GrokClientError::WreqClientError(err))?;
|
||||
|
||||
let status = response.status();
|
||||
|
||||
for (k, v) in response.headers().iter() {
|
||||
println!("Header: {}: {:?}", k, v);
|
||||
}
|
||||
|
||||
println!("Upgrading...");
|
||||
info!("Upgrading...");
|
||||
|
||||
let upgraded = response
|
||||
.upgrade()
|
||||
.await
|
||||
.map_err(|err| GrokClientError::WreqClientError(err))?;
|
||||
|
||||
println!("Status: {}", status);
|
||||
|
||||
println!("Into websocket...");
|
||||
info!("Into websocket...");
|
||||
|
||||
let mut websocket = upgraded.into_websocket()
|
||||
.await
|
||||
.map_err(|err| GrokGenericApiError::WreqError(err))?;
|
||||
|
||||
let message = r#"
|
||||
{"type":"conversation.item.create","timestamp":1760675883072,"item":{"type":"message","content":[{"requestId":"3cedf20e-f51c-db5d-a124-bcec05feedf1","text":"A pirannah","type":"input_text","properties":{"section_count":0,"is_kids_mode":false,"enable_nsfw":true,"skip_upsampler":false,"is_initial":false}}]}}
|
||||
"#.trim().to_string();
|
||||
|
||||
let wire_message = Message::text(message);
|
||||
|
||||
websocket.send(wire_message)
|
||||
.await
|
||||
.map_err(|err| GrokGenericApiError::WreqError(err))?;
|
||||
|
||||
loop {
|
||||
let maybe_message = websocket.recv().await;
|
||||
|
||||
if let Some(message) = maybe_message {
|
||||
let message = message.map_err(|err| GrokGenericApiError::WreqError(err))?;
|
||||
|
||||
match message {
|
||||
Message::Text(text) => {
|
||||
println!("Received text message: {}", text);
|
||||
}
|
||||
Message::Binary(bin) => {
|
||||
println!("Received binary message: {:?}", bin);
|
||||
}
|
||||
Message::Ping(ping) => {
|
||||
println!("Received ping: {:?}", ping);
|
||||
}
|
||||
Message::Pong(pong) => {
|
||||
println!("Received pong: {:?}", pong);
|
||||
}
|
||||
Message::Close(close_frame) => {
|
||||
println!("Received close: {:?}", close_frame);
|
||||
break;
|
||||
}
|
||||
_ => {
|
||||
println!("Received other message: {:?}", message);
|
||||
}
|
||||
}
|
||||
|
||||
tokio::time::sleep(std::time::Duration::from_millis(15_000)).await;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use errors::AnyhowResult;
|
||||
use crate::test_utils::get_test_cookies::get_test_cookies;
|
||||
use super::*;
|
||||
|
||||
#[tokio::test]
|
||||
#[ignore] // manually test
|
||||
async fn create() -> AnyhowResult<()> {
|
||||
let cookies = get_test_cookies()?;
|
||||
let args = CreateListenWebsocketArgs {
|
||||
cookies: &cookies,
|
||||
};
|
||||
let result = create_listen_websocket(args).await;
|
||||
|
||||
match result {
|
||||
Ok(ok) => {
|
||||
println!("Okay");
|
||||
}
|
||||
Err(err) => {
|
||||
println!("{:?}", err);
|
||||
}
|
||||
}
|
||||
|
||||
assert_eq!(1, 2);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
mod create_listen_websocket;
|
||||
@@ -0,0 +1,9 @@
|
||||
use errors::AnyhowResult;
|
||||
use std::fs::read_to_string;
|
||||
|
||||
#[cfg(test)]
|
||||
pub fn get_test_cookies() -> AnyhowResult<String> {
|
||||
let cookies = read_to_string("/Users/bt/Artcraft/credentials/grok_cookies.txt")?;
|
||||
let cookies = cookies.trim().to_string();
|
||||
Ok(cookies)
|
||||
}
|
||||
@@ -0,0 +1,2 @@
|
||||
#[cfg(test)]
|
||||
pub (crate) mod get_test_cookies;
|
||||
Reference in new issue
Block a user