crawlberg 1.2.1 → 1.3.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,6 +1,11 @@
1
+ # This file is auto-generated by alef — DO NOT EDIT.
2
+ # alef:hash:6d3e12955a76fb5c98a03dc656a5b76ae41ba095ad388a22cb35ce647d7159fc
3
+ # To regenerate: alef generate
4
+ # To verify freshness: alef verify
5
+
1
6
  [package]
2
7
  name = "crawlberg-rb"
3
- version = "1.2.1"
8
+ version = "1.3.3"
4
9
  edition = "2024"
5
10
  license = "MIT"
6
11
  description = "High-performance web crawling engine"
@@ -17,10 +22,22 @@ path = "../src/lib.rs"
17
22
  crate-type = ["cdylib"]
18
23
 
19
24
  [dependencies]
20
- crawlberg = { version = "1.2.1", features = ["interact", "browser-chromiumoxide"] }
25
+ crawlberg = { version = "1.3.3", features = ["interact", "browser-chromiumoxide"] }
21
26
  futures = "0.3"
22
27
  magnus = "0.8"
23
28
  rb-sys = ">=0.9, <0.9.128"
24
29
  serde = { version = "1", features = ["derive"] }
25
30
  serde_json = "1"
26
31
  tokio = { version = "1", features = ["rt-multi-thread"] }
32
+
33
+ # This crate deliberately does not use `[lints]` / `workspace = true`: its C-ABI /
34
+ # PyO3 / napi / ext-php-rs / NIF boundary requires `unsafe` code, and the workspace's
35
+ # `[workspace.lints.rust]` sets `unsafe_code = "deny"` -- an all-or-nothing table that
36
+ # would turn every such boundary into a compile error. The `[lints.clippy]` block below
37
+ # instead carries the subset of the workspace's deny-by-default lint policy this crate
38
+ # can actually satisfy. ~keep
39
+ [lints.clippy]
40
+ all = { level = "warn", priority = -1 }
41
+ dbg_macro = "deny"
42
+ print_stderr = "deny"
43
+ print_stdout = "deny"
@@ -1,3 +1,8 @@
1
+ # This file is auto-generated by alef — DO NOT EDIT.
2
+ # alef:hash:7e8b3cef132610f31102ee2069cf33d39e5e1ece68f870166e669e04f476544e
3
+ # To regenerate: alef generate
4
+ # To verify freshness: alef verify
5
+
1
6
  # frozen_string_literal: true
2
7
 
3
8
  require "mkmf"
@@ -1,5 +1,5 @@
1
1
  // This file is auto-generated by alef. DO NOT EDIT.
2
- // alef:hash:0ce4d753fdb4854e44358639dcbaebee3449a4afa142dbc4f0a72aa72c214648
2
+ // alef:hash:9312cb415995255492557432651036cfe6b0edf4ccd0b27a88d0cb3c5a7d1466
3
3
  // Re-generate with: alef generate
4
4
  #![allow(dead_code, unused_imports, unused_variables)]
5
5
  #![allow(
