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)]
212 pub quality: Option<f64>,
213 #[serde(skip_serializing_if = "Option::is_none")]
214 pub images: Option<Vec<String>>,
215 #[serde(skip_serializing_if = "Option::is_none")]
216 pub screenshot: Option<String>,
217 #[serde(skip_serializing_if = "Option::is_none")]
218 pub json: Option<Value>,
219 #[serde(skip_serializing_if = "Option::is_none")]
220 pub summary: Option<String>,
221 #[serde(skip_serializing_if = "Option::is_none")]
222 pub actions: Option<Value>,
223 #[serde(skip_serializing_if = "Option::is_none")]
224 pub warning: Option<String>,
225 #[serde(skip_serializing_if = "Option::is_none")]
226 pub change_tracking: Option<ChangeTracking>,
227 #[serde(skip_serializing_if = "Option::is_none")]
228 pub chunks: Option<Vec<DocChunk>>,
229 #[serde(skip_serializing_if = "Vec::is_empty", default)]
232 pub attachments: Vec<super::Attachment>,
233 pub metadata: Metadata,
234}
235
236#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
238#[serde(rename_all = "camelCase")]
239pub struct PageMarkdown {
240 pub page_number: usize,
242 pub markdown: String,
243}
244
245#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
246#[serde(rename_all = "camelCase")]
247pub struct DocChunk {
248 pub text: String,
249 pub heading_path: Vec<String>,
250 pub start: usize,
251 pub end: usize,
252 pub tokens: usize,
253}
254
255#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
256pub struct MapLink {
257 pub url: String,
258 #[serde(skip_serializing_if = "Option::is_none")]
259 pub title: Option<String>,
260 #[serde(skip_serializing_if = "Option::is_none")]
261 pub description: Option<String>,
262}
263
264#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
265pub struct ScrapeResponse {
266 pub success: bool,
267 pub data: Document,
268 #[serde(skip_serializing_if = "Option::is_none")]
269 pub warning: Option<String>,
270}
271
272#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
273#[serde(rename_all = "camelCase")]
274pub struct JobStarted {
275 pub success: bool,
276 pub id: String,
277 pub url: String,
278 #[serde(rename = "invalidURLs", skip_serializing_if = "Option::is_none")]
279 pub invalid_urls: Option<Vec<String>>,
280}
281
282#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
283#[serde(rename_all = "camelCase")]
284pub struct JobStatus {
285 pub success: bool,
286 pub status: String,
287 pub completed: usize,
288 pub total: usize,
289 pub credits_used: usize,
290 pub expires_at: String,
291 #[serde(skip_serializing_if = "Option::is_none")]
292 pub next: Option<String>,
293 pub data: Vec<Document>,
294 #[serde(skip_serializing_if = "Option::is_none")]
295 pub pagesift: Option<CrawlSummary>,
296}
297
298#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
299pub struct JobError {
300 pub id: String,
301 pub timestamp: String,
302 pub url: String,
303 pub code: String,
304 pub error: String,
305}
306
307#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
308#[serde(rename_all = "camelCase")]
309pub struct JobErrors {
310 pub errors: Vec<JobError>,
311 pub robots_blocked: Vec<String>,
312}
313
314#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
315pub struct MapResponse {
316 pub success: bool,
317 pub links: Vec<MapLink>,
318}