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,
13 #[serde(skip_serializing_if = "Option::is_none")]
15 pub coverage: Option<f64>,
16 #[serde(skip_serializing_if = "BTreeMap::is_empty", default)]
18 pub term_evidence: BTreeMap<String, usize>,
19 pub pages: usize,
21}
22
23#[derive(Debug, Clone, Default, PartialEq, Serialize, Deserialize)]
25#[serde(rename_all = "camelCase")]
26pub struct PagesiftMeta {
27 #[serde(skip_serializing_if = "Option::is_none")]
28 pub content_hash: Option<String>,
29 #[serde(skip_serializing_if = "Option::is_none")]
30 pub raw_hash: Option<String>,
31 #[serde(skip_serializing_if = "Option::is_none")]
32 pub text_hash: Option<String>,
33 #[serde(skip_serializing_if = "Vec::is_empty", default)]
34 pub redirect_chain: Vec<String>,
35 #[serde(skip_serializing_if = "Option::is_none")]
36 pub etag: Option<String>,
37 #[serde(skip_serializing_if = "Option::is_none")]
38 pub last_modified: Option<String>,
39 #[serde(skip_serializing_if = "std::ops::Not::not", default)]
40 pub not_modified: bool,
41 #[serde(skip_serializing_if = "Option::is_none")]
43 pub engine: Option<String>,
44 #[serde(skip_serializing_if = "Option::is_none")]
46 pub browser_engine: Option<String>,
47 #[serde(skip_serializing_if = "Vec::is_empty", default)]
48 pub warnings: Vec<String>,
49 #[serde(skip_serializing_if = "BTreeMap::is_empty", default)]
51 pub timings: BTreeMap<String, f64>,
52 #[serde(skip_serializing_if = "Option::is_none")]
54 pub duplicate_of: Option<String>,
55 #[serde(skip_serializing_if = "Option::is_none")]
57 pub relevance: Option<f32>,
58 #[serde(skip_serializing_if = "Option::is_none")]
60 pub query_filter: Option<QueryFilterStats>,
61 #[serde(skip_serializing_if = "Vec::is_empty", default)]
63 pub json_ld: Vec<Value>,
64}
65
66#[derive(Debug, Clone, Default, PartialEq, Serialize, Deserialize)]
67#[serde(rename_all = "camelCase")]
68pub struct QueryFilterStats {
69 pub kept_blocks: usize,
70 pub total_blocks: usize,
71 pub tokens_before: usize,
72 pub tokens_after: usize,
73}
74
75#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
77#[serde(rename_all = "camelCase")]
78pub struct ChangeTracking {
79 pub previous_scrape_at: Option<String>,
80 pub change_status: String,
82 pub visibility: String,
84 #[serde(skip_serializing_if = "Option::is_none")]
85 pub diff: Option<Value>,
86 #[serde(skip_serializing_if = "Option::is_none")]
87 pub json: Option<Value>,
88 #[serde(skip_serializing_if = "Option::is_none")]
89 pub pagesift: Option<Value>,
90}
91
92#[derive(Debug, Clone, Default, PartialEq, Serialize, Deserialize)]
93#[serde(rename_all = "camelCase")]
94pub struct Metadata {
95 #[serde(skip_serializing_if = "Option::is_none")]
96 pub title: Option<String>,
97 #[serde(skip_serializing_if = "Option::is_none")]
98 pub description: Option<String>,
99 #[serde(skip_serializing_if = "Option::is_none")]
100 pub language: Option<String>,
101 #[serde(skip_serializing_if = "Option::is_none")]
102 pub keywords: Option<String>,
103 #[serde(skip_serializing_if = "Option::is_none")]
104 pub robots: Option<String>,
105 #[serde(skip_serializing_if = "Option::is_none")]
106 pub favicon: Option<String>,
107 #[serde(skip_serializing_if = "Option::is_none")]
108 pub published_time: Option<String>,
109 #[serde(skip_serializing_if = "Option::is_none")]
110 pub author: Option<String>,
111 #[serde(skip_serializing_if = "Option::is_none")]
112 pub modified_time: Option<String>,
113 #[serde(skip_serializing_if = "Option::is_none")]
114 pub url: Option<String>,
115 #[serde(rename = "sourceURL", skip_serializing_if = "Option::is_none")]
116 pub source_url: Option<String>,
117 pub status_code: u16,
118 #[serde(skip_serializing_if = "Option::is_none")]
119 pub content_type: Option<String>,
120 #[serde(skip_serializing_if = "Option::is_none")]
121 pub error: Option<String>,
122 pub proxy_used: String,
123 #[serde(skip_serializing_if = "Option::is_none")]
124 pub cache_state: Option<String>,
125 #[serde(skip_serializing_if = "Option::is_none")]
126 pub cached_at: Option<String>,
127 #[serde(flatten)]
128 pub extra: BTreeMap<String, Value>,
129 #[serde(skip_serializing_if = "Option::is_none")]
130 pub pagesift: Option<PagesiftMeta>,
131}
132
133#[derive(Debug, Clone, Default, PartialEq, Serialize, Deserialize)]
134#[serde(rename_all = "camelCase")]
135pub struct Document {
136 #[serde(skip_serializing_if = "Option::is_none")]
137 pub markdown: Option<String>,
138 #[serde(skip_serializing_if = "Option::is_none")]
140 pub pages: Option<Vec<PageMarkdown>>,
141 #[serde(skip_serializing_if = "Option::is_none")]
142 pub html: Option<String>,
143 #[serde(skip_serializing_if = "Option::is_none")]
144 pub raw_html: Option<String>,
145 #[serde(skip_serializing_if = "Option::is_none")]
146 pub links: Option<Vec<String>>,
147 #[serde(skip_serializing_if = "Option::is_none")]
148 pub images: Option<Vec<String>>,
149 #[serde(skip_serializing_if = "Option::is_none")]
150 pub screenshot: Option<String>,
151 #[serde(skip_serializing_if = "Option::is_none")]
152 pub json: Option<Value>,
153 #[serde(skip_serializing_if = "Option::is_none")]
154 pub summary: Option<String>,
155 #[serde(skip_serializing_if = "Option::is_none")]
156 pub actions: Option<Value>,
157 #[serde(skip_serializing_if = "Option::is_none")]
158 pub warning: Option<String>,
159 #[serde(skip_serializing_if = "Option::is_none")]
160 pub change_tracking: Option<ChangeTracking>,
161 #[serde(skip_serializing_if = "Option::is_none")]
162 pub chunks: Option<Vec<DocChunk>>,
163 pub metadata: Metadata,
164}
165
166#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
168#[serde(rename_all = "camelCase")]
169pub struct PageMarkdown {
170 pub page_number: usize,
172 pub markdown: String,
173}
174
175#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
176#[serde(rename_all = "camelCase")]
177pub struct DocChunk {
178 pub text: String,
179 pub heading_path: Vec<String>,
180 pub start: usize,
181 pub end: usize,
182 pub tokens: usize,
183}
184
185#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
186pub struct MapLink {
187 pub url: String,
188 #[serde(skip_serializing_if = "Option::is_none")]
189 pub title: Option<String>,
190 #[serde(skip_serializing_if = "Option::is_none")]
191 pub description: Option<String>,
192}
193
194#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
195pub struct ScrapeResponse {
196 pub success: bool,
197 pub data: Document,
198 #[serde(skip_serializing_if = "Option::is_none")]
199 pub warning: Option<String>,
200}
201
202#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
203#[serde(rename_all = "camelCase")]
204pub struct JobStarted {
205 pub success: bool,
206 pub id: String,
207 pub url: String,
208 #[serde(rename = "invalidURLs", skip_serializing_if = "Option::is_none")]
209 pub invalid_urls: Option<Vec<String>>,
210}
211
212#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
213#[serde(rename_all = "camelCase")]
214pub struct JobStatus {
215 pub success: bool,
216 pub status: String,
217 pub completed: usize,
218 pub total: usize,
219 pub credits_used: usize,
220 pub expires_at: String,
221 #[serde(skip_serializing_if = "Option::is_none")]
222 pub next: Option<String>,
223 pub data: Vec<Document>,
224 #[serde(skip_serializing_if = "Option::is_none")]
225 pub pagesift: Option<CrawlSummary>,
226}
227
228#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
229pub struct JobError {
230 pub id: String,
231 pub timestamp: String,
232 pub url: String,
233 pub code: String,
234 pub error: String,
235}
236
237#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
238#[serde(rename_all = "camelCase")]
239pub struct JobErrors {
240 pub errors: Vec<JobError>,
241 pub robots_blocked: Vec<String>,
242}
243
244#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
245pub struct MapResponse {
246 pub success: bool,
247 pub links: Vec<MapLink>,
248}