@@ -316,7 +316,7 @@ impl ContentConfig {
316
316
  exclude_selectors: kwargs
317
317
  .get(ruby.to_symbol("exclude_selectors"))
318
318
  .and_then(|v| <Vec<String>>::try_convert(v).ok())
319
- .unwrap_or_default(),
319
+ .unwrap_or(vec!["noscript".to_string()]),
320
320
  skip_images: kwargs
321
321
  .get(ruby.to_symbol("skip_images"))
322
322
  .and_then(|v| bool::try_convert(v).ok())
@@ -467,7 +467,7 @@ impl BrowserConfig {
467
467
  wait: kwargs
468
468
  .get(ruby.to_symbol("wait"))
469
469
  .and_then(|v| BrowserWait::try_convert(v).ok())
470
- .unwrap_or_default(),
470
+ .unwrap_or(BrowserWait::NetworkIdle),
471
471
  wait_selector: kwargs
472
472
  .get(ruby.to_symbol("wait_selector"))
473
473
  .and_then(|v| String::try_convert(v).ok()),
@@ -559,6 +559,10 @@ pub struct CrawlConfig {
559
559
  max_pages: Option<usize>,
560
560
  max_links_per_page: Option<usize>,
561
561
  max_concurrent: Option<usize>,
562
+ crawl_strategy: CrawlStrategyKind,
563
+ content_filter: Option<ContentFilterKind>,
564
+ bm25_query: Option<String>,
565
+ bm25_threshold: Option<f64>,
562
566
  respect_robots_txt: bool,
563
567
  soft_http_errors: bool,
564
568
  user_agent: Option<String>,
@@ -654,6 +658,19 @@ impl CrawlConfig {
654
658
  max_concurrent: kwargs
655
659
  .get(ruby.to_symbol("max_concurrent"))
656
660
  .and_then(|v| usize::try_convert(v).ok()),
661
+ crawl_strategy: kwargs
662
+ .get(ruby.to_symbol("crawl_strategy"))
663
+ .and_then(|v| CrawlStrategyKind::try_convert(v).ok())
664
+ .unwrap_or(CrawlStrategyKind::Bfs),
665
+ content_filter: kwargs
666
+ .get(ruby.to_symbol("content_filter"))
667
+ .and_then(|v| ContentFilterKind::try_convert(v).ok()),
668
+ bm25_query: kwargs
669
+ .get(ruby.to_symbol("bm25_query"))
670
+ .and_then(|v| String::try_convert(v).ok()),
671
+ bm25_threshold: kwargs
672
+ .get(ruby.to_symbol("bm25_threshold"))
673
+ .and_then(|v| f64::try_convert(v).ok()),
657
674
  respect_robots_txt: kwargs
658
675
  .get(ruby.to_symbol("respect_robots_txt"))
659
676
  .and_then(|v| bool::try_convert(v).ok())
@@ -791,7 +808,7 @@ impl CrawlConfig {
791
808
  ssrf: kwargs
792
809
  .get(ruby.to_symbol("ssrf"))
793
810
  .and_then(|v| SsrfPolicy::try_convert(v).ok())
794
- .unwrap_or_default(),
811
+ .unwrap_or(crawlberg::SsrfPolicy::from_env().into()),
795
812
  ssrf_deny_private_explicit: kwargs
796
813
  .get(ruby.to_symbol("ssrf_deny_private_explicit"))
797
814
  .and_then(|v| bool::try_convert(v).ok()),
@@ -814,6 +831,22 @@ impl CrawlConfig {
814
831
  self.max_concurrent
815
832
  }
816
833
 
834
+ fn crawl_strategy(&self) -> CrawlStrategyKind {
835
+ self.crawl_strategy.clone()
836
+ }
837
+
838
+ fn content_filter(&self) -> Option<ContentFilterKind> {
839
+ self.content_filter.clone()
840
+ }
841
+
842
+ fn bm25_query(&self) -> Option<String> {
843
+ self.bm25_query.clone()
844
+ }
845
+
846
+ fn bm25_threshold(&self) -> Option<f64> {
847
+ self.bm25_threshold
848
+ }
849
+
817
850
  fn respect_robots_txt(&self) -> bool {
818
851
  self.respect_robots_txt
819
852
  }
@@ -981,6 +1014,14 @@ impl CrawlConfig {
981
1014
 
982
1015
  max_concurrent: self.max_concurrent,
983
1016
 
1017
+ crawl_strategy: self.crawl_strategy.clone().into(),
1018
+
1019
+ content_filter: self.content_filter.clone().map(Into::into),
1020
+
1021
+ bm25_query: self.bm25_query.clone(),
1022
+
1023
+ bm25_threshold: self.bm25_threshold,
1024
+
984
1025
  respect_robots_txt: self.respect_robots_txt,
985
1026
 
986
1027
  soft_http_errors: self.soft_http_errors,
@@ -2460,7 +2501,7 @@ impl LinkInfo {
2460
2501
  link_type: kwargs
2461
2502
  .get(ruby.to_symbol("link_type"))
2462
2503
  .and_then(|v| LinkType::try_convert(v).ok())
2463
- .unwrap_or_default(),
2504
+ .unwrap_or(LinkType::Internal),
2464
2505
  rel: kwargs
2465
2506
  .get(ruby.to_symbol("rel"))
2466
2507
  .and_then(|v| String::try_convert(v).ok()),
@@ -2560,7 +2601,7 @@ impl ImageInfo {
2560
2601
  source: kwargs
2561
2602
  .get(ruby.to_symbol("source"))
2562
2603
  .and_then(|v| ImageSource::try_convert(v).ok())
2563
- .unwrap_or_default(),
2604
+ .unwrap_or(ImageSource::Img),
2564
2605
  })
2565
2606
  }
2566
2607
 
@@ -2645,7 +2686,7 @@ impl FeedInfo {
2645
2686
  feed_type: kwargs
2646
2687
  .get(ruby.to_symbol("feed_type"))
2647
2688
  .and_then(|v| FeedType::try_convert(v).ok())
2648
- .unwrap_or_default(),
2689
+ .unwrap_or(FeedType::Rss),
2649
2690
  })
2650
2691
  }
2651
2692
 
@@ -2895,7 +2936,7 @@ impl DownloadedAsset {
2895
2936
  asset_category: kwargs
2896
2937
  .get(ruby.to_symbol("asset_category"))
2897
2938
  .and_then(|v| AssetCategory::try_convert(v).ok())
2898
- .unwrap_or_default(),
2939
+ .unwrap_or(AssetCategory::Image),
2899
2940
  html_tag: kwargs
2900
2941
  .get(ruby.to_symbol("html_tag"))
2901
2942
  .and_then(|v| String::try_convert(v).ok()),
@@ -4542,8 +4583,9 @@ impl magnus::IntoValue for BrowserMode {
4542
4583
  impl magnus::TryConvert for BrowserMode {
4543
4584
  fn try_convert(val: magnus::Value) -> Result<Self, magnus::Error> {
4544
4585
  let s: String = magnus::TryConvert::try_convert(val)?;
4545
- // Accept the serde wire name (snake_case), the PascalCase Rust variant name,
4546
- // and a lowercase fallback so fixtures written in any of those styles work.
4586
+ // Accept the real serde wire value, the legacy always-snake_case symbol Magnus used to
4587
+ // emit unconditionally, and the verbatim PascalCase Rust variant name, so fixtures and
4588
+ // existing consumer code written in any of those styles keep working.
4547
4589
  match s.as_str() {
4548
4590
  "auto" | "Auto" => Ok(BrowserMode::Auto),
4549
4591
  "always" | "Always" => Ok(BrowserMode::Always),
@@ -4588,8 +4630,9 @@ impl magnus::IntoValue for BrowserWait {
4588
4630
  impl magnus::TryConvert for BrowserWait {
4589
4631
  fn try_convert(val: magnus::Value) -> Result<Self, magnus::Error> {
4590
4632
  let s: String = magnus::TryConvert::try_convert(val)?;
4591
- // Accept the serde wire name (snake_case), the PascalCase Rust variant name,
4592
- // and a lowercase fallback so fixtures written in any of those styles work.
4633
+ // Accept the real serde wire value, the legacy always-snake_case symbol Magnus used to
4634
+ // emit unconditionally, and the verbatim PascalCase Rust variant name, so fixtures and
4635
+ // existing consumer code written in any of those styles keep working.
4593
4636
  match s.as_str() {
4594
4637
  "network_idle" | "NetworkIdle" => Ok(BrowserWait::NetworkIdle),
4595
4638
  "selector" | "Selector" => Ok(BrowserWait::Selector),
@@ -4631,8 +4674,9 @@ impl magnus::IntoValue for BrowserBackend {
4631
4674
  impl magnus::TryConvert for BrowserBackend {
4632
4675
  fn try_convert(val: magnus::Value) -> Result<Self, magnus::Error> {
4633
4676
  let s: String = magnus::TryConvert::try_convert(val)?;
4634
- // Accept the serde wire name (snake_case), the PascalCase Rust variant name,
4635
- // and a lowercase fallback so fixtures written in any of those styles work.
4677
+ // Accept the real serde wire value, the legacy always-snake_case symbol Magnus used to
4678
+ // emit unconditionally, and the verbatim PascalCase Rust variant name, so fixtures and
4679
+ // existing consumer code written in any of those styles keep working.
4636
4680
  match s.as_str() {
4637
4681
  "chromiumoxide" | "Chromiumoxide" => Ok(BrowserBackend::Chromiumoxide),
4638
4682
  "native" | "Native" => Ok(BrowserBackend::Native),
@@ -4671,8 +4715,9 @@ impl magnus::IntoValue for DocumentContentEncoding {
4671
4715
  impl magnus::TryConvert for DocumentContentEncoding {
4672
4716
  fn try_convert(val: magnus::Value) -> Result<Self, magnus::Error> {
4673
4717
  let s: String = magnus::TryConvert::try_convert(val)?;
4674
- // Accept the serde wire name (snake_case), the PascalCase Rust variant name,
4675
- // and a lowercase fallback so fixtures written in any of those styles work.
4718
+ // Accept the real serde wire value, the legacy always-snake_case symbol Magnus used to
4719
+ // emit unconditionally, and the verbatim PascalCase Rust variant name, so fixtures and
4720
+ // existing consumer code written in any of those styles keep working.
4676
4721
  match s.as_str() {
4677
4722
  "base64" | "Base64" => Ok(DocumentContentEncoding::Base64),
4678
4723
  other => Err(magnus::Error::new(
@@ -4686,6 +4731,95 @@ impl magnus::TryConvert for DocumentContentEncoding {
4686
4731
  unsafe impl IntoValueFromNative for DocumentContentEncoding {}
4687
4732
  unsafe impl TryConvertOwned for DocumentContentEncoding {}
4688
4733
 
4734
+ #[derive(Clone, Copy, PartialEq, Eq, Debug, serde::Serialize, serde::Deserialize)]
4735
+ #[serde(rename_all = "snake_case")]
4736
+ pub enum CrawlStrategyKind {
4737
+ Bfs,
4738
+ Dfs,
4739
+ BestFirst,
4740
+ Adaptive,
4741
+ }
4742
+
4743
+ impl Default for CrawlStrategyKind {
4744
+ fn default() -> Self {
4745
+ Self::Bfs
4746
+ }
4747
+ }
4748
+
4749
+ impl magnus::IntoValue for CrawlStrategyKind {
4750
+ fn into_value_with(self, handle: &Ruby) -> magnus::Value {
4751
+ let sym = match self {
4752
+ CrawlStrategyKind::Bfs => "bfs",
4753
+ CrawlStrategyKind::Dfs => "dfs",
4754
+ CrawlStrategyKind::BestFirst => "best_first",
4755
+ CrawlStrategyKind::Adaptive => "adaptive",
4756
+ };
4757
+ handle.to_symbol(sym).into_value_with(handle)
4758
+ }
4759
+ }
4760
+
4761
+ impl magnus::TryConvert for CrawlStrategyKind {
4762
+ fn try_convert(val: magnus::Value) -> Result<Self, magnus::Error> {
4763
+ let s: String = magnus::TryConvert::try_convert(val)?;
4764
+ // Accept the real serde wire value, the legacy always-snake_case symbol Magnus used to
4765
+ // emit unconditionally, and the verbatim PascalCase Rust variant name, so fixtures and
4766
+ // existing consumer code written in any of those styles keep working.
4767
+ match s.as_str() {
4768
+ "bfs" | "Bfs" => Ok(CrawlStrategyKind::Bfs),
4769
+ "dfs" | "Dfs" => Ok(CrawlStrategyKind::Dfs),
4770
+ "best_first" | "BestFirst" => Ok(CrawlStrategyKind::BestFirst),
4771
+ "adaptive" | "Adaptive" => Ok(CrawlStrategyKind::Adaptive),
4772
+ other => Err(magnus::Error::new(
4773
+ unsafe { Ruby::get_unchecked() }.exception_arg_error(),
4774
+ format!("invalid CrawlStrategyKind value: {other}"),
4775
+ )),
4776
+ }
4777
+ }
4778
+ }
4779
+
4780
+ unsafe impl IntoValueFromNative for CrawlStrategyKind {}
4781
+ unsafe impl TryConvertOwned for CrawlStrategyKind {}
4782
+
4783
+ #[derive(Clone, Copy, PartialEq, Eq, Debug, serde::Serialize, serde::Deserialize)]
4784
+ #[serde(rename_all = "snake_case")]
4785
+ pub enum ContentFilterKind {
4786
+ Bm25,
4787
+ }
4788
+
4789
+ impl Default for ContentFilterKind {
4790
+ fn default() -> Self {
4791
+ Self::Bm25
4792
+ }
4793
+ }
4794
+
4795
+ impl magnus::IntoValue for ContentFilterKind {
4796
+ fn into_value_with(self, handle: &Ruby) -> magnus::Value {
4797
+ let sym = match self {
4798
+ ContentFilterKind::Bm25 => "bm25",
4799
+ };
4800
+ handle.to_symbol(sym).into_value_with(handle)
4801
+ }
4802
+ }
4803
+
4804
+ impl magnus::TryConvert for ContentFilterKind {
4805
+ fn try_convert(val: magnus::Value) -> Result<Self, magnus::Error> {
4806
+ let s: String = magnus::TryConvert::try_convert(val)?;
4807
+ // Accept the real serde wire value, the legacy always-snake_case symbol Magnus used to
4808
+ // emit unconditionally, and the verbatim PascalCase Rust variant name, so fixtures and
4809
+ // existing consumer code written in any of those styles keep working.
4810
+ match s.as_str() {
4811
+ "bm25" | "Bm25" => Ok(ContentFilterKind::Bm25),
4812
+ other => Err(magnus::Error::new(
4813
+ unsafe { Ruby::get_unchecked() }.exception_arg_error(),
4814
+ format!("invalid ContentFilterKind value: {other}"),
4815
+ )),
4816
+ }
4817
+ }
4818
+ }
4819
+
4820
+ unsafe impl IntoValueFromNative for ContentFilterKind {}
4821
+ unsafe impl TryConvertOwned for ContentFilterKind {}
4822
+
4689
4823
  #[derive(Clone, Debug, serde::Serialize, serde::Deserialize)]
4690
4824
  #[serde(tag = "type")]
4691
4825
  pub enum AuthConfig {
@@ -4781,8 +4915,9 @@ impl magnus::IntoValue for LinkType {
4781
4915
  impl magnus::TryConvert for LinkType {
4782
4916
  fn try_convert(val: magnus::Value) -> Result<Self, magnus::Error> {
4783
4917
  let s: String = magnus::TryConvert::try_convert(val)?;
4784
- // Accept the serde wire name (snake_case), the PascalCase Rust variant name,
4785
- // and a lowercase fallback so fixtures written in any of those styles work.
4918
+ // Accept the real serde wire value, the legacy always-snake_case symbol Magnus used to
4919
+ // emit unconditionally, and the verbatim PascalCase Rust variant name, so fixtures and
4920
+ // existing consumer code written in any of those styles keep working.
4786
4921
  match s.as_str() {
4787
4922
  "internal" | "Internal" => Ok(LinkType::Internal),
4788
4923
  "external" | "External" => Ok(LinkType::External),
@@ -4821,8 +4956,8 @@ impl magnus::IntoValue for ImageSource {
4821
4956
  let sym = match self {
4822
4957
  ImageSource::Img => "img",
4823
4958
  ImageSource::PictureSource => "picture_source",
4824
- ImageSource::OgImage => "og_image",
4825
- ImageSource::TwitterImage => "twitter_image",
4959
+ ImageSource::OgImage => "og:image",
4960
+ ImageSource::TwitterImage => "twitter:image",
4826
4961
  };
4827
4962
  handle.to_symbol(sym).into_value_with(handle)
4828
4963
  }
@@ -4831,13 +4966,14 @@ impl magnus::IntoValue for ImageSource {
4831
4966
  impl magnus::TryConvert for ImageSource {
4832
4967
  fn try_convert(val: magnus::Value) -> Result<Self, magnus::Error> {
4833
4968
  let s: String = magnus::TryConvert::try_convert(val)?;
4834
- // Accept the serde wire name (snake_case), the PascalCase Rust variant name,
4835
- // and a lowercase fallback so fixtures written in any of those styles work.
4969
+ // Accept the real serde wire value, the legacy always-snake_case symbol Magnus used to
4970
+ // emit unconditionally, and the verbatim PascalCase Rust variant name, so fixtures and
4971
+ // existing consumer code written in any of those styles keep working.
4836
4972
  match s.as_str() {
4837
4973
  "img" | "Img" => Ok(ImageSource::Img),
4838
4974
  "picture_source" | "PictureSource" => Ok(ImageSource::PictureSource),
4839
- "og_image" | "OgImage" => Ok(ImageSource::OgImage),
4840
- "twitter_image" | "TwitterImage" => Ok(ImageSource::TwitterImage),
4975
+ "og:image" | "og_image" | "OgImage" => Ok(ImageSource::OgImage),
4976
+ "twitter:image" | "twitter_image" | "TwitterImage" => Ok(ImageSource::TwitterImage),
4841
4977
  other => Err(magnus::Error::new(
4842
4978
  unsafe { Ruby::get_unchecked() }.exception_arg_error(),
4843
4979
  format!("invalid ImageSource value: {other}"),
@@ -4877,8 +5013,9 @@ impl magnus::IntoValue for FeedType {
4877
5013
  impl magnus::TryConvert for FeedType {
4878
5014
  fn try_convert(val: magnus::Value) -> Result<Self, magnus::Error> {
4879
5015
  let s: String = magnus::TryConvert::try_convert(val)?;
4880
- // Accept the serde wire name (snake_case), the PascalCase Rust variant name,
4881
- // and a lowercase fallback so fixtures written in any of those styles work.
5016
+ // Accept the real serde wire value, the legacy always-snake_case symbol Magnus used to
5017
+ // emit unconditionally, and the verbatim PascalCase Rust variant name, so fixtures and
5018
+ // existing consumer code written in any of those styles keep working.
4882
5019
  match s.as_str() {
4883
5020
  "rss" | "Rss" => Ok(FeedType::Rss),
4884
5021
  "atom" | "Atom" => Ok(FeedType::Atom),
@@ -4936,8 +5073,9 @@ impl magnus::IntoValue for AssetCategory {
4936
5073
  impl magnus::TryConvert for AssetCategory {
4937
5074
  fn try_convert(val: magnus::Value) -> Result<Self, magnus::Error> {
4938
5075
  let s: String = magnus::TryConvert::try_convert(val)?;
4939
- // Accept the serde wire name (snake_case), the PascalCase Rust variant name,
4940
- // and a lowercase fallback so fixtures written in any of those styles work.
5076
+ // Accept the real serde wire value, the legacy always-snake_case symbol Magnus used to
5077
+ // emit unconditionally, and the verbatim PascalCase Rust variant name, so fixtures and
5078
+ // existing consumer code written in any of those styles keep working.
4941
5079
  match s.as_str() {
4942
5080
  "document" | "Document" => Ok(AssetCategory::Document),
4943
5081
  "image" | "Image" => Ok(AssetCategory::Image),
@@ -5133,8 +5271,9 @@ impl magnus::IntoValue for ScrollDirection {
5133
5271
  impl magnus::TryConvert for ScrollDirection {
5134
5272
  fn try_convert(val: magnus::Value) -> Result<Self, magnus::Error> {
5135
5273
  let s: String = magnus::TryConvert::try_convert(val)?;
5136
- // Accept the serde wire name (snake_case), the PascalCase Rust variant name,
5137
- // and a lowercase fallback so fixtures written in any of those styles work.
5274
+ // Accept the real serde wire value, the legacy always-snake_case symbol Magnus used to
5275
+ // emit unconditionally, and the verbatim PascalCase Rust variant name, so fixtures and
5276
+ // existing consumer code written in any of those styles keep working.
5138
5277
  match s.as_str() {
5139
5278
  "up" | "Up" => Ok(ScrollDirection::Up),
5140
5279
  "down" | "Down" => Ok(ScrollDirection::Down),
@@ -5612,6 +5751,10 @@ impl From<CrawlConfig> for crawlberg::CrawlConfig {
5612
5751
  max_pages: val.max_pages,
5613
5752
  max_links_per_page: val.max_links_per_page,
5614
5753
  max_concurrent: val.max_concurrent,
5754
+ crawl_strategy: val.crawl_strategy.into(),
5755
+ content_filter: val.content_filter.map(Into::into),
5756
+ bm25_query: val.bm25_query,
5757
+ bm25_threshold: val.bm25_threshold,
5615
5758
  respect_robots_txt: val.respect_robots_txt,
5616
5759
  soft_http_errors: val.soft_http_errors,
5617
5760
  user_agent: val.user_agent,
@@ -5668,6 +5811,10 @@ impl From<crawlberg::CrawlConfig> for CrawlConfig {
5668
5811
  max_pages: val.max_pages,
5669
5812
  max_links_per_page: val.max_links_per_page,
5670
5813
  max_concurrent: val.max_concurrent,
5814
+ crawl_strategy: val.crawl_strategy.into(),
5815
+ content_filter: val.content_filter.map(Into::into),
5816
+ bm25_query: val.bm25_query.map(|v| v.to_string()),
5817
+ bm25_threshold: val.bm25_threshold,
5671
5818
  respect_robots_txt: val.respect_robots_txt,
5672
5819
  soft_http_errors: val.soft_http_errors,
5673
5820
  user_agent: val.user_agent.map(|v| v.to_string()),
@@ -6746,6 +6893,44 @@ impl From<crawlberg::DocumentContentEncoding> for DocumentContentEncoding {
6746
6893
  }
6747
6894
  }
6748
6895
 
6896
+ impl From<CrawlStrategyKind> for crawlberg::CrawlStrategyKind {
6897
+ fn from(val: CrawlStrategyKind) -> Self {
6898
+ match val {
6899
+ CrawlStrategyKind::Bfs => Self::Bfs,
6900
+ CrawlStrategyKind::Dfs => Self::Dfs,
6901
+ CrawlStrategyKind::BestFirst => Self::BestFirst,
6902
+ CrawlStrategyKind::Adaptive => Self::Adaptive,
6903
+ }
6904
+ }
6905
+ }
6906
+
6907
+ impl From<crawlberg::CrawlStrategyKind> for CrawlStrategyKind {
6908
+ fn from(val: crawlberg::CrawlStrategyKind) -> Self {
6909
+ match val {
6910
+ crawlberg::CrawlStrategyKind::Bfs => Self::Bfs,
6911
+ crawlberg::CrawlStrategyKind::Dfs => Self::Dfs,
6912
+ crawlberg::CrawlStrategyKind::BestFirst => Self::BestFirst,
6913
+ crawlberg::CrawlStrategyKind::Adaptive => Self::Adaptive,
6914
+ }
6915
+ }
6916
+ }
6917
+
6918
+ impl From<ContentFilterKind> for crawlberg::ContentFilterKind {
6919
+ fn from(val: ContentFilterKind) -> Self {
6920
+ match val {
6921
+ ContentFilterKind::Bm25 => Self::Bm25,
6922
+ }
6923
+ }
6924
+ }
6925
+
6926
+ impl From<crawlberg::ContentFilterKind> for ContentFilterKind {
6927
+ fn from(val: crawlberg::ContentFilterKind) -> Self {
6928
+ match val {
6929
+ crawlberg::ContentFilterKind::Bm25 => Self::Bm25,
6930
+ }
6931
+ }
6932
+ }
6933
+
6749
6934
  impl From<AuthConfig> for crawlberg::AuthConfig {
6750
6935
  fn from(val: AuthConfig) -> Self {
6751
6936
  match val {
@@ -7286,6 +7471,14 @@ fn ruby_init(ruby: &Ruby) -> Result<(), Error> {
7286
7471
 
7287
7472
  class.define_method("max_concurrent", method!(CrawlConfig::max_concurrent, 0))?;
7288
7473
 
7474
+ class.define_method("crawl_strategy", method!(CrawlConfig::crawl_strategy, 0))?;
7475
+
7476
+ class.define_method("content_filter", method!(CrawlConfig::content_filter, 0))?;
7477
+
7478
+ class.define_method("bm25_query", method!(CrawlConfig::bm25_query, 0))?;
7479
+
7480
+ class.define_method("bm25_threshold", method!(CrawlConfig::bm25_threshold, 0))?;
7481
+
7289
7482
  class.define_method("respect_robots_txt", method!(CrawlConfig::respect_robots_txt, 0))?;
7290
7483
 
7291
7484
  class.define_method("soft_http_errors", method!(CrawlConfig::soft_http_errors, 0))?;