use futures::SinkExt;
use jmap_base_client::connect_ws;
use jmap_chat_client::{ChatWsExt, ChatWsFrame};
use std::net::SocketAddr;
use tokio::net::TcpListener;
use tokio_tungstenite::tungstenite::Message;
const RESPONSE_FRAME: &str =
r#"{"@type":"Response","requestId":"r1","methodResponses":[],"sessionState":"s1"}"#;
const STATE_CHANGE_FRAME: &str = concat!(
r#"{"@type":"StateChange","#,
r#""changed":{"u1":{"Message":"d35ecb040aab"}},"#,
r#""pushState":"bbb"}"#
);
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error + Send + Sync>> {
let listener = TcpListener::bind("127.0.0.1:0").await?;
let addr: SocketAddr = listener.local_addr()?;
let ws_url = format!("ws://{addr}/ws");
eprintln!("stub WebSocket: {ws_url}");
let stub = tokio::spawn(async move {
let (stream, _peer) = listener.accept().await?;
let mut ws = tokio_tungstenite::accept_async(stream).await?;
ws.send(Message::Text(RESPONSE_FRAME.into())).await?;
ws.send(Message::Text(STATE_CHANGE_FRAME.into())).await?;
ws.close(None).await?;
Ok::<_, Box<dyn std::error::Error + Send + Sync>>(())
});
let mut session = connect_ws(&ws_url, None).await?;
let mut count = 0usize;
while let Some(frame) = session.next_chat_frame().await {
let frame = frame?;
count += 1;
match &frame {
ChatWsFrame::Response(r) => println!(
"frame #{count}: Response — {} method responses, session_state={:?}",
r.method_responses.len(),
r.session_state
),
ChatWsFrame::StateChange(sc) => println!(
"frame #{count}: StateChange — {} account(s) changed",
sc.changed.len()
),
other => println!("frame #{count}: other — {other:?}"),
}
}
println!("session closed after {count} frame(s)");
stub.await??;
Ok(())
}