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, Serialize, Deserialize)]
43#[serde(rename_all = "camelCase")]
44pub struct PagesiftMeta {
45 #[serde(skip_serializing_if = "Option::is_none")]
46 pub content_hash: Option<String>,
47 #[serde(skip_serializing_if = "Option::is_none")]
48 pub raw_hash: Option<String>,
49 #[serde(skip_serializing_if = "Option::is_none")]
50 pub text_hash: Option<String>,
51 #[serde(skip_serializing_if = "Vec::is_empty", default)]
52 pub redirect_chain: Vec<String>,
53 #[serde(skip_serializing_if = "Option::is_none")]
54 pub etag: Option<String>,
55 #[serde(skip_serializing_if = "Option::is_none")]
56 pub last_modified: Option<String>,
57 #[serde(skip_serializing_if = "std::ops::Not::not", default)]
58 pub not_modified: bool,
59 #[serde(skip_serializing_if = "Option::is_none")]
61 pub engine: Option<String>,
62 #[serde(skip_serializing_if = "Option::is_none")]
64 pub browser_engine: Option<String>,
65 #[serde(skip_serializing_if = "Vec::is_empty", default)]
66 pub warnings: Vec<String>,
67 #[serde(skip_serializing_if = "BTreeMap::is_empty", default)]
69 pub timings: BTreeMap<String, f64>,
70 #[serde(skip_serializing_if = "Option::is_none")]
72 pub duplicate_of: Option<String>,
73 #[serde(skip_serializing_if = "Option::is_none")]
75 pub relevance: Option<f32>,
76 #[serde(skip_serializing_if = "Option::is_none")]
78 pub crawl: Option<CrawlTrace>,
79 #[serde(skip_serializing_if = "Option::is_none")]
81 pub query_filter: Option<QueryFilterStats>,
82 #[serde(skip_serializing_if = "Vec::is_empty", default)]
84 pub json_ld: Vec<Value>,
85 #[serde(skip_serializing_if = "Option::is_none")]
88 pub plan: Option<PlanTrace>,
89}
90
91#[derive(Debug, Clone, Default, PartialEq, Serialize, Deserialize)]
93#[serde(rename_all = "camelCase")]
94pub struct PlanTrace {
95 pub steps: Vec<PlanStep>,
96}
97
98#[derive(Debug, Clone, Default, PartialEq, Serialize, Deserialize)]
99#[serde(rename_all = "camelCase")]
100pub struct PlanStep {
101 pub action: String,
103 pub chosen: bool,
104 pub learned: bool,
106 #[serde(skip_serializing_if = "Option::is_none")]
108 pub p: Option<f64>,
109 #[serde(skip_serializing_if = "Option::is_none")]
111 pub value: Option<f64>,
112 #[serde(skip_serializing_if = "Option::is_none")]
114 pub charge: Option<f64>,
115 #[serde(skip_serializing_if = "Option::is_none")]
117 pub quality: Option<f64>,
118 #[serde(skip_serializing_if = "Option::is_none")]
120 pub blocks: Option<[usize; 3]>, }
122
123#[derive(Debug, Clone, Default, PartialEq, Serialize, Deserialize)]
124#[serde(rename_all = "camelCase")]
125pub struct QueryFilterStats {
126 pub kept_blocks: usize,
127 pub total_blocks: usize,
128 pub tokens_before: usize,
129 pub tokens_after: usize,
130}
131
132#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
134#[serde(rename_all = "camelCase")]
135pub struct ChangeTracking {
136 pub previous_scrape_at: Option<String>,
137 pub change_status: String,
139 pub visibility: String,
141 #[serde(skip_serializing_if = "Option::is_none")]
142 pub diff: Option<Value>,
143 #[serde(skip_serializing_if = "Option::is_none")]
144 pub json: Option<Value>,
145 #[serde(skip_serializing_if = "Option::is_none")]
146 pub pagesift: Option<Value>,
147}
148
149#[derive(Debug, Clone, Default, PartialEq, Serialize, Deserialize)]
150#[serde(rename_all = "camelCase")]
151pub struct Metadata {
152 #[serde(skip_serializing_if = "Option::is_none")]
153 pub title: Option<String>,
154 #[serde(skip_serializing_if = "Option::is_none")]
155 pub description: Option<String>,
156 #[serde(skip_serializing_if = "Option::is_none")]
157 pub language: Option<String>,
158 #[serde(skip_serializing_if = "Option::is_none")]
159 pub keywords: Option<String>,
160 #[serde(skip_serializing_if = "Option::is_none")]
161 pub robots: Option<String>,
162 #[serde(skip_serializing_if = "Option::is_none")]
163 pub favicon: Option<String>,
164 #[serde(skip_serializing_if = "Option::is_none")]
165 pub published_time: Option<String>,
166 #[serde(skip_serializing_if = "Option::is_none")]
167 pub author: Option<String>,
168 #[serde(skip_serializing_if = "Option::is_none")]
169 pub modified_time: Option<String>,
170 #[serde(skip_serializing_if = "Option::is_none")]
171 pub url: Option<String>,
172 #[serde(rename = "sourceURL", skip_serializing_if = "Option::is_none")]
173 pub source_url: Option<String>,
174 pub status_code: u16,
175 #[serde(skip_serializing_if = "Option::is_none")]
176 pub content_type: Option<String>,
177 #[serde(skip_serializing_if = "Option::is_none")]
178 pub error: Option<String>,
179 pub proxy_used: String,
180 #[serde(skip_serializing_if = "Option::is_none")]
181 pub cache_state: Option<String>,
182 #[serde(skip_serializing_if = "Option::is_none")]
183 pub cached_at: Option<String>,
184 #[serde(flatten)]
185 pub extra: BTreeMap<String, Value>,
186 #[serde(skip_serializing_if = "Option::is_none")]
187 pub pagesift: Option<PagesiftMeta>,
188}
189
190#[derive(Debug, Clone, Default, PartialEq, Serialize, Deserialize)]
191#[serde(rename_all = "camelCase")]
192pub struct Document {
193 #[serde(skip_serializing_if = "Option::is_none")]
194 pub markdown: Option<String>,
195 #[serde(skip_serializing_if = "Option::is_none")]
197 pub pages: Option<Vec<PageMarkdown>>,
198 #[serde(skip_serializing_if = "Option::is_none")]
199 pub html: Option<String>,
200 #[serde(skip_serializing_if = "Option::is_none")]
201 pub raw_html: Option<String>,
202 #[serde(skip_serializing_if = "Option::is_none")]
203 pub links: Option<Vec<String>>,
204 #[serde(skip)]
206 pub link_text: Option<Vec<String>>,
207 #[serde(skip)]
209 pub alternates: Vec<(String, String)>,
210 #[serde(skip)]
213 pub quality: Option<f64>,
214 #[serde(skip_serializing_if = "Option::is_none")]
215 pub images: Option<Vec<String>>,
216 #[serde(skip_serializing_if = "Option::is_none")]
217 pub screenshot: Option<String>,
218 #[serde(skip_serializing_if = "Option::is_none")]
219 pub json: Option<Value>,
220 #[serde(skip_serializing_if = "Option::is_none")]
221 pub summary: Option<String>,
222 #[serde(skip_serializing_if = "Option::is_none")]
223 pub actions: Option<Value>,
224 #[serde(skip_serializing_if = "Option::is_none")]
225 pub warning: Option<String>,
226 #[serde(skip_serializing_if = "Option::is_none")]
227 pub change_tracking: Option<ChangeTracking>,
228 #[serde(skip_serializing_if = "Option::is_none")]
229 pub chunks: Option<Vec<DocChunk>>,
230 #[serde(skip_serializing_if = "Vec::is_empty", default)]
233 pub attachments: Vec<super::Attachment>,
234 pub metadata: Metadata,
235}
236
237#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
239#[serde(rename_all = "camelCase")]
240pub struct PageMarkdown {
241 pub page_number: usize,
243 pub markdown: String,
244}
245
246#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
247#[serde(rename_all = "camelCase")]
248pub struct DocChunk {
249 pub text: String,
250 pub heading_path: Vec<String>,
251 pub start: usize,
252 pub end: usize,
253 pub tokens: usize,
254}
255
256#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
257pub struct MapLink {
258 pub url: String,
259 #[serde(skip_serializing_if = "Option::is_none")]
260 pub title: Option<String>,
261 #[serde(skip_serializing_if = "Option::is_none")]
262 pub description: Option<String>,
263}
264
265#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
266pub struct ScrapeResponse {
267 pub success: bool,
268 pub data: Document,
269 #[serde(skip_serializing_if = "Option::is_none")]
270 pub warning: Option<String>,
271}
272
273#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
274#[serde(rename_all = "camelCase")]
275pub struct JobStarted {
276 pub success: bool,
277 pub id: String,
278 pub url: String,
279 #[serde(rename = "invalidURLs", skip_serializing_if = "Option::is_none")]
280 pub invalid_urls: Option<Vec<String>>,
281}
282
283#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
284#[serde(rename_all = "camelCase")]
285pub struct JobStatus {
286 pub success: bool,
287 pub status: String,
288 pub completed: usize,
289 pub total: usize,
290 pub credits_used: usize,
291 pub expires_at: String,
292 #[serde(skip_serializing_if = "Option::is_none")]
293 pub next: Option<String>,
294 pub data: Vec<Document>,
295 #[serde(skip_serializing_if = "Option::is_none")]
296 pub pagesift: Option<CrawlSummary>,
297}
298
299#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
300pub struct JobError {
301 pub id: String,
302 pub timestamp: String,
303 pub url: String,
304 pub code: String,
305 pub error: String,
306}
307
308#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
309#[serde(rename_all = "camelCase")]
310pub struct JobErrors {
311 pub errors: Vec<JobError>,
312 pub robots_blocked: Vec<String>,
313}
314
315#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
316pub struct MapResponse {
317 pub success: bool,
318 pub links: Vec<MapLink>,
319}