crawlberg 1.11.1 → 1.12.0

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 409b1edc648234b832f62ed311e71d5be8e76a27c2483c613124da7075739946
4
- data.tar.gz: bc13e5d4e5ac46d7840cfcd1121a59f7c784191e2b3f97102d4a55324ad1cc1d
3
+ metadata.gz: ccfb786cd775f2189206d95ae30218971296b115ec48e1a64c3fff68ce602c75
4
+ data.tar.gz: c02f1627a22312d32df5362159fb2a54b5d9ee4737c15754443dedb971325628
5
5
  SHA512:
6
- metadata.gz: cffaf1ec4a66183ff3f625f5bb37a6eea1615f7439bc9e7c3eb1cc25378ff69ddd609e1d5c7e2b2f6c910fccc7aa08bf4628ebff775c161d34b289a2e8755c21
7
- data.tar.gz: ef778845f998c6a338acdd2eb820b110cb29a93054a7f295adbdd7cf4dd9b60156482e5b5265d77390722dc52693a1e9904eb1874c236cbe3bc41c7f62a56dac
6
+ metadata.gz: 7a8d0a19cfd37e7a879f5f4e15af84156e56cf062c0afe545b550d12f6210aec14bab5af9fceb583f1a93de6d5db69d8fd519fba668226f4fa1b248f126addad
7
+ data.tar.gz: 2c3e3287fbd7eec2e6f1ea9222e5ad8867b39b3de75075c115fc68baa1972edd933a0b33c93fa7d27c035dbf13524465ce4eec6045220c2efcbb69bbe6aad3f2
@@ -63,9 +63,9 @@ checksum = "330a5ed07fa54e4702c9d6c4174f74427fc0ef6e214bbd677ae50a5099946470"
63
63
 
64
64
  [[package]]
65
65
  name = "arc-swap"
66
- version = "1.9.2"
66
+ version = "1.9.3"
67
67
  source = "registry+https://github.com/rust-lang/crates.io-index"
68
- checksum = "c049c0be4daef0b145cb3555416b3b8ef5b7888a38aea1a3a155801fe7b0810b"
68
+ checksum = "380962b3d93b99642e50b9febf72c071e97e8b32d86eae9cf4ef582bb960ae6e"
69
69
  dependencies = [
70
70
  "rustversion",
71
71
  ]
