Spaces:
Sleeping
Sleeping
| use crate::app::{ | |
| constant::{ | |
| CONTENT_TYPE_CONNECT_PROTO, CURSOR_API2_HOST, CURSOR_HOST, CURSOR_SETTINGS_URL, | |
| HEADER_NAME_GHOST_MODE, TRUE, | |
| }, | |
| lazy::{ | |
| CURSOR_API2_CHAT_URL, CURSOR_API2_STRIPE_URL, CURSOR_USAGE_API_URL, CURSOR_USER_API_URL, | |
| REVERSE_PROXY_HOST, USE_PROXY, | |
| }, | |
| }; | |
| use reqwest::header::{ | |
| ACCEPT, ACCEPT_ENCODING, ACCEPT_LANGUAGE, CACHE_CONTROL, CONNECTION, CONTENT_TYPE, COOKIE, DNT, | |
| HOST, ORIGIN, PRAGMA, REFERER, TE, TRANSFER_ENCODING, USER_AGENT, | |
| }; | |
| use reqwest::{Client, RequestBuilder}; | |
| use uuid::Uuid; | |
| use super::utils::generate_hash; | |
| macro_rules! def_const { | |
| ($name:ident, $value:expr) => { | |
| const $name: &'static str = $value; | |
| }; | |
| } | |
| def_const!(SEC_FETCH_DEST, "sec-fetch-dest"); | |
| def_const!(SEC_FETCH_MODE, "sec-fetch-mode"); | |
| def_const!(SEC_FETCH_SITE, "sec-fetch-site"); | |
| def_const!(SEC_GPC, "sec-gpc"); | |
| def_const!(PRIORITY, "priority"); | |
| def_const!(ONE, "1"); | |
| def_const!(ENCODINGS, "gzip,br"); | |
| def_const!(VALUE_ACCEPT, "*/*"); | |
| def_const!(VALUE_LANGUAGE, "zh-CN"); | |
| def_const!(EMPTY, "empty"); | |
| def_const!(CORS, "cors"); | |
| def_const!(NO_CACHE, "no-cache"); | |
| def_const!(UA_WIN, "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.0.0 Safari/537.36"); | |
| def_const!(SAME_ORIGIN, "same-origin"); | |
| def_const!(KEEP_ALIVE, "keep-alive"); | |
| def_const!(TRAILERS, "trailers"); | |
| def_const!(U_EQ_4, "u=4"); | |
| def_const!(PROXY_HOST, "x-co"); | |
| /// 返回预构建的 Cursor API 客户端 | |
| /// | |
| /// # 参数 | |
| /// | |
| /// * `auth_token` - 授权令牌 | |
| /// * `checksum` - 校验和 | |
| /// * `endpoint` - API 端点路径 | |
| /// | |
| /// # 返回 | |
| /// | |
| /// * `reqwest::RequestBuilder` - 配置好的请求构建器 | |
| pub fn build_client(auth_token: &str, checksum: &str) -> RequestBuilder { | |
| let trace_id = Uuid::new_v4().to_string(); | |
| let client = if *USE_PROXY { | |
| Client::new() | |
| .post(&*CURSOR_API2_CHAT_URL) | |
| .header(HOST, &*REVERSE_PROXY_HOST) | |
| .header(PROXY_HOST, CURSOR_API2_HOST) | |
| } else { | |
| Client::new() | |
| .post(&*CURSOR_API2_CHAT_URL) | |
| .header(HOST, CURSOR_API2_HOST) | |
| }; | |
| client | |
| .header(CONTENT_TYPE, CONTENT_TYPE_CONNECT_PROTO) | |
| .bearer_auth(auth_token) | |
| .header("connect-accept-encoding", ENCODINGS) | |
| .header("connect-protocol-version", ONE) | |
| .header(USER_AGENT, "connect-es/1.6.1") | |
| .header("x-amzn-trace-id", format!("Root={}", trace_id)) | |
| .header("x-client-key", generate_hash()) | |
| .header("x-cursor-checksum", checksum) | |
| .header("x-cursor-client-version", "0.42.5") | |
| .header("x-cursor-timezone", "Asia/Shanghai") | |
| .header(HEADER_NAME_GHOST_MODE, TRUE) | |
| .header("x-request-id", trace_id) | |
| .header(CONNECTION, KEEP_ALIVE) | |
| .header(TRANSFER_ENCODING, "chunked") | |
| } | |
| /// 返回预构建的获取 Stripe 账户信息的 Cursor API 客户端 | |
| /// | |
| /// # 参数 | |
| /// | |
| /// * `auth_token` - 授权令牌 | |
| /// | |
| /// # 返回 | |
| /// | |
| /// * `reqwest::RequestBuilder` - 配置好的请求构建器 | |
| pub fn build_profile_client(auth_token: &str) -> RequestBuilder { | |
| let client = if *USE_PROXY { | |
| Client::new() | |
| .get(&*CURSOR_API2_STRIPE_URL) | |
| .header(HOST, &*REVERSE_PROXY_HOST) | |
| .header(PROXY_HOST, CURSOR_API2_HOST) | |
| } else { | |
| Client::new() | |
| .get(&*CURSOR_API2_STRIPE_URL) | |
| .header(HOST, CURSOR_API2_HOST) | |
| }; | |
| client | |
| .header("sec-ch-ua", "\"Not-A.Brand\";v=\"99\", \"Chromium\";v=\"124\"") | |
| .header(HEADER_NAME_GHOST_MODE, TRUE) | |
| .header("sec-ch-ua-mobile", "?0") | |
| .bearer_auth(auth_token) | |
| .header( | |
| USER_AGENT, | |
| "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Cursor/0.42.5 Chrome/124.0.6367.243 Electron/30.4.0 Safari/537.36", | |
| ) | |
| .header("sec-ch-ua-platform", "\"Windows\"") | |
| .header(ACCEPT, VALUE_ACCEPT) | |
| .header(ORIGIN, "vscode-file://vscode-app") | |
| .header(SEC_FETCH_SITE, "cross-site") | |
| .header(SEC_FETCH_MODE, CORS) | |
| .header(SEC_FETCH_DEST, EMPTY) | |
| .header(ACCEPT_ENCODING, ENCODINGS) | |
| .header(ACCEPT_LANGUAGE, VALUE_LANGUAGE) | |
| .header(PRIORITY, "u=1, i") | |
| } | |
| /// 返回预构建的获取使用情况的 Cursor API 客户端 | |
| /// | |
| /// # 参数 | |
| /// | |
| /// * `user_id` - 用户 ID | |
| /// * `auth_token` - 授权令牌 | |
| /// | |
| /// # 返回 | |
| /// | |
| /// * `reqwest::RequestBuilder` - 配置好的请求构建器 | |
| pub fn build_usage_client(user_id: &str, auth_token: &str) -> RequestBuilder { | |
| let session_token = format!("{}%3A%3A{}", user_id, auth_token); | |
| let client = if *USE_PROXY { | |
| Client::new() | |
| .get(&*CURSOR_USAGE_API_URL) | |
| .header(HOST, &*REVERSE_PROXY_HOST) | |
| .header(PROXY_HOST, CURSOR_HOST) | |
| } else { | |
| Client::new() | |
| .get(&*CURSOR_USAGE_API_URL) | |
| .header(HOST, CURSOR_HOST) | |
| }; | |
| client | |
| .header(USER_AGENT, UA_WIN) | |
| .header(ACCEPT, VALUE_ACCEPT) | |
| .header(ACCEPT_LANGUAGE, VALUE_LANGUAGE) | |
| .header(ACCEPT_ENCODING, ENCODINGS) | |
| .header(REFERER, CURSOR_SETTINGS_URL) | |
| .header(DNT, ONE) | |
| .header(SEC_GPC, ONE) | |
| .header(SEC_FETCH_DEST, EMPTY) | |
| .header(SEC_FETCH_MODE, CORS) | |
| .header(SEC_FETCH_SITE, SAME_ORIGIN) | |
| .header(CONNECTION, KEEP_ALIVE) | |
| .header(PRAGMA, NO_CACHE) | |
| .header(CACHE_CONTROL, NO_CACHE) | |
| .header(TE, TRAILERS) | |
| .header(PRIORITY, U_EQ_4) | |
| .header( | |
| COOKIE, | |
| &format!("WorkosCursorSessionToken={}", session_token), | |
| ) | |
| .query(&[("user", user_id)]) | |
| } | |
| /// 返回预构建的获取用户信息的 Cursor API 客户端 | |
| /// | |
| /// # 参数 | |
| /// | |
| /// * `user_id` - 用户 ID | |
| /// * `auth_token` - 授权令牌 | |
| /// | |
| /// # 返回 | |
| /// | |
| /// * `reqwest::RequestBuilder` - 配置好的请求构建器 | |
| pub fn build_userinfo_client(user_id: &str, auth_token: &str) -> RequestBuilder { | |
| let session_token = format!("{}%3A%3A{}", user_id, auth_token); | |
| let client = if *USE_PROXY { | |
| Client::new() | |
| .get(&*CURSOR_USER_API_URL) | |
| .header(HOST, &*REVERSE_PROXY_HOST) | |
| .header(PROXY_HOST, CURSOR_HOST) | |
| } else { | |
| Client::new() | |
| .get(&*CURSOR_USER_API_URL) | |
| .header(HOST, CURSOR_HOST) | |
| }; | |
| client | |
| .header(USER_AGENT, UA_WIN) | |
| .header(ACCEPT, VALUE_ACCEPT) | |
| .header(ACCEPT_LANGUAGE, VALUE_LANGUAGE) | |
| .header(ACCEPT_ENCODING, ENCODINGS) | |
| .header(REFERER, CURSOR_SETTINGS_URL) | |
| .header(DNT, ONE) | |
| .header(SEC_GPC, ONE) | |
| .header(SEC_FETCH_DEST, EMPTY) | |
| .header(SEC_FETCH_MODE, CORS) | |
| .header(SEC_FETCH_SITE, SAME_ORIGIN) | |
| .header(CONNECTION, KEEP_ALIVE) | |
| .header(PRAGMA, NO_CACHE) | |
| .header(CACHE_CONTROL, NO_CACHE) | |
| .header(TE, TRAILERS) | |
| .header(PRIORITY, U_EQ_4) | |
| .header( | |
| COOKIE, | |
| &format!("WorkosCursorSessionToken={}", session_token), | |
| ) | |
| .query(&[("user", user_id)]) | |
| } | |