1use serde::{Deserialize, Serialize};
4use url::Url;
5
6use crate::crawl::{RobotsFile, SitemapSummary};
7use crate::page::PageRecord;
8
9#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
11pub struct Edge {
12 pub from: u32,
14 pub to: u32,
16 pub anchor: u32,
18 pub nofollow: bool,
19}
20
21#[derive(Debug, Clone, Default, PartialEq, Eq, Serialize, Deserialize)]
24pub struct LinkGraph {
25 pub edges: Vec<Edge>,
26 pub anchors: Vec<String>,
27}
28
29impl LinkGraph {
30 pub fn anchor(&self, e: &Edge) -> &str {
31 &self.anchors[e.anchor as usize]
32 }
33}
34
35#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
37#[serde(rename_all = "snake_case", tag = "kind", content = "reason")]
38pub enum StopReason {
39 Completed,
40 PageLimit,
41 TimeLimit,
42 Unreachable(String),
43 Blocked(String),
44 RobotsBlocked,
45}
46
47impl StopReason {
48 pub fn is_complete(&self) -> bool {
50 matches!(self, StopReason::Completed)
51 }
52
53 pub fn crawl_ran(&self) -> bool {
55 matches!(
56 self,
57 StopReason::Completed | StopReason::PageLimit | StopReason::TimeLimit
58 )
59 }
60}
61
62pub const UNREACHABLE_REASON_PREFIX: &str = "site unreachable";
64pub const BLOCKED_REASON_PREFIX: &str = "site blocked our crawler";
66
67#[derive(Debug, Clone, Copy, PartialEq, Eq)]
69pub enum SiteFault {
70 Unreachable,
72 Blocked,
74}
75
76impl SiteFault {
77 pub fn from_failure_reason(reason: &str) -> Option<SiteFault> {
80 if reason.starts_with(UNREACHABLE_REASON_PREFIX) {
81 Some(SiteFault::Unreachable)
82 } else if reason.starts_with(BLOCKED_REASON_PREFIX) {
83 Some(SiteFault::Blocked)
84 } else {
85 None
86 }
87 }
88}
89
90#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
92pub struct Progress {
93 pub pages_done: u32,
94 pub queued: u32,
95 pub failures: u32,
96 pub depth: u16,
97 pub elapsed_ms: u64,
98}
99
100#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
101pub struct CrawlOutput {
102 pub origin: Url,
104 pub pages: Vec<PageRecord>,
105 pub links: LinkGraph,
106 pub robots: Option<RobotsFile>,
107 pub sitemap: SitemapSummary,
108 pub stop: StopReason,
109 pub duration_ms: u64,
110}