1use reqwest::header::{
4 HeaderMap, HeaderName, HeaderValue, ACCEPT, ACCEPT_LANGUAGE, CONTENT_TYPE, ORIGIN, REFERER,
5 USER_AGENT,
6};
7
8#[derive(Debug, Clone, Copy)]
10pub enum Endpoint {
11 Init,
13 Generate,
15 RotateCookies,
17 Upload,
19}
20
21impl Endpoint {
22 pub fn url(&self) -> &'static str {
24 match self {
25 Endpoint::Init => "https://gemini.google.com/app",
26 Endpoint::Generate => "https://gemini.google.com/_/BardChatUi/data/assistant.lamda.BardFrontendService/StreamGenerate",
27 Endpoint::RotateCookies => "https://accounts.google.com/RotateCookies",
28 Endpoint::Upload => "https://content-push.googleapis.com/upload",
29 }
30 }
31}
32
33pub fn gemini_headers() -> HeaderMap {
38 let mut headers = HeaderMap::new();
39 headers.insert(
40 CONTENT_TYPE,
41 HeaderValue::from_static("application/x-www-form-urlencoded;charset=utf-8"),
42 );
43
44 headers.insert(
45 ORIGIN,
46 HeaderValue::from_static("https://gemini.google.com"),
47 );
48 headers.insert(
49 REFERER,
50 HeaderValue::from_static("https://gemini.google.com/"),
51 );
52 headers.insert(
53 HeaderName::from_static("x-same-domain"),
54 HeaderValue::from_static("1"),
55 );
56 headers.insert(
58 USER_AGENT,
59 HeaderValue::from_static("Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36"),
60 );
61 headers.insert(ACCEPT, HeaderValue::from_static("*/*"));
63 headers.insert(ACCEPT_LANGUAGE, HeaderValue::from_static("en-US,en;q=0.9"));
64 headers.insert(
65 HeaderName::from_static("sec-ch-ua"),
66 HeaderValue::from_static(
67 "\"Not_A Brand\";v=\"8\", \"Chromium\";v=\"120\", \"Google Chrome\";v=\"120\"",
68 ),
69 );
70 headers.insert(
71 HeaderName::from_static("sec-ch-ua-mobile"),
72 HeaderValue::from_static("?0"),
73 );
74 headers.insert(
75 HeaderName::from_static("sec-ch-ua-platform"),
76 HeaderValue::from_static("\"Windows\""),
77 );
78 headers.insert(
79 HeaderName::from_static("sec-fetch-dest"),
80 HeaderValue::from_static("empty"),
81 );
82 headers.insert(
83 HeaderName::from_static("sec-fetch-mode"),
84 HeaderValue::from_static("cors"),
85 );
86 headers.insert(
87 HeaderName::from_static("sec-fetch-site"),
88 HeaderValue::from_static("same-origin"),
89 );
90 headers
91}
92
93pub fn rotate_cookies_headers() -> HeaderMap {
95 let mut headers = HeaderMap::new();
96 headers.insert(CONTENT_TYPE, HeaderValue::from_static("application/json"));
97 headers
98}
99
100pub fn upload_headers() -> HeaderMap {
104 let mut headers = HeaderMap::new();
105 headers.insert(
106 HeaderName::from_static("push-id"),
107 HeaderValue::from_static("feeds/mcudyrk2a4khkz"),
108 );
109 headers
110}
111
112#[derive(Debug, Clone, Default)]
117pub enum Model {
118 #[default]
120 Unspecified,
121 G2_0Flash,
123 G2_0FlashThinking,
125 G2_5Flash,
127 G2_5Pro,
129 G2_0ExpAdvanced,
131 G2_5ExpAdvanced,
133 G3_0Pro,
135 G3_0Flash,
137 G3_0Thinking,
139}
140
141impl Model {
142 pub fn name(&self) -> &'static str {
144 match self {
145 Model::Unspecified => "unspecified",
146 Model::G2_0Flash => "gemini-2.0-flash",
147 Model::G2_0FlashThinking => "gemini-2.0-flash-thinking",
148 Model::G2_5Flash => "gemini-2.5-flash",
149 Model::G2_5Pro => "gemini-2.5-pro",
150 Model::G2_0ExpAdvanced => "gemini-2.0-exp-advanced",
151 Model::G2_5ExpAdvanced => "gemini-2.5-exp-advanced",
152 Model::G3_0Pro => "gemini-3.0-pro",
153 Model::G3_0Flash => "gemini-3.0-flash",
154 Model::G3_0Thinking => "gemini-3.0-flash-thinking",
155 }
156 }
157
158 pub fn headers(&self) -> Option<HeaderMap> {
163 let header_value = match self {
164 Model::Unspecified => return None,
165 Model::G2_0Flash => r#"[1,null,null,null,"f299729663a2343f"]"#,
166 Model::G2_0FlashThinking => r#"[null,null,null,null,"7ca48d02d802f20a"]"#,
167 Model::G2_5Flash => r#"[1,null,null,null,"35609594dbe934d8"]"#,
168 Model::G2_5Pro => r#"[1,null,null,null,"2525e3954d185b3c"]"#,
169 Model::G2_0ExpAdvanced => r#"[null,null,null,null,"b1e46a6037e6aa9f"]"#,
170 Model::G2_5ExpAdvanced => r#"[null,null,null,null,"203e6bb81620bcfe"]"#,
171 Model::G3_0Pro => {
172 r#"[1,null,null,null,"e6fa609c3fa255c0",null,null,0,[4],null,null,2]"#
173 }
174 Model::G3_0Thinking => {
175 r#"[1,null,null,null,"e051ce1aa80aa576",null,null,0,[4],null,null,2]"#
176 }
177 Model::G3_0Flash => {
178 r#"[1,null,null,null,"56fdd199312815e2",null,null,0,[4],null,null,2]"#
179 }
180 };
181
182 let mut headers = HeaderMap::new();
183 headers.insert(
184 HeaderName::from_static("x-goog-ext-525001261-jspb"),
185 HeaderValue::from_str(header_value).unwrap(),
186 );
187 Some(headers)
188 }
189
190 pub fn is_advanced_only(&self) -> bool {
192 matches!(self, Model::G2_0ExpAdvanced | Model::G2_5ExpAdvanced)
193 }
194
195 pub fn from_name(name: &str) -> Option<Self> {
212 match name {
213 "unspecified" => Some(Model::Unspecified),
214 "gemini-2.0-flash" => Some(Model::G2_0Flash),
215 "gemini-2.0-flash-thinking" => Some(Model::G2_0FlashThinking),
216 "gemini-2.5-flash" => Some(Model::G2_5Flash),
217 "gemini-2.5-pro" => Some(Model::G2_5Pro),
218 "gemini-2.0-exp-advanced" => Some(Model::G2_0ExpAdvanced),
219 "gemini-2.5-exp-advanced" => Some(Model::G2_5ExpAdvanced),
220 "gemini-3.0-pro" => Some(Model::G3_0Pro),
221 "gemini-3.0-flash" => Some(Model::G3_0Flash),
222 "gemini-3.0-thinking" => Some(Model::G3_0Thinking),
223 _ => None,
224 }
225 }
226}