3 releases

new 0.1.2 Apr 21, 2024
0.1.1 Apr 8, 2024
0.1.0 Mar 28, 2024

#158 in Robotics

Download history 127/week @ 2024-03-26 108/week @ 2024-04-02 49/week @ 2024-04-09 120/week @ 2024-04-16

404 downloads per month

Apache-2.0 OR MIT

110KB
2.5K SLoC

Bing Copilot Async Client

features

default = ["rustls"]

Using rustls by default makes it simpler to compile across platforms.

If you want to use native-tls, you can use {------, features = ["native-tls"],default-features = false}

You can use one of the enum to build a client; The cookie can be got by using Cookie Editor or other browser extensions. (Also you can you javascript to get it by yourself)

pub enum Cookie {
    // Json means format like this:
    // [
    // {
    //     "domain": ".bing.com",
    //     "expirationDate": 1743827661.986849,
    //     "hostOnly": false,
    //     "httpOnly": false,
    //     "name": "SnrOvr",
    //     "path": "/",
    //     "sameSite": "no_restriction",
    //     "secure": true,
    //     "session": false,
    //     "storeId": null,
    //     "value": "X=rebateson"
    // },
    // ······
    // ]
    JsonPath(String),
    JsonStr(String),
    // Head means format like:
    // SnrOvr=X=rebateson;SRCHUSR=DOB=20240323&T=1712299341000&TPC=1711617907000&POEX=W; ······
    HeadPath(String),
    HeadStr(String),
}

build a client without chats

use bing_client::BingClient;
#[tokio::main]
async fn main(){
    let client = BingClient::build_with_chats(&Cookie::JsonPath("path to cookie json".to_string()))
}

build a client with chats

let client = BingClient::build(&Cookie::JsonPath("path to cookie json".to_string()))
    .await
    .unwrap();
client.chats.iter().for_each(|chat| {
    println!("{}", chat);
});

Serialize and Deserialize a client

let client = BingClient::build(&Cookie::JsonPath("path to cookie json".to_string())).await.unwrap();
let client_str = serde_json::to_string(&client).unwrap();
let client = serde_json::from_str::<BingClient>(&client_str).unwrap();

Get chat list

let chats = client.get_chat_list().await.unwrap();

Create a new chat

let chat = client.create_chat().await.unwrap();

Delete a chat

client.delete_chat(& chat).await.unwrap();

Rename a chat

client..rename_chat(& chat, "new name".to_string()).await.unwrap();

Get chat messages

let messages = client.get_chat_messages(&mut last_chat).await.unwrap();

Ask question in a chat, and get only string(markdown) reply

let client = BingClient::build(&Cookie::JsonPath("path to cookie json".to_string())).await.unwrap();
let mut new_chat = client.create_chat().await.unwrap();
let user_input = UserInput::build(
    // Text question
    "hello".to_string(),
    // Image attachment, uncomment this
    // Some(Image::Path(r"example_image.jpg".to_string())),
    None,
    // Chat Tone
    Tone::Balanced,
    // plugins to use
    vec![Plugin::search()],
    &new_chat,
    &client,
)
.await
.unwrap();

let (mut stream, stop_fn) = client
    .ask_stream_plain(&mut new_chat, user_input)
    .await
    .unwrap();
while let GeneratorState::Yielded(data) = stream.async_resume().await {
    print!("\x1b[2J\x1b[H");
    println!("{data}");
}

Ask question in a chat, and get muti type reply

let client = BingClient::build(&Cookie::JsonPath("path to cookie json".to_string())).await.unwrap();
let mut new_chat = client.create_chat().await.unwrap();
let user_input = UserInput::build(
    "hello".to_string(),
    None,
    crate::types::user_input_type::Tone::Balanced,
    vec![Plugin::search()],
    &new_chat,
    &client,
)
.await
.unwrap();
let (mut stream, stop_fn) = client
    .ask_stream(&mut new_chat, user_input)
    .await
    .unwrap();
while let GeneratorState::Yielded(data) = stream.async_resume().await {
    print!("\x1b[2J\x1b[H");
    match data {
        crate::types::bot_easy_resp::BotResp::Text(text) => todo!(),
        crate::types::bot_easy_resp::BotResp::SuggestReply(suggest_replys) => todo!(),
        crate::types::bot_easy_resp::BotResp::Notice(notice) => todo!(),
        crate::types::bot_easy_resp::BotResp::Image(images) => todo!(),
        crate::types::bot_easy_resp::BotResp::Apology(apology) => todo!(),
        crate::types::bot_easy_resp::BotResp::SourceAttribution(sources) => todo!(),
        crate::types::bot_easy_resp::BotResp::Limit(limit) => todo!(),
    }
}

Stop answering

let client = BingClient::build(&Cookie::JsonPath("path to cookie json".to_string()))
    .await
    .unwrap();
let mut new_chat = client.create_chat().await.unwrap();
let user_input = UserInput::build(
    "Write a science fiction story.".to_string(),
    None,
    crate::types::user_input_type::Tone::Creative,
    vec![],
    &new_chat,
    &client,
)
.await
.unwrap();
let (mut stream, stop_fn) = client
    .ask_stream_plain(&mut new_chat, user_input)
    .await
    .unwrap();
// For example, stop the client from answering after four answers

let mut times = 0;
while let GeneratorState::Yielded(data) = stream.async_resume().await {
    times += 1;
    if times == 4{
        println!("try stop");
        stop_fn();
    }
    print!("{} ",data.len());
}

Draw images

let imgs = client.draw_image("a bird").await.unwrap();

Dependencies

~21–37MB
~436K SLoC