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")]
139 pub html: Option<String>,
140 #[serde(skip_serializing_if = "Option::is_none")]
141 pub raw_html: Option<String>,
142 #[serde(skip_serializing_if = "Option::is_none")]
143 pub links: Option<Vec<String>>,
144 #[serde(skip_serializing_if = "Option::is_none")]
145 pub images: Option<Vec<String>>,
146 #[serde(skip_serializing_if = "Option::is_none")]
147 pub screenshot: Option<String>,
148 #[serde(skip_serializing_if = "Option::is_none")]
149 pub json: Option<Value>,
150 #[serde(skip_serializing_if = "Option::is_none")]
151 pub summary: Option<String>,
152 #[serde(skip_serializing_if = "Option::is_none")]
153 pub actions: Option<Value>,
154 #[serde(skip_serializing_if = "Option::is_none")]
155 pub warning: Option<String>,
156 #[serde(skip_serializing_if = "Option::is_none")]
157 pub change_tracking: Option<ChangeTracking>,
158 #[serde(skip_serializing_if = "Option::is_none")]
159 pub chunks: Option<Vec<DocChunk>>,
160 pub metadata: Metadata,
161}
162
163#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
164#[serde(rename_all = "camelCase")]
165pub struct DocChunk {
166 pub text: String,
167 pub heading_path: Vec<String>,
168 pub start: usize,
169 pub end: usize,
170 pub tokens: usize,
171}
172
173#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
174pub struct MapLink {
175 pub url: String,
176 #[serde(skip_serializing_if = "Option::is_none")]
177 pub title: Option<String>,
178 #[serde(skip_serializing_if = "Option::is_none")]
179 pub description: Option<String>,
180}
181
182#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
183pub struct ScrapeResponse {
184 pub success: bool,
185 pub data: Document,
186 #[serde(skip_serializing_if = "Option::is_none")]
187 pub warning: Option<String>,
188}
189
190#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
191#[serde(rename_all = "camelCase")]
192pub struct JobStarted {
193 pub success: bool,
194 pub id: String,
195 pub url: String,
196 #[serde(rename = "invalidURLs", skip_serializing_if = "Option::is_none")]
197 pub invalid_urls: Option<Vec<String>>,
198}
199
200#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
201#[serde(rename_all = "camelCase")]
202pub struct JobStatus {
203 pub success: bool,
204 pub status: String,
205 pub completed: usize,
206 pub total: usize,
207 pub credits_used: usize,
208 pub expires_at: String,
209 #[serde(skip_serializing_if = "Option::is_none")]
210 pub next: Option<String>,
211 pub data: Vec<Document>,
212 #[serde(skip_serializing_if = "Option::is_none")]
213 pub pagesift: Option<CrawlSummary>,
214}
215
216#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
217pub struct JobError {
218 pub id: String,
219 pub timestamp: String,
220 pub url: String,
221 pub code: String,
222 pub error: String,
223}
224
225#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
226#[serde(rename_all = "camelCase")]
227pub struct JobErrors {
228 pub errors: Vec<JobError>,
229 pub robots_blocked: Vec<String>,
230}
231
232#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
233pub struct MapResponse {
234 pub success: bool,
235 pub links: Vec<MapLink>,
236}