1use serde::{Deserialize, Serialize};
4use serde_json::Value;
5use std::collections::BTreeMap;
6
7#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
9#[serde(rename_all = "camelCase")]
10pub struct CrawlSummary {
11 pub stop_reason: String,
14 #[serde(skip_serializing_if = "Option::is_none")]
16 pub coverage: Option<f64>,
17 #[serde(skip_serializing_if = "BTreeMap::is_empty", default)]
19 pub term_evidence: BTreeMap<String, usize>,
20 pub pages: usize,
22}
23
24#[derive(Debug, Clone, Default, PartialEq, Serialize, Deserialize)]
27#[serde(rename_all = "camelCase")]
28pub struct CrawlTrace {
29 pub depth: usize,
31 #[serde(skip_serializing_if = "Option::is_none")]
33 pub parent: Option<String>,
34 #[serde(skip_serializing_if = "Option::is_none")]
36 pub score: Option<f32>,
37 #[serde(skip_serializing_if = "Option::is_none")]
39 pub attachment_of: Option<String>,
40}
41
42#[derive(Debug, Clone, Default, PartialEq, Eq, Serialize, Deserialize)]
44#[serde(rename_all = "camelCase")]
45pub struct OcrMeta {
46 pub engine: String,
47 pub model: String,
48 pub device: String,
50 pub pages: usize,
52 pub fallback: bool,
54}
55
56#[derive(Debug, Clone, Default, PartialEq, Serialize, Deserialize)]
57#[serde(rename_all = "camelCase")]
58pub struct PagesiftMeta {
59 #[serde(skip_serializing_if = "Option::is_none")]
60 pub content_hash: Option<String>,
61 #[serde(skip_serializing_if = "Option::is_none")]
62 pub raw_hash: Option<String>,
63 #[serde(skip_serializing_if = "Option::is_none")]
64 pub text_hash: Option<String>,
65 #[serde(skip_serializing_if = "Vec::is_empty", default)]
66 pub redirect_chain: Vec<String>,
67 #[serde(skip_serializing_if = "Option::is_none")]
68 pub etag: Option<String>,
69 #[serde(skip_serializing_if = "Option::is_none")]
70 pub last_modified: Option<String>,
71 #[serde(skip_serializing_if = "std::ops::Not::not", default)]
72 pub not_modified: bool,
73 #[serde(skip_serializing_if = "Option::is_none")]
75 pub engine: Option<String>,
76 #[serde(skip_serializing_if = "Option::is_none")]
78 pub browser_engine: Option<String>,
79 #[serde(skip_serializing_if = "Option::is_none")]
81 pub browser_fingerprint: Option<String>,
82 #[serde(skip_serializing_if = "Vec::is_empty", default)]
83 pub warnings: Vec<String>,
84 #[serde(skip_serializing_if = "BTreeMap::is_empty", default)]
86 pub timings: BTreeMap<String, f64>,
87 #[serde(skip_serializing_if = "Option::is_none")]
89 pub ocr: Option<OcrMeta>,
90 #[serde(skip_serializing_if = "Option::is_none")]
92 pub duplicate_of: Option<String>,
93 #[serde(skip_serializing_if = "Option::is_none")]
95 pub relevance: Option<f32>,
96 #[serde(skip_serializing_if = "Option::is_none")]
98 pub crawl: Option<CrawlTrace>,
99 #[serde(skip_serializing_if = "Option::is_none")]
101 pub query_filter: Option<QueryFilterStats>,
102 #[serde(skip_serializing_if = "Vec::is_empty", default)]
104 pub json_ld: Vec<Value>,
105 #[serde(skip_serializing_if = "Option::is_none")]
108 pub plan: Option<PlanTrace>,
109}
110
111#[derive(Debug, Clone, Default, PartialEq, Serialize, Deserialize)]
113#[serde(rename_all = "camelCase")]
114pub struct PlanTrace {
115 pub steps: Vec<PlanStep>,
116}
117
118#[derive(Debug, Clone, Default, PartialEq, Serialize, Deserialize)]
119#[serde(rename_all = "camelCase")]
120pub struct PlanStep {
121 pub action: String,
123 pub chosen: bool,
124 pub learned: bool,
126 #[serde(skip_serializing_if = "Option::is_none")]
128 pub p: Option<f64>,
129 #[serde(skip_serializing_if = "Option::is_none")]
131 pub value: Option<f64>,
132 #[serde(skip_serializing_if = "Option::is_none")]
134 pub charge: Option<f64>,
135 #[serde(skip_serializing_if = "Option::is_none")]
137 pub quality: Option<f64>,
138 #[serde(skip_serializing_if = "Option::is_none")]
140 pub blocks: Option<[usize; 3]>, }
142
143#[derive(Debug, Clone, Default, PartialEq, Serialize, Deserialize)]
144#[serde(rename_all = "camelCase")]
145pub struct QueryFilterStats {
146 pub kept_blocks: usize,
147 pub total_blocks: usize,
148 pub tokens_before: usize,
149 pub tokens_after: usize,
150}
151
152#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
154#[serde(rename_all = "camelCase")]
155pub struct ChangeTracking {
156 pub previous_scrape_at: Option<String>,
157 pub change_status: String,
159 pub visibility: String,
161 #[serde(skip_serializing_if = "Option::is_none")]
162 pub diff: Option<Value>,
163 #[serde(skip_serializing_if = "Option::is_none")]
164 pub json: Option<Value>,
165 #[serde(skip_serializing_if = "Option::is_none")]
166 pub pagesift: Option<Value>,
167}
168
169#[derive(Debug, Clone, Default, PartialEq, Serialize, Deserialize)]
170#[serde(rename_all = "camelCase")]
171pub struct Metadata {
172 #[serde(skip_serializing_if = "Option::is_none")]
174 pub scrape_id: Option<String>,
175 #[serde(skip_serializing_if = "Option::is_none")]
176 pub title: Option<String>,
177 #[serde(skip_serializing_if = "Option::is_none")]
178 pub description: Option<String>,
179 #[serde(skip_serializing_if = "Option::is_none")]
180 pub language: Option<String>,
181 #[serde(skip_serializing_if = "Option::is_none")]
182 pub keywords: Option<String>,
183 #[serde(skip_serializing_if = "Option::is_none")]
184 pub robots: Option<String>,
185 #[serde(skip_serializing_if = "Option::is_none")]
186 pub favicon: Option<String>,
187 #[serde(skip_serializing_if = "Option::is_none")]
188 pub published_time: Option<String>,
189 #[serde(skip_serializing_if = "Option::is_none")]
190 pub author: Option<String>,
191 #[serde(skip_serializing_if = "Option::is_none")]
192 pub modified_time: Option<String>,
193 #[serde(skip_serializing_if = "Option::is_none")]
194 pub url: Option<String>,
195 #[serde(rename = "sourceURL", skip_serializing_if = "Option::is_none")]
196 pub source_url: Option<String>,
197 pub status_code: u16,
198 #[serde(skip_serializing_if = "Option::is_none")]
199 pub content_type: Option<String>,
200 #[serde(skip_serializing_if = "Option::is_none")]
201 pub error: Option<String>,
202 pub proxy_used: String,
203 #[serde(skip_serializing_if = "Option::is_none")]
204 pub cache_state: Option<String>,
205 #[serde(skip_serializing_if = "Option::is_none")]
206 pub cached_at: Option<String>,
207 #[serde(flatten)]
208 pub extra: BTreeMap<String, Value>,
209 #[serde(skip_serializing_if = "Option::is_none")]
210 pub pagesift: Option<PagesiftMeta>,
211}
212
213#[derive(Debug, Clone, Default, PartialEq, Serialize, Deserialize)]
214#[serde(rename_all = "camelCase")]
215pub struct Document {
216 #[serde(skip_serializing_if = "Option::is_none")]
217 pub markdown: Option<String>,
218 #[serde(skip_serializing_if = "Option::is_none")]
220 pub pages: Option<Vec<PageMarkdown>>,
221 #[serde(skip_serializing_if = "Option::is_none")]
222 pub html: Option<String>,
223 #[serde(skip_serializing_if = "Option::is_none")]
224 pub raw_html: Option<String>,
225 #[serde(skip_serializing_if = "Option::is_none")]
226 pub links: Option<Vec<String>>,
227 #[serde(skip)]
229 pub link_text: Option<Vec<String>>,
230 #[serde(skip)]
232 pub alternates: Vec<(String, String)>,
233 #[serde(skip)]
236 pub quality: Option<f64>,
237 #[serde(skip_serializing_if = "Option::is_none")]
238 pub images: Option<Vec<String>>,
239 #[serde(skip_serializing_if = "Option::is_none")]
240 pub screenshot: Option<String>,
241 #[serde(skip_serializing_if = "Option::is_none")]
242 pub json: Option<Value>,
243 #[serde(skip_serializing_if = "Option::is_none")]
245 pub extract: Option<Value>,
246 #[serde(skip_serializing_if = "Option::is_none")]
247 pub summary: Option<String>,
248 #[serde(skip_serializing_if = "Option::is_none")]
249 pub actions: Option<Value>,
250 #[serde(skip_serializing_if = "Option::is_none")]
251 pub warning: Option<String>,
252 #[serde(skip_serializing_if = "Option::is_none")]
253 pub change_tracking: Option<ChangeTracking>,
254 #[serde(skip_serializing_if = "Option::is_none")]
255 pub chunks: Option<Vec<DocChunk>>,
256 #[serde(skip_serializing_if = "Vec::is_empty", default)]
259 pub attachments: Vec<super::Attachment>,
260 pub metadata: Metadata,
261}
262
263#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
265#[serde(rename_all = "camelCase")]
266pub struct PageMarkdown {
267 pub page_number: usize,
269 pub markdown: String,
270}
271
272#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
273#[serde(rename_all = "camelCase")]
274pub struct DocChunk {
275 pub text: String,
276 pub heading_path: Vec<String>,
277 pub start: usize,
278 pub end: usize,
279 pub tokens: usize,
280}
281
282#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
283pub struct MapLink {
284 pub url: String,
285 #[serde(skip_serializing_if = "Option::is_none")]
286 pub title: Option<String>,
287 #[serde(skip_serializing_if = "Option::is_none")]
288 pub description: Option<String>,
289}
290
291#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
292pub struct ScrapeResponse {
293 pub success: bool,
294 pub data: Document,
295 #[serde(skip_serializing_if = "Option::is_none")]
296 pub warning: Option<String>,
297}
298
299#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
300#[serde(rename_all = "camelCase")]
301pub struct JobStarted {
302 pub success: bool,
303 pub id: String,
304 pub url: String,
305 #[serde(rename = "invalidURLs", skip_serializing_if = "Option::is_none")]
306 pub invalid_urls: Option<Vec<String>>,
307 #[serde(default, skip_serializing_if = "Vec::is_empty")]
309 pub warnings: Vec<String>,
310}
311
312#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
313#[serde(rename_all = "camelCase")]
314pub struct JobStatus {
315 pub success: bool,
316 pub status: String,
317 pub completed: usize,
318 pub total: usize,
319 pub credits_used: usize,
320 pub expires_at: String,
321 #[serde(skip_serializing_if = "Option::is_none")]
322 pub next: Option<String>,
323 pub data: Vec<Document>,
324 #[serde(skip_serializing_if = "Option::is_none")]
325 pub pagesift: Option<CrawlSummary>,
326}
327
328#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
329pub struct JobError {
330 pub id: String,
331 pub timestamp: String,
332 pub url: String,
333 pub code: String,
334 pub error: String,
335}
336
337#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
338#[serde(rename_all = "camelCase")]
339pub struct JobErrors {
340 pub errors: Vec<JobError>,
341 pub robots_blocked: Vec<String>,
342}
343
344#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
345pub struct MapResponse {
346 pub success: bool,
347 pub links: Vec<MapLink>,
348 #[serde(default, skip_serializing_if = "Vec::is_empty")]
350 pub warnings: Vec<String>,
351}