@@ -87,9 +87,9 @@ dependencies = [
87
87
 
88
88
  [[package]]
89
89
  name = "async-compression"
90
- version = "0.4.50"
90
+ version = "0.4.51"
91
91
  source = "registry+https://github.com/rust-lang/crates.io-index"
92
- checksum = "ee19bd99b43e3691acbad4e840420a4881cea6c0b66a208125a824f8fd53f5a1"
92
+ checksum = "9d5755640120b24961f8231e05892e4a4f7e0d04e8aeca161508c9c397946970"
93
93
  dependencies = [
94
94
  "compression-codecs",
95
95
  "compression-core",
@@ -160,12 +160,6 @@ dependencies = [
160
160
  "pkg-config",
161
161
  ]
162
162
 
163
- [[package]]
164
- name = "base64"
165
- version = "0.22.1"
166
- source = "registry+https://github.com/rust-lang/crates.io-index"
167
- checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6"
168
-
169
163
  [[package]]
170
164
  name = "base64"
171
165
  version = "0.23.1"
@@ -280,9 +274,9 @@ checksum = "fc652a48c352aef3ea3aed32080501cf3ef6ed5da78602a020c991775b0aff04"
280
274
 
281
275
  [[package]]
282
276
  name = "cc"
283
- version = "1.8.0"
277
+ version = "1.9.0"
284
278
  source = "registry+https://github.com/rust-lang/crates.io-index"
285
- checksum = "6651c9ed80effdc7db0ff72512157f901af5e3549e341e24b1dd4887d836d838"
279
+ checksum = "877bf67ac8e52449eb2f9e98a344ea163beb70dd1f9eebe3cc5357dcfeaee4df"
286
280
  dependencies = [
287
281
  "find-msvc-tools",
288
282
  "jobserver",
@@ -413,9 +407,9 @@ checksum = "3d7b894f5411737b7867f4827955924d7c254fc9f4d91a6aad6b097804b1018b"
413
407
 
414
408
  [[package]]
415
409
  name = "combine"
416
- version = "4.6.8"
410
+ version = "4.6.9"
417
411
  source = "registry+https://github.com/rust-lang/crates.io-index"
418
- checksum = "cfc320937d09e6de266b31b9afb480f197d7a861be86be7cb2ea7e5d1bfffc5e"
412
+ checksum = "4356eba6976435498d05a311ee9fc486da3bc81c200d3f0d7dd9703b41913f92"
419
413
  dependencies = [
420
414
  "bytes",
421
415
  "memchr",
@@ -423,9 +417,9 @@ dependencies = [
423
417
 
424
418
  [[package]]
425
419
  name = "compression-codecs"
426
- version = "0.4.45"
420
+ version = "0.4.46"
427
421
  source = "registry+https://github.com/rust-lang/crates.io-index"
428
- checksum = "98fc98460ba0ad5317075d3632b8dfc45d0be8c4a49347c2a38272019717614a"
422
+ checksum = "cae36683101b2899f48bd31f8db9839437356188e3b1ff23096e73dab09ba8fe"
429
423
  dependencies = [
430
424
  "brotli",
431
425
  "compression-core",
@@ -435,9 +429,9 @@ dependencies = [
435
429
 
436
430
  [[package]]
437
431
  name = "compression-core"
438
- version = "0.4.33"
432
+ version = "0.4.34"
439
433
  source = "registry+https://github.com/rust-lang/crates.io-index"
440
- checksum = "6e8ccc4ea9f6acc32d102c0f6d471d11d913ad15f20c04de743374861fa1d414"
434
+ checksum = "2ebdda89edc534bf8d5dd2857562633b6495557e5846552ade994b99ed13c36a"
441
435
 
442
436
  [[package]]
443
437
  name = "const-oid"
@@ -543,9 +537,9 @@ dependencies = [
543
537
 
544
538
  [[package]]
545
539
  name = "crawlberg"
546
- version = "1.11.1"
540
+ version = "1.12.0"
547
541
  source = "registry+https://github.com/rust-lang/crates.io-index"
548
- checksum = "c441d340160d808d8d494be20e91e87c37227ad09881cf70b7e32d6eabf2c94a"
542
+ checksum = "816cd63cd218f1072b402230d946d4805923b1d53a2faa39d5ce71d58d3f022a"
549
543
  dependencies = [
550
544
  "ahash",
551
545
  "aho-corasick",
@@ -553,7 +547,7 @@ dependencies = [
553
547
  "astral-tl",
554
548
  "async-trait",
555
549
  "async-tungstenite",
556
- "base64 0.23.1",
550
+ "base64",
557
551
  "blake3",
558
552
  "bytes",
559
553
  "chardetng",
@@ -613,12 +607,12 @@ dependencies = [
613
607
 
614
608
  [[package]]
615
609
  name = "crawlberg-chromiumoxide"
616
- version = "0.9.3"
610
+ version = "0.9.4"
617
611
  source = "registry+https://github.com/rust-lang/crates.io-index"
618
- checksum = "8add9abf085c5f95d7dfbde84b67e6b6f2fb95a0ca288c98a4e8ceae169d2d3f"
612
+ checksum = "937d12e969f7090c02cb64dff52375f3e26e669cbdda7bc49ce364fb8ce7bb68"
619
613
  dependencies = [
620
614
  "async-tungstenite",
621
- "base64 0.22.1",
615
+ "base64",
622
616
  "chromiumoxide_cdp",
623
617
  "chromiumoxide_types",
624
618
  "dunce",
@@ -641,7 +635,7 @@ dependencies = [
641
635
 
642
636
  [[package]]
643
637
  name = "crawlberg-rb"
644
- version = "1.11.1"
638
+ version = "1.12.0"
645
639
  dependencies = [
646
640
  "crawlberg",
647
641
  "futures",
@@ -654,15 +648,15 @@ dependencies = [
654
648
 
655
649
  [[package]]
656
650
  name = "crawlberg-robots"
657
- version = "1.11.1"
651
+ version = "1.12.0"
658
652
  source = "registry+https://github.com/rust-lang/crates.io-index"
659
- checksum = "07c5d34335e3703ed5d12bffa68b67e33063347a219cae698bf939f9fb41a62f"
653
+ checksum = "a7f393d7f0a1f96526de81142b88a733b92b9ca8ad3fc35b1c23c90818b50029"
660
654
 
661
655
  [[package]]
662
656
  name = "crc32fast"
663
- version = "1.5.2"
657
+ version = "1.5.3"
664
658
  source = "registry+https://github.com/rust-lang/crates.io-index"
665
- checksum = "01a7799fd6b852db0e61728dde9a204c423b44d689dbd432522543614b490e78"
659
+ checksum = "0ba106e844045ddc02c20768ac4b0b7cb45f2cc2ecbd833ac9f5dacb183c2055"
666
660
  dependencies = [
667
661
  "cfg-if",
668
662
  ]
@@ -851,9 +845,9 @@ dependencies = [
851
845
 
852
846
  [[package]]
853
847
  name = "find-msvc-tools"
854
- version = "0.1.14"
848
+ version = "0.1.15"
855
849
  source = "registry+https://github.com/rust-lang/crates.io-index"
856
- checksum = "aedcfb3409746eddb02b9e19ebda1c3394f759a152e48ee875a0844d1b955484"
850
+ checksum = "1c66915cc5391097de7a2b0b972e8505aa33c0df401fd3a6811dbdb32881ba48"
857
851
 
858
852
  [[package]]
859
853
  name = "flate2"
@@ -1092,13 +1086,13 @@ checksum = "491194d601b4fa9fac3c9571e014070a0ad1bc3392d1bc10419695196a8b3cc3"
1092
1086
 
1093
1087
  [[package]]
1094
1088
  name = "html-to-markdown-rs"
1095
- version = "3.18.1"
1089
+ version = "3.18.5"
1096
1090
  source = "registry+https://github.com/rust-lang/crates.io-index"
1097
- checksum = "36135ae2471a090d086837db2f4794dca3bf8ca0ba288b799a0bb85dd3f0acf0"
1091
+ checksum = "456da57af20dc98ba1ec1ab70079f977ec29bf62b713ee1acaa71799a275adb4"
1098
1092
  dependencies = [
1099
1093
  "ahash",
1100
1094
  "astral-tl",
1101
- "base64 0.23.1",
1095
+ "base64",
1102
1096
  "bitflags",
1103
1097
  "html-escape",
1104
1098
  "html5ever",
@@ -1222,7 +1216,7 @@ version = "0.1.21"
1222
1216
  source = "registry+https://github.com/rust-lang/crates.io-index"
1223
1217
  checksum = "ddc03d96684f9226b8a787cdb71488417b53ab5ea8fdb1dac946cb9431cc8bff"
1224
1218
  dependencies = [
1225
- "base64 0.23.1",
1219
+ "base64",
1226
1220
  "bytes",
1227
1221
  "futures-channel",
1228
1222
  "futures-util",
@@ -1573,9 +1567,9 @@ checksum = "20870f649af7073d53e38067b2a84312175d56ea15217e1b15bc83506ec50afb"
1573
1567
 
1574
1568
  [[package]]
1575
1569
  name = "libc"
1576
- version = "0.2.189"
1570
+ version = "0.2.191"
1577
1571
  source = "registry+https://github.com/rust-lang/crates.io-index"
1578
- checksum = "3eaf3ede3fee6db1a4c2ee091bf8a8b4dccdc6d17f656fb07896ee72867612f2"
1572
+ checksum = "65cd87c9a6d60536580b316ad985726104730a5151c99845f2490428ef91240a"
1579
1573
 
1580
1574
  [[package]]
1581
1575
  name = "libloading"
@@ -2000,9 +1994,9 @@ dependencies = [
2000
1994
 
2001
1995
  [[package]]
2002
1996
  name = "psl"
2003
- version = "2.1.241"
1997
+ version = "2.1.244"
2004
1998
  source = "registry+https://github.com/rust-lang/crates.io-index"
2005
- checksum = "c7319b480e204d67e759cad7886178335d26324c7c8573c126cc9dfa7350d064"
1999
+ checksum = "bc3ac0c25b0c40554a755e56dfe268855c53f391bbb7922a1c1fe59b73b163a9"
2006
2000
  dependencies = [
2007
2001
  "psl-types",
2008
2002
  ]
@@ -2232,7 +2226,7 @@ version = "0.13.5"
2232
2226
  source = "registry+https://github.com/rust-lang/crates.io-index"
2233
2227
  checksum = "16a1cfa75cc186dd73d5818e510e042e40927bccc9c236b061cea97e1eb08029"
2234
2228
  dependencies = [
2235
- "base64 0.23.1",
2229
+ "base64",
2236
2230
  "bytes",
2237
2231
  "cookie",
2238
2232
  "cookie_store",
@@ -2373,9 +2367,9 @@ checksum = "eec689c0bc40ff2458a5977b6619cb718087084a18e02a131c599b62d05e1a5f"
2373
2367
 
2374
2368
  [[package]]
2375
2369
  name = "rustls-webpki"
2376
- version = "0.103.15"
2370
+ version = "0.103.16"
2377
2371
  source = "registry+https://github.com/rust-lang/crates.io-index"
2378
- checksum = "f3c3cf1d8b1e7d4927e2d154c3fcb02979afb9939629c62cd9048d4f07b60ac2"
2372
+ checksum = "4443b1b6d39d7c663139942cc4558262562d2c84123bb6282ef177009ca8b281"
2379
2373
  dependencies = [
2380
2374
  "aws-lc-rs",
2381
2375
  "ring",
@@ -2400,9 +2394,9 @@ dependencies = [
2400
2394
 
2401
2395
  [[package]]
2402
2396
  name = "schannel"
2403
- version = "0.1.29"
2397
+ version = "0.1.30"
2404
2398
  source = "registry+https://github.com/rust-lang/crates.io-index"
2405
- checksum = "91c1b7e4904c873ef0710c1f407dde2e6287de2bebc1bbbf7d430bb7cbffd939"
2399
+ checksum = "9cb23c424d8ee841bb4d813677ca237e2a610067d594fec130f87d6093495ab5"
2406
2400
  dependencies = [
2407
2401
  "windows-sys 0.61.2",
2408
2402
  ]
@@ -2843,9 +2837,9 @@ checksum = "fd3ca314f692efd6c868f8408f53fe444634a845f96c028b97d35f6a1f79f0ee"
2843
2837
 
2844
2838
  [[package]]
2845
2839
  name = "tokio"
2846
- version = "1.53.3"
2840
+ version = "1.54.1"
2847
2841
  source = "registry+https://github.com/rust-lang/crates.io-index"
2848
- checksum = "ce3335fa71841cda333a58d7615b03901380ecf09d59b3296d21f8bbac0dde4e"
2842
+ checksum = "b52fd3255258d26fac7264ab5a76b53c13367136dc011d3d6ad4f8ed070396a3"
2849
2843
  dependencies = [
2850
2844
  "bytes",
2851
2845
  "libc",
@@ -3225,9 +3219,9 @@ dependencies = [
3225
3219
 
3226
3220
  [[package]]
3227
3221
  name = "webpki-root-certs"
3228
- version = "1.0.9"
3222
+ version = "1.0.10"
3229
3223
  source = "registry+https://github.com/rust-lang/crates.io-index"
3230
- checksum = "b96554aa2acc8ccdb7e1c9a58a7a68dd5d13bccc69cd124cb09406db612a1c9b"
3224
+ checksum = "58ec80e73fd8baf57bf0d9615554c75348bda990d6d5bbeab964dd068319fecb"
3231
3225
  dependencies = [
3232
3226
  "rustls-pki-types",
3233
3227
  ]
@@ -1,11 +1,11 @@
1
1
  # This file is auto-generated by alef — DO NOT EDIT.
2
- # alef:hash:7fb2df2846ff405ffd7dba3601d74e88dbb7578bb5175c54cc2e8e10229e6ddd
2
+ # alef:hash:5c5de05901161d333a4343e3a35f6b8e0967bdc7fbaa657e0ccb4f328fc2701b
3
3
  # To regenerate: alef generate
4
4
  # To verify freshness: alef verify
5
5
 
6
6
  [package]
7
7
  name = "crawlberg-rb"
8
- version = "1.11.1"
8
+ version = "1.12.0"
9
9
  edition = "2024"
10
10
  authors = ["Na'aman Hirschfeld <naaman@xberg.io>", "Tobias Perlstein <tobias@xberg.io>"]
11
11
  license = "MIT"
@@ -23,7 +23,7 @@ path = "../src/lib.rs"
23
23
  crate-type = ["cdylib"]
24
24
 
25
25
  [dependencies]
26
- crawlberg = { version = "1.11.1", features = ["interact", "browser-chromiumoxide"] }
26
+ crawlberg = { version = "1.12.0", features = ["interact", "browser-chromiumoxide"] }
27
27
  futures = "0.3"
28
28
  magnus = "0.9"
29
29
  rb-sys = ">=0.9.130, <0.10"
@@ -1,5 +1,5 @@
1
1
  // This file is auto-generated by alef. DO NOT EDIT.
2
- // alef:hash:2ec1fdc93f72b06b0d045fd1f6b6288fad256babb9754b0e89759ebc3fd4b1f8
2
+ // alef:hash:582ed106e4be9129fdfae3b203c9f9ccb338efae1989ad0fdde9d99890d81bd7
3
3
  // Re-generate with: alef generate
4
4
  #![allow(dead_code, unused_imports, unused_variables)]
5
5
  #![allow(
@@ -843,6 +843,8 @@ pub struct BrowserConfig {
843
843
  session_affinity: bool,
844
844
  chrome_path: Option<String>,
845
845
  chrome_args: Vec<String>,
846
+ scroll_containers: bool,
847
+ dom_quiet_window: u64,
846
848
  }
847
849
 
848
850
  unsafe impl IntoValueFromNative for BrowserConfig {}
@@ -892,6 +894,8 @@ impl std::fmt::Debug for BrowserConfig {
892
894
  debug.field("session_affinity", &self.session_affinity);
893
895
  debug.field("chrome_path", &self.chrome_path);
894
896
  debug.field("chrome_args", &"<redacted>");
897
+ debug.field("scroll_containers", &self.scroll_containers);
898
+ debug.field("dom_quiet_window", &self.dom_quiet_window);
895
899
  debug.finish()
896
900
  }
897
901
  }
@@ -1070,6 +1074,24 @@ impl BrowserConfig {
1070
1074
  })?,
1071
1075
  None => Default::default(),
1072
1076
  },
1077
+ scroll_containers: match kwargs.get(ruby.to_symbol("scroll_containers")) {
1078
+ Some(v) => bool::try_convert(v).map_err(|e| {
1079
+ magnus::Error::new(
1080
+ unsafe { magnus::Ruby::get_unchecked() }.exception_type_error(),
1081
+ format!("invalid value for `scroll_containers`: {}", e),
1082
+ )
1083
+ })?,
1084
+ None => false,
1085
+ },
1086
+ dom_quiet_window: match kwargs.get(ruby.to_symbol("dom_quiet_window")) {
1087
+ Some(v) => u64::try_convert(v).map_err(|e| {
1088
+ magnus::Error::new(
1089
+ unsafe { magnus::Ruby::get_unchecked() }.exception_type_error(),
1090
+ format!("invalid value for `dom_quiet_window`: {}", e),
1091
+ )
1092
+ })?,
1093
+ None => 150,
1094
+ },
1073
1095
  })
1074
1096
  }
1075
1097
 
@@ -1140,6 +1162,14 @@ impl BrowserConfig {
1140
1162
  fn chrome_args(&self) -> Vec<String> {
1141
1163
  self.chrome_args.clone()
1142
1164
  }
1165
+
1166
+ fn scroll_containers(&self) -> bool {
1167
+ self.scroll_containers
1168
+ }
1169
+
1170
+ fn dom_quiet_window(&self) -> u64 {
1171
+ self.dom_quiet_window.clone()
1172
+ }
1143
1173
  }
1144
1174
 
1145
1175
  #[derive(Clone, Debug, serde::Serialize)]
@@ -1936,6 +1966,7 @@ pub struct CrawlConfig {
1936
1966
  save_browser_profile: bool,
1937
1967
  ssrf: SsrfPolicy,
1938
1968
  ssrf_deny_private_explicit: Option<bool>,
1969
+ danger_accept_invalid_certs: bool,
1939
1970
  }
1940
1971
 
1941
1972
  unsafe impl IntoValueFromNative for CrawlConfig {}
@@ -2023,6 +2054,7 @@ impl std::fmt::Debug for CrawlConfig {
2023
2054
  debug.field("save_browser_profile", &self.save_browser_profile);
2024
2055
  debug.field("ssrf", &self.ssrf);
2025
2056
  debug.field("ssrf_deny_private_explicit", &self.ssrf_deny_private_explicit);
2057
+ debug.field("danger_accept_invalid_certs", &self.danger_accept_invalid_certs);
2026
2058
  debug.finish()
2027
2059
  }
2028
2060
  }
@@ -2549,6 +2581,15 @@ impl CrawlConfig {
2549
2581
  })?),
2550
2582
  None => None,
2551
2583
  },
2584
+ danger_accept_invalid_certs: match kwargs.get(ruby.to_symbol("danger_accept_invalid_certs")) {
2585
+ Some(v) => bool::try_convert(v).map_err(|e| {
2586
+ magnus::Error::new(
2587
+ unsafe { magnus::Ruby::get_unchecked() }.exception_type_error(),
2588
+ format!("invalid value for `danger_accept_invalid_certs`: {}", e),
2589
+ )
2590
+ })?,
2591
+ None => false,
2592
+ },
2552
2593
  })
2553
2594
  }
2554
2595
 
@@ -2772,6 +2813,10 @@ impl CrawlConfig {
2772
2813
  self.ssrf_deny_private_explicit
2773
2814
  }
2774
2815
 
2816
+ fn danger_accept_invalid_certs(&self) -> bool {
2817
+ self.danger_accept_invalid_certs
2818
+ }
2819
+
2775
2820
  fn validate(&self) -> Result<(), Error> {
2776
2821
  #[allow(clippy::needless_update)]
2777
2822
  let core_self = crawlberg::CrawlConfig {
@@ -2890,6 +2935,8 @@ impl CrawlConfig {
2890
2935
 
2891
2936
  ssrf_deny_private_explicit: self.ssrf_deny_private_explicit,
2892
2937
 
2938
+ danger_accept_invalid_certs: self.danger_accept_invalid_certs,
2939
+
2893
2940
  ..Default::default()
2894
2941
  };
2895
2942
  let result = core_self.validate().map_err(|e| {
@@ -3454,7 +3501,7 @@ impl CrawlPageResult {
3454
3501
  }
3455
3502
  }
3456
3503
 
3457
- #[derive(Clone, Debug, serde::Serialize, serde::Deserialize)]
3504
+ #[derive(Clone, Debug, serde::Serialize)]
3458
3505
  #[serde(default)]
3459
3506
  #[magnus::wrap(class = "Crawlberg::CrawlResult")]
3460
3507
  pub struct CrawlResult {
@@ -3466,6 +3513,7 @@ pub struct CrawlResult {
3466
3513
  cookies: Vec<CookieInfo>,
3467
3514
  stayed_on_domain: bool,
3468
3515
  browser_used: bool,
3516
+ waf_block: Option<WafBlockDetails>,
3469
3517
  }
3470
3518
 
3471
3519
  unsafe impl IntoValueFromNative for CrawlResult {}
@@ -3495,6 +3543,14 @@ impl magnus::TryConvert for CrawlResult {
3495
3543
  }
3496
3544
 
3497
3545
  unsafe impl TryConvertOwned for CrawlResult {}
3546
+ impl<'de> serde::Deserialize<'de> for CrawlResult {
3547
+ fn deserialize<D>(deserializer: D) -> ::core::result::Result<Self, D::Error>
3548
+ where
3549
+ D: serde::Deserializer<'de>,
3550
+ {
3551
+ <crawlberg::CrawlResult as serde::Deserialize>::deserialize(deserializer).map(Into::into)
3552
+ }
3553
+ }
3498
3554
 
3499
3555
  impl Default for CrawlResult {
3500
3556
  fn default() -> Self {
@@ -3581,6 +3637,15 @@ impl CrawlResult {
3581
3637
  })?,
3582
3638
  None => Default::default(),
3583
3639
  },
3640
+ waf_block: match kwargs.get(ruby.to_symbol("waf_block")).filter(|v| !v.is_nil()) {
3641
+ Some(v) => Some(WafBlockDetails::try_convert(v).map_err(|e| {
3642
+ magnus::Error::new(
3643
+ unsafe { magnus::Ruby::get_unchecked() }.exception_type_error(),
3644
+ format!("invalid value for `waf_block`: {}", e),
3645
+ )
3646
+ })?),
3647
+ None => None,
3648
+ },
3584
3649
  })
3585
3650
  }
3586
3651
 
@@ -3616,6 +3681,10 @@ impl CrawlResult {
3616
3681
  self.browser_used
3617
3682
  }
3618
3683
 
3684
+ fn waf_block(&self) -> Option<WafBlockDetails> {
3685
+ self.waf_block.clone()
3686
+ }
3687
+
3619
3688
  fn unique_normalized_urls(&self) -> usize {
3620
3689
  #[allow(clippy::needless_update)]
3621
3690
  let core_self = crawlberg::CrawlResult {
@@ -3635,6 +3704,8 @@ impl CrawlResult {
3635
3704
 
3636
3705
  browser_used: self.browser_used,
3637
3706
 
3707
+ waf_block: self.waf_block.clone().map(Into::into),
3708
+
3638
3709
  ..Default::default()
3639
3710
  };
3640
3711
  core_self.unique_normalized_urls()
@@ -6845,6 +6916,99 @@ impl SsrfPolicy {
6845
6916
  }
6846
6917
  }
6847
6918
 
6919
+ #[derive(Clone, Debug, serde::Serialize, serde::Deserialize)]
6920
+ #[serde(default)]
6921
+ #[magnus::wrap(class = "Crawlberg::WafBlockDetails")]
6922
+ pub struct WafBlockDetails {
6923
+ vendor: String,
6924
+ status: Option<u16>,
6925
+ body_prefix: Option<String>,
6926
+ }
6927
+
6928
+ unsafe impl IntoValueFromNative for WafBlockDetails {}
6929
+
6930
+ impl magnus::TryConvert for WafBlockDetails {
6931
+ fn try_convert(val: magnus::Value) -> Result<Self, magnus::Error> {
6932
+ if let Ok(r) = <&WafBlockDetails as magnus::TryConvert>::try_convert(val) {
6933
+ return Ok(r.clone());
6934
+ }
6935
+ let json_str: String = if let Ok(s) = <String as magnus::TryConvert>::try_convert(val) {
6936
+ s
6937
+ } else {
6938
+ val.funcall::<_, _, String>("to_json", ()).map_err(|e| {
6939
+ magnus::Error::new(
6940
+ unsafe { magnus::Ruby::get_unchecked() }.exception_type_error(),
6941
+ format!("no implicit conversion into WafBlockDetails: {}", e),
6942
+ )
6943
+ })?
6944
+ };
6945
+ serde_json::from_str::<WafBlockDetails>(&json_str).map_err(|e| {
6946
+ magnus::Error::new(
6947
+ unsafe { magnus::Ruby::get_unchecked() }.exception_type_error(),
6948
+ format!("failed to deserialize WafBlockDetails: {}", e),
6949
+ )
6950
+ })
6951
+ }
6952
+ }
6953
+
6954
+ unsafe impl TryConvertOwned for WafBlockDetails {}
6955
+
6956
+ impl Default for WafBlockDetails {
6957
+ fn default() -> Self {
6958
+ crawlberg::WafBlockDetails::default().into()
6959
+ }
6960
+ }
6961
+
6962
+ impl WafBlockDetails {
6963
+ fn new(args: &[magnus::Value]) -> Result<Self, magnus::Error> {
6964
+ let ruby = unsafe { magnus::Ruby::get_unchecked() };
6965
+ let args = magnus::scan_args::scan_args::<(), (Option<magnus::RHash>,), (), (), (), ()>(args)?;
6966
+ let (kwargs_opt,) = args.optional;
6967
+ let kwargs = kwargs_opt.unwrap_or_else(|| ruby.hash_new());
6968
+ Ok(Self {
6969
+ vendor: match kwargs.get(ruby.to_symbol("vendor")) {
6970
+ Some(v) => String::try_convert(v).map_err(|e| {
6971
+ magnus::Error::new(
6972
+ unsafe { magnus::Ruby::get_unchecked() }.exception_type_error(),
6973
+ format!("invalid value for `vendor`: {}", e),
6974
+ )
6975
+ })?,
6976
+ None => Default::default(),
6977
+ },
6978
+ status: match kwargs.get(ruby.to_symbol("status")).filter(|v| !v.is_nil()) {
6979
+ Some(v) => Some(u16::try_convert(v).map_err(|e| {
6980
+ magnus::Error::new(
6981
+ unsafe { magnus::Ruby::get_unchecked() }.exception_type_error(),
6982
+ format!("invalid value for `status`: {}", e),
6983
+ )
6984
+ })?),
6985
+ None => None,
6986
+ },
6987
+ body_prefix: match kwargs.get(ruby.to_symbol("body_prefix")).filter(|v| !v.is_nil()) {
6988
+ Some(v) => Some(String::try_convert(v).map_err(|e| {
6989
+ magnus::Error::new(
6990
+ unsafe { magnus::Ruby::get_unchecked() }.exception_type_error(),
6991
+ format!("invalid value for `body_prefix`: {}", e),
6992
+ )
6993
+ })?),
6994
+ None => None,
6995
+ },
6996
+ })
6997
+ }
6998
+
6999
+ fn vendor(&self) -> String {
7000
+ self.vendor.clone()
7001
+ }
7002
+
7003
+ fn status(&self) -> Option<u16> {
7004
+ self.status
7005
+ }
7006
+
7007
+ fn body_prefix(&self) -> Option<String> {
7008
+ self.body_prefix.clone()
7009
+ }
7010
+ }
7011
+
6848
7012
  #[derive(Clone, Copy, PartialEq, Eq, Hash, Debug, serde::Serialize, serde::Deserialize)]
6849
7013
  #[serde(rename_all = "snake_case")]
6850
7014
  pub enum AssetCategory {
@@ -8136,6 +8300,8 @@ impl From<BrowserConfig> for crawlberg::BrowserConfig {
8136
8300
  session_affinity: val.session_affinity,
8137
8301
  chrome_path: val.chrome_path.map(Into::into),
8138
8302
  chrome_args: val.chrome_args.into_iter().collect(),
8303
+ scroll_containers: val.scroll_containers,
8304
+ dom_quiet_window: std::time::Duration::from_millis(val.dom_quiet_window),
8139
8305
  ..Default::default()
8140
8306
  }
8141
8307
  }
@@ -8162,6 +8328,8 @@ impl From<crawlberg::BrowserConfig> for BrowserConfig {
8162
8328
  session_affinity: val.session_affinity,
8163
8329
  chrome_path: val.chrome_path.map(|p| p.to_string_lossy().to_string()),
8164
8330
  chrome_args: val.chrome_args.into_iter().collect(),
8331
+ scroll_containers: val.scroll_containers,
8332
+ dom_quiet_window: val.dom_quiet_window.as_millis() as u64,
8165
8333
  }
8166
8334
  }
8167
8335
  }
@@ -8379,6 +8547,7 @@ impl From<CrawlConfig> for crawlberg::CrawlConfig {
8379
8547
  save_browser_profile: val.save_browser_profile,
8380
8548
  ssrf: val.ssrf.into(),
8381
8549
  ssrf_deny_private_explicit: val.ssrf_deny_private_explicit,
8550
+ danger_accept_invalid_certs: val.danger_accept_invalid_certs,
8382
8551
  ..Default::default()
8383
8552
  }
8384
8553
  }
@@ -8447,6 +8616,7 @@ impl From<crawlberg::CrawlConfig> for CrawlConfig {
8447
8616
  save_browser_profile: val.save_browser_profile,
8448
8617
  ssrf: val.ssrf.into(),
8449
8618
  ssrf_deny_private_explicit: val.ssrf_deny_private_explicit,
8619
+ danger_accept_invalid_certs: val.danger_accept_invalid_certs,
8450
8620
  }
8451
8621
  }
8452
8622
  }
@@ -8536,6 +8706,7 @@ impl From<CrawlResult> for crawlberg::CrawlResult {
8536
8706
  cookies: val.cookies.into_iter().map(Into::into).collect(),
8537
8707
  stayed_on_domain: val.stayed_on_domain,
8538
8708
  browser_used: val.browser_used,
8709
+ waf_block: val.waf_block.map(Into::into),
8539
8710
  ..Default::default()
8540
8711
  }
8541
8712
  }
@@ -8553,6 +8724,7 @@ impl From<crawlberg::CrawlResult> for CrawlResult {
8553
8724
  cookies: val.cookies.into_iter().map(Into::into).collect(),
8554
8725
  stayed_on_domain: val.stayed_on_domain,
8555
8726
  browser_used: val.browser_used,
8727
+ waf_block: val.waf_block.map(Into::into),
8556
8728
  }
8557
8729
  }
8558
8730
  }
@@ -9214,6 +9386,29 @@ impl From<crawlberg::SsrfPolicy> for SsrfPolicy {
9214
9386
  }
9215
9387
  }
9216
9388
 
9389
+ #[allow(clippy::needless_update)]
9390
+ impl From<WafBlockDetails> for crawlberg::WafBlockDetails {
9391
+ fn from(val: WafBlockDetails) -> Self {
9392
+ Self {
9393
+ vendor: val.vendor,
9394
+ status: val.status,
9395
+ body_prefix: val.body_prefix,
9396
+ ..Default::default()
9397
+ }
9398
+ }
9399
+ }
9400
+
9401
+ #[allow(clippy::redundant_closure)]
9402
+ impl From<crawlberg::WafBlockDetails> for WafBlockDetails {
9403
+ fn from(val: crawlberg::WafBlockDetails) -> Self {
9404
+ Self {
9405
+ vendor: val.vendor.to_string(),
9406
+ status: val.status,
9407
+ body_prefix: val.body_prefix.map(|v| v.to_string()),
9408
+ }
9409
+ }
9410
+ }
9411
+
9217
9412
  impl From<AssetCategory> for crawlberg::AssetCategory {
9218
9413
  fn from(val: AssetCategory) -> Self {
9219
9414
  match val {
@@ -9876,6 +10071,10 @@ fn ruby_init(ruby: &Ruby) -> Result<(), Error> {
9876
10071
 
9877
10072
  class.define_method("chrome_args", method!(BrowserConfig::chrome_args, 0))?;
9878
10073
 
10074
+ class.define_method("scroll_containers", method!(BrowserConfig::scroll_containers, 0))?;
10075
+
10076
+ class.define_method("dom_quiet_window", method!(BrowserConfig::dom_quiet_window, 0))?;
10077
+
9879
10078
  let class = module.define_class("BrowserExtras", ruby.class_object())?;
9880
10079
 
9881
10080
  class.define_singleton_method("new", function!(BrowserExtras::new, -1))?;
@@ -10100,6 +10299,11 @@ fn ruby_init(ruby: &Ruby) -> Result<(), Error> {
10100
10299
  method!(CrawlConfig::ssrf_deny_private_explicit, 0),
10101
10300
  )?;
10102
10301
 
10302
+ class.define_method(
10303
+ "danger_accept_invalid_certs",
10304
+ method!(CrawlConfig::danger_accept_invalid_certs, 0),
10305
+ )?;
10306
+
10103
10307
  class.define_method("validate", method!(CrawlConfig::validate, 0))?;
10104
10308
 
10105
10309
  let class = module.define_class("CrawlEngineHandle", ruby.class_object())?;
@@ -10185,6 +10389,8 @@ fn ruby_init(ruby: &Ruby) -> Result<(), Error> {
10185
10389
 
10186
10390
  class.define_method("browser_used", method!(CrawlResult::browser_used, 0))?;
10187
10391
 
10392
+ class.define_method("waf_block", method!(CrawlResult::waf_block, 0))?;
10393
+
10188
10394
  class.define_method(
10189
10395
  "unique_normalized_urls",
10190
10396
  method!(CrawlResult::unique_normalized_urls, 0),
@@ -10574,6 +10780,16 @@ fn ruby_init(ruby: &Ruby) -> Result<(), Error> {
10574
10780
 
10575
10781
  class.define_method("scheme_allowlist", method!(SsrfPolicy::scheme_allowlist, 0))?;
10576
10782
 
10783
+ let class = module.define_class("WafBlockDetails", ruby.class_object())?;
10784
+
10785
+ class.define_singleton_method("new", function!(WafBlockDetails::new, -1))?;
10786
+
10787
+ class.define_method("vendor", method!(WafBlockDetails::vendor, 0))?;
10788
+
10789
+ class.define_method("status", method!(WafBlockDetails::status, 0))?;
10790
+
10791
+ class.define_method("body_prefix", method!(WafBlockDetails::body_prefix, 0))?;
10792
+
10577
10793
  let class = module.define_class("CrawlStreamIterator", ruby.class_object())?;
10578
10794
  class.define_method("next_chunk", method!(CrawlStreamIterator::next_chunk, 0))?;
10579
10795
  class.define_method("each", method!(CrawlStreamIterator::each, 0))?;
@@ -1,5 +1,5 @@
1
1
  # This file is auto-generated by alef — DO NOT EDIT.
2
- # alef:hash:d323ed0aab9764791b48678b68c8fedcf8e7b3e1dbe50ec190a9023e68acc3bb
2
+ # alef:hash:60c8949f72e7c9412406a7c721b2968d8acafde7ead2534f00d423542e33bade
3
3
  # To regenerate: alef generate
4
4
  # To verify freshness: alef verify
5
5
  # frozen_string_literal: true
@@ -164,6 +164,10 @@ module Crawlberg
164
164
  end
165
165
  end
166
166
  ## A single page has been crawled.
167
+ ##
168
+ ## A link whose redirect lands on a URL the crawl already queued or visited gets no event of
169
+ ## its own: it is requested, then dropped as a duplicate of the destination, which is reported
170
+ ## once under its own URL. The request count can therefore exceed the event count.
167
171
  CrawlEventPage = Data.define(:result) do
168
172
  include CrawlEvent
169
173
  extend T::Sig
@@ -1,10 +1,10 @@
1
1
  # This file is auto-generated by alef — DO NOT EDIT.
2
- # alef:hash:0fcaeaf159ae13b7e3d56e201029880b4cf648beeb0bb8efc6d0ff175d94e894
2
+ # alef:hash:ed92ed554ddf1dcb4d5a619d4a13d01d9287c96310437df1c7a4c484d27b969c
3
3
  # To regenerate: alef generate
4
4
  # To verify freshness: alef verify
5
5
  # frozen_string_literal: true
6
6
 
7
7
  module Crawlberg
8
8
  ## The version string for this package.
9
- VERSION = "1.11.1"
9
+ VERSION = "1.12.0"
10
10
  end
data/sig/types.rbs CHANGED
@@ -1,5 +1,5 @@
1
1
  # This file is auto-generated by alef — DO NOT EDIT.
2
- # alef:hash:ad470f62b746634fbd629f163e7bae4a88fb011bbde28d998e38ade4877adf3f
2
+ # alef:hash:a2ea8938a47348aa37d91448784e4263e6b5f4df1fe3a7ff1f9a8bdd3bf04009
3
3
  # To regenerate: alef generate
4
4
  # To verify freshness: alef verify
5
5
 
@@ -87,8 +87,10 @@ def initialize: (?results: Array[BatchScrapeResult], ?total_count: Integer, ?com
87
87
  attr_reader session_affinity: bool
88
88
  attr_reader chrome_path: String?
89
89
  attr_reader chrome_args: Array[String]
90
+ attr_reader scroll_containers: bool
91
+ attr_reader dom_quiet_window: Integer
90
92
 
91
- def initialize: (?mode: enum_BrowserMode, ?backend: enum_BrowserBackend, ?endpoint: String, ?timeout: Integer, ?overall_timeout: Integer, ?shutdown_timeout: Integer, ?wait: enum_BrowserWait, ?wait_selector: String, ?extra_wait: Integer, ?proxy: ProxyConfig, ?block_url_patterns: Array[String], ?eval_script: String, ?robots_user_agent: String, ?capture_network_events: bool, ?session_affinity: bool, ?chrome_path: String, ?chrome_args: Array[String]) -> void
93
+ def initialize: (?mode: enum_BrowserMode, ?backend: enum_BrowserBackend, ?endpoint: String, ?timeout: Integer, ?overall_timeout: Integer, ?shutdown_timeout: Integer, ?wait: enum_BrowserWait, ?wait_selector: String, ?extra_wait: Integer, ?proxy: ProxyConfig, ?block_url_patterns: Array[String], ?eval_script: String, ?robots_user_agent: String, ?capture_network_events: bool, ?session_affinity: bool, ?chrome_path: String, ?chrome_args: Array[String], ?scroll_containers: bool, ?dom_quiet_window: Integer) -> void
92
94
  end
93
95
 
94
96
  class BrowserExtras
@@ -204,8 +206,9 @@ def initialize: (?output_format: String, ?preprocessing_preset: String, ?remove_
204
206
  attr_reader save_browser_profile: bool
205
207
  attr_reader ssrf: SsrfPolicy
206
208
  attr_reader ssrf_deny_private_explicit: bool?
209
+ attr_reader danger_accept_invalid_certs: bool
207
210
 
208
- def initialize: (?max_depth: Integer, ?max_pages: Integer, ?max_links_per_page: Integer, ?max_concurrent: Integer, ?crawl_strategy: enum_CrawlStrategyKind, ?content_filter: enum_ContentFilterKind, ?bm25_query: String, ?bm25_threshold: Float, ?respect_robots_txt: bool, ?soft_http_errors: bool, ?user_agent: String, ?stay_on_domain: bool, ?allow_subdomains: bool, ?include_paths: Array[String], ?exclude_paths: Array[String], ?path_patterns_match_query: bool, ?path_patterns_match_url: bool, ?dedup_include_query: bool, ?strip_tracking_params: bool, ?tracking_params: Array[String], ?custom_headers: Hash[String, String], ?request_timeout: Integer, ?rate_limit_ms: Integer, ?max_redirects: Integer, ?retry_count: Integer, ?retry_codes: Array[Integer], ?retry_initial_delay_ms: Integer, ?retry_max_delay_ms: Integer, ?rate_limit_jitter_ratio: Float, ?cookies_enabled: bool, ?auth: AuthConfig, ?max_body_size: Integer, ?remove_tags: Array[String], ?content: ContentConfig, ?map_limit: Integer, ?map_search: String, ?download_assets: bool, ?asset_types: Array[enum_AssetCategory], ?max_asset_size: Integer, ?browser: BrowserConfig, ?proxy: ProxyConfig, ?user_agents: Array[String], ?capture_screenshot: bool, ?follow_document_urls: bool, ?document_url_depth: Integer, ?download_documents: bool, ?document_max_size: Integer, ?document_mime_types: Array[String], ?document_output_dir: String, ?document_content_encoding: enum_DocumentContentEncoding, ?warc_output: String, ?browser_profile: String, ?save_browser_profile: bool, ?ssrf: SsrfPolicy, ?ssrf_deny_private_explicit: bool) -> void
211
+ def initialize: (?max_depth: Integer, ?max_pages: Integer, ?max_links_per_page: Integer, ?max_concurrent: Integer, ?crawl_strategy: enum_CrawlStrategyKind, ?content_filter: enum_ContentFilterKind, ?bm25_query: String, ?bm25_threshold: Float, ?respect_robots_txt: bool, ?soft_http_errors: bool, ?user_agent: String, ?stay_on_domain: bool, ?allow_subdomains: bool, ?include_paths: Array[String], ?exclude_paths: Array[String], ?path_patterns_match_query: bool, ?path_patterns_match_url: bool, ?dedup_include_query: bool, ?strip_tracking_params: bool, ?tracking_params: Array[String], ?custom_headers: Hash[String, String], ?request_timeout: Integer, ?rate_limit_ms: Integer, ?max_redirects: Integer, ?retry_count: Integer, ?retry_codes: Array[Integer], ?retry_initial_delay_ms: Integer, ?retry_max_delay_ms: Integer, ?rate_limit_jitter_ratio: Float, ?cookies_enabled: bool, ?auth: AuthConfig, ?max_body_size: Integer, ?remove_tags: Array[String], ?content: ContentConfig, ?map_limit: Integer, ?map_search: String, ?download_assets: bool, ?asset_types: Array[enum_AssetCategory], ?max_asset_size: Integer, ?browser: BrowserConfig, ?proxy: ProxyConfig, ?user_agents: Array[String], ?capture_screenshot: bool, ?follow_document_urls: bool, ?document_url_depth: Integer, ?download_documents: bool, ?document_max_size: Integer, ?document_mime_types: Array[String], ?document_output_dir: String, ?document_content_encoding: enum_DocumentContentEncoding, ?warc_output: String, ?browser_profile: String, ?save_browser_profile: bool, ?ssrf: SsrfPolicy, ?ssrf_deny_private_explicit: bool, ?danger_accept_invalid_certs: bool) -> void
209
212
  def validate: () -> void
210
213
  end
211
214
 
@@ -255,8 +258,9 @@ def initialize: (?url: String, ?normalized_url: String, ?status_code: Integer, ?
255
258
  attr_reader cookies: Array[CookieInfo]
256
259
  attr_reader stayed_on_domain: bool
257
260
  attr_reader browser_used: bool
261
+ attr_reader waf_block: WafBlockDetails?
258
262
 
259
- def initialize: (?pages: Array[CrawlPageResult], ?final_url: String, ?redirect_count: Integer, ?was_skipped: bool, ?error: String, ?cookies: Array[CookieInfo], ?stayed_on_domain: bool, ?browser_used: bool) -> void
263
+ def initialize: (?pages: Array[CrawlPageResult], ?final_url: String, ?redirect_count: Integer, ?was_skipped: bool, ?error: String, ?cookies: Array[CookieInfo], ?stayed_on_domain: bool, ?browser_used: bool, ?waf_block: WafBlockDetails) -> void
260
264
  def unique_normalized_urls: () -> Integer
261
265
  end
262
266
 
@@ -510,6 +514,14 @@ def initialize: (?status_code: Integer, ?final_url: String, ?content_type: Strin
510
514
  def initialize: (?deny_private: bool, ?allowlist: Array[HostMatcher], ?denylist: Array[HostMatcher], ?max_redirects: Integer, ?scheme_allowlist: Array[String]) -> void
511
515
  end
512
516
 
517
+ class WafBlockDetails
518
+ attr_reader vendor: String
519
+ attr_reader status: Integer?
520
+ attr_reader body_prefix: String?
521
+
522
+ def initialize: (?vendor: String, ?status: Integer, ?body_prefix: String) -> void
523
+ end
524
+
513
525
  type enum_AssetCategory = :document | :image | :audio | :video | :font | :stylesheet | :script | :archive | :data | :other
514
526
 
515
527
  class AuthConfig
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: crawlberg
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.11.1
4
+ version: 1.12.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Na'aman Hirschfeld
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2026-10-16 00:00:00.000000000 Z
12
+ date: 2026-10-22 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: rb_sys