universal-parcel-scraper 0.809.2-main.4367 → 0.811.0-main.4377

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.
package/README.md CHANGED
@@ -161,7 +161,7 @@ the command line's `track --source ParcelsApp` does the same.
161
161
  <!-- GENERATED:stages -->
162
162
  <img src="docs/assets/stages.svg" alt="DHL: Die Sendung wurde in das Zustellfahrzeug geladen.; Mondial Relay: En cours de livraison; Correios Brazil: Objeto saiu para entrega ao destinatário; Correos Express: EN REPARTO; Yamato Transport: 配達中; La Poste / Colissimo: DISTOU. All are filed under out_for_delivery." width="760">
163
163
 
164
- The carrier folders record 17,645 such statuses, each filed under one stage.
164
+ The carrier folders record 17,648 such statuses, each filed under one stage.
165
165
  <!-- /GENERATED:stages -->
166
166
 
167
167
  Wording nobody recorded yet goes through a classifier that reads seven European languages.
package/data/catalog.json CHANGED
@@ -427,6 +427,8 @@
427
427
  "autoComplete": "postal-code"
428
428
  }
429
429
  ],
430
+ "recognitionRank": 524,
431
+ "recognitionPattern": "^1810\\d{14}$",
430
432
  "refresh": {
431
433
  "minMinutes": 30
432
434
  },
@@ -476,6 +478,10 @@
476
478
  {
477
479
  "pattern": "^(?=.{13}$|.{15}$)3S[A-Z]{1,3}\\d+$",
478
480
  "confidence": "low"
481
+ },
482
+ {
483
+ "pattern": "^1810\\d{14}$",
484
+ "confidence": "low"
479
485
  }
480
486
  ]
481
487
  },
@@ -27785,6 +27791,10 @@
27785
27791
  {
27786
27792
  "pattern": "^PKG\\d{5}(?:0[1-9]|1[0-2])(?:0[1-9]|[12]\\d|3[01])ES\\d{13}[A-Z]$",
27787
27793
  "confidence": "low"
27794
+ },
27795
+ {
27796
+ "pattern": "^WT\\d{16}$",
27797
+ "confidence": "low"
27788
27798
  }
27789
27799
  ]
27790
27800
  },
@@ -30508,7 +30518,7 @@
30508
30518
  ],
30509
30519
  "detectionRules": [
30510
30520
  {
30511
- "pattern": "^(?:AE|EG|GH|KE|KZ|MA|MU|MV|NG|PK|RE|RW|SA|TR|UG|ZA|ZM)\\d{12}T?$",
30521
+ "pattern": "^(?:AE|EG|GH|IE|KE|KZ|MA|MU|MV|NG|PK|RE|RW|SA|TR|UG|ZA|ZM)\\d{12}T?$",
30512
30522
  "confidence": "low"
30513
30523
  },
30514
30524
  {
@@ -20397,6 +20397,19 @@
20397
20397
  "heppner"
20398
20398
  ]
20399
20399
  },
20400
+ {
20401
+ "input": "181011000000000017",
20402
+ "carrier": "unknown",
20403
+ "confidence": "low",
20404
+ "candidates": [
20405
+ "spring-gds",
20406
+ "bpost",
20407
+ "ecoscooting"
20408
+ ],
20409
+ "asked": [
20410
+ "spring-gds"
20411
+ ]
20412
+ },
20400
20413
  {
20401
20414
  "input": "18113149",
20402
20415
  "carrier": "unknown",
@@ -78708,6 +78721,17 @@
78708
78721
  "amazon-logistics"
78709
78722
  ]
78710
78723
  },
78724
+ {
78725
+ "input": "IE120000000017",
78726
+ "carrier": "unknown",
78727
+ "confidence": "low",
78728
+ "candidates": [
78729
+ "speedaf"
78730
+ ],
78731
+ "asked": [
78732
+ "speedaf"
78733
+ ]
78734
+ },
78711
78735
  {
78712
78736
  "input": "IEG9246514",
78713
78737
  "carrier": "unknown",
@@ -95661,8 +95685,13 @@
95661
95685
  {
95662
95686
  "input": "WT2527401177023677",
95663
95687
  "carrier": "unknown",
95664
- "confidence": "none",
95665
- "candidates": []
95688
+ "confidence": "low",
95689
+ "candidates": [
95690
+ "quick-rabbit"
95691
+ ],
95692
+ "asked": [
95693
+ "quick-rabbit"
95694
+ ]
95666
95695
  },
95667
95696
  {
95668
95697
  "input": "WX6Z9T",
@@ -685,6 +685,8 @@ var tt = {
685
685
  inputMode: "text",
686
686
  autoComplete: "postal-code"
687
687
  }],
688
+ recognitionRank: 524,
689
+ recognitionPattern: "^1810\\d{14}$",
688
690
  refresh: { minMinutes: 30 },
689
691
  localClocks: !0
690
692
  },
@@ -722,6 +724,10 @@ var tt = {
722
724
  {
723
725
  pattern: "^(?=.{13}$|.{15}$)3S[A-Z]{1,3}\\d+$",
724
726
  confidence: "low"
727
+ },
728
+ {
729
+ pattern: "^1810\\d{14}$",
730
+ confidence: "low"
725
731
  }
726
732
  ]
727
733
  },
@@ -21162,13 +21168,20 @@ var tt = {
21162
21168
  pathPattern: "^/(?:[a-z]{2}/)?tracking/?$",
21163
21169
  params: ["ref"]
21164
21170
  }],
21165
- detectionRules: [{
21166
- pattern: "^PKG\\d{3}20\\d{2}(?:0[1-9]|1[0-2])(?:0[1-9]|[12]\\d|3[01])\\d{9}$",
21167
- confidence: "high"
21168
- }, {
21169
- pattern: "^PKG\\d{5}(?:0[1-9]|1[0-2])(?:0[1-9]|[12]\\d|3[01])ES\\d{13}[A-Z]$",
21170
- confidence: "low"
21171
- }]
21171
+ detectionRules: [
21172
+ {
21173
+ pattern: "^PKG\\d{3}20\\d{2}(?:0[1-9]|1[0-2])(?:0[1-9]|[12]\\d|3[01])\\d{9}$",
21174
+ confidence: "high"
21175
+ },
21176
+ {
21177
+ pattern: "^PKG\\d{5}(?:0[1-9]|1[0-2])(?:0[1-9]|[12]\\d|3[01])ES\\d{13}[A-Z]$",
21178
+ confidence: "low"
21179
+ },
21180
+ {
21181
+ pattern: "^WT\\d{16}$",
21182
+ confidence: "low"
21183
+ }
21184
+ ]
21172
21185
  },
21173
21186
  "quicksilver-sa": {
21174
21187
  displayName: "Quicksilver",
@@ -23178,7 +23191,7 @@ var tt = {
23178
23191
  params: ["tradeNo"]
23179
23192
  }],
23180
23193
  detectionRules: [{
23181
- pattern: "^(?:AE|EG|GH|KE|KZ|MA|MU|MV|NG|PK|RE|RW|SA|TR|UG|ZA|ZM)\\d{12}T?$",
23194
+ pattern: "^(?:AE|EG|GH|IE|KE|KZ|MA|MU|MV|NG|PK|RE|RW|SA|TR|UG|ZA|ZM)\\d{12}T?$",
23182
23195
  confidence: "low"
23183
23196
  }, {
23184
23197
  pattern: "^(?:AE|EG|GH|KE|KZ|MA|MU|MV|NG|PK|RE|RW|SA|TR|UG|ZA|ZM)\\d{9}[ER]$",
@@ -26880,7 +26893,8 @@ var tt = {
26880
26893
  "spring-gds": [
26881
26894
  "spring-gds-1",
26882
26895
  "spring-gds-2",
26883
- "spring-gds-3"
26896
+ "spring-gds-3",
26897
+ "spring-gds-1810"
26884
26898
  ],
26885
26899
  postlogistics: ["postlogistics-dashed-reference", "postlogistics-compact-reference"],
26886
26900
  dachser: [],
@@ -27914,7 +27928,11 @@ var tt = {
27914
27928
  "pushpak-courier": [],
27915
27929
  "quality-post": [],
27916
27930
  "quantium-solutions": [],
27917
- "quick-rabbit": ["quick-rabbit-1", "quick-rabbit-2"],
27931
+ "quick-rabbit": [
27932
+ "quick-rabbit-1",
27933
+ "quick-rabbit-2",
27934
+ "quick-rabbit-3"
27935
+ ],
27918
27936
  "quicksilver-sa": ["quicksilver-sa-1"],
27919
27937
  quiqup: [],
27920
27938
  qwintry: ["qwintry-1"],
@@ -34304,6 +34322,7 @@ var Uu = {
34304
34322
  speedaf: 989,
34305
34323
  speedex: 938,
34306
34324
  speedy: 280,
34325
+ "spring-gds": 524,
34307
34326
  "spx-br": 982,
34308
34327
  "st-courier": 753,
34309
34328
  "stallion-express": 105,
@@ -7,6 +7,8 @@
7
7
  {"wording": "预计…飞", "language": "zh", "english": "Flight booked", "stage": "in_transit", "confirmedBy": "source", "note": "The row names the day the flight is expected to leave, as month-day; the key replaces it with an ellipsis and the English leaves it out, since it is still to come. As a universal provider relays it."},
8
8
  {"wording": "已飞未落地", "language": "zh", "english": "Flight departed, not yet landed", "stage": "in_transit", "confirmedBy": "source", "note": "As a universal provider relays it."},
9
9
  {"wording": "一程已落地 二程预计…飞", "language": "zh", "english": "First flight landed, connecting flight booked", "stage": "in_transit", "confirmedBy": "source", "note": "The first leg has landed; the row names the day the second is expected to leave, which the key replaces with an ellipsis. As a universal provider relays it."},
10
- {"wording": "二程已飞未落地", "language": "zh", "english": "Connecting flight departed, not yet landed", "stage": "in_transit", "confirmedBy": "source", "note": "As a universal provider relays it."}
10
+ {"wording": "二程已飞未落地", "language": "zh", "english": "Connecting flight departed, not yet landed", "stage": "in_transit", "confirmedBy": "source", "note": "As a universal provider relays it."},
11
+ {"wording": "已落地 等待拆板提货", "language": "zh", "english": "Landed, awaiting unloading for collection", "stage": "in_transit", "confirmedBy": "live", "firstSeen": "2026-10-29", "note": "The last flight has landed; its pallets are still to be broken down and the shipment collected from the airport."},
12
+ {"wording": "已提回 等待清关", "language": "zh", "english": "Collected from the airport, awaiting customs clearance", "stage": "customs", "confirmedBy": "live", "firstSeen": "2026-10-29", "note": "Collected from the airport and held for import clearance, as other forwarders' rows of the same step read."}
11
13
  ]
12
14
  }
@@ -87,6 +87,11 @@
87
87
  "id": "quick-rabbit-2",
88
88
  "pattern": "^PKG\\d{5}(?:0[1-9]|1[0-2])(?:0[1-9]|[12]\\d|3[01])ES\\d{13}[A-Z]$",
89
89
  "confidence": "low"
90
+ },
91
+ {
92
+ "id": "quick-rabbit-3",
93
+ "pattern": "^WT\\d{16}$",
94
+ "confidence": "low"
90
95
  }
91
96
  ]
92
97
  }
@@ -109,9 +109,12 @@
109
109
  },
110
110
  "expect": {
111
111
  "carrier": "unknown",
112
- "confidence": "none"
112
+ "confidence": "low",
113
+ "candidates": [
114
+ "quick-rabbit"
115
+ ]
113
116
  },
114
- "note": "The shipper’s reference, which the tracker also answers for; its owner is not known, so it gets no rule."
117
+ "note": "The shipper’s reference, which the tracker also answers for. Its issuer is not known, so a low rule suggests Quick Rabbit and recognition asks its tracker."
115
118
  }
116
119
  ]
117
120
  }
@@ -114,7 +114,7 @@
114
114
  "detection": [
115
115
  {
116
116
  "id": "speedaf-12",
117
- "pattern": "^(?:AE|EG|GH|KE|KZ|MA|MU|MV|NG|PK|RE|RW|SA|TR|UG|ZA|ZM)\\d{12}T?$",
117
+ "pattern": "^(?:AE|EG|GH|IE|KE|KZ|MA|MU|MV|NG|PK|RE|RW|SA|TR|UG|ZA|ZM)\\d{12}T?$",
118
118
  "confidence": "low"
119
119
  },
120
120
  {
@@ -734,6 +734,21 @@
734
734
  "confidence": "none"
735
735
  },
736
736
  "note": "A reply to Speedaf Nigeria on X gives it, and Speedaf answers that the number looks wrong."
737
+ },
738
+ {
739
+ "number": "IE120000000017",
740
+ "role": "shipment",
741
+ "evidence": "synthetic",
742
+ "derivedFrom": "donated_real",
743
+ "shapeConfirmed": "2026-10-29",
744
+ "expect": {
745
+ "carrier": "unknown",
746
+ "confidence": "low",
747
+ "candidates": [
748
+ "speedaf"
749
+ ]
750
+ },
751
+ "note": "Made-up number in the shape of an Irish one: IE and twelve digits, the layout Speedaf gives its parcels for other countries. Speedaf's site lists a customer service in Ireland; no public page shows an Irish number."
737
752
  }
738
753
  ]
739
754
  }
@@ -22,7 +22,7 @@
22
22
  * delivery postcode. With a Dutch postcode, or another country's postcode
23
23
  * given with that country, that tracker is asked first.
24
24
  */
25
- import type { AdapterFactory, TrackingContext } from '../../core/adapter/index.js';
25
+ import { type AdapterFactory, type TrackingContext } from '../../core/adapter/index.js';
26
26
  import type { CarrierResult } from '../../core/result/index.js';
27
27
  import { type StepRecorder } from '../../core/telemetry/index.js';
28
28
  /** Projects one `tracking-items` payload. Pure: the offline tests target this. */
@@ -1,3 +1,29 @@
1
+ /**
2
+ * PostNL international tracking (carrier id `spring-gds`).
3
+ *
4
+ * The folder keeps the historical `spring-gds` id for parcels and clients that
5
+ * already store it; the carrier is presented as PostNL everywhere else. Spring
6
+ * GDS is PostNL's international subsidiary and its mailingtechnology.com
7
+ * portal shows the same barcode (see this folder's README).
8
+ *
9
+ * `postnl.post` hands out a visitor token that lasts a day to anyone who asks,
10
+ * then accepts a batch tracking request with it. The tracker keeps the token
11
+ * for its later lookups. Both calls replay once after a transport failure or an
12
+ * HTTP 502/503/504, and an HTTP 429 only when it supplies a short, valid
13
+ * `Retry-After` that ends before the lookup does. A 429 left standing names the
14
+ * wait PostNL asked for.
15
+ *
16
+ * The response echoes the requested barcodes, so the item whose `item` equals
17
+ * the requested number is the only one read. PostNL answers an unknown barcode
18
+ * with an ordinary item that has no events and says so in `message`.
19
+ *
20
+ * A 3S barcode sent within the Netherlands is not there: PostNL's domestic
21
+ * tracker on jouw.postnl.nl shows it, given the barcode, the country and the
22
+ * delivery postcode. With a Dutch postcode, or another country's postcode
23
+ * given with that country, that tracker is asked first.
24
+ */
25
+ import { recognizeFromLookup } from '../../core/adapter/index.js';
26
+ import { CARRIER_DEFINITIONS } from '../../core/catalog/definitions.js';
1
27
  import { DateTime } from 'luxon';
2
28
  import { CarrierError, IndeterminateError, InputRequiredError, NoHistoryError, NotFoundError, RateLimitedError, SchemaError, TransportError, UpstreamHttpError, UpstreamNetworkError, } from '../../core/errors/index.js';
3
29
  import { runSteps } from '../../core/runner/index.js';
@@ -8,6 +34,7 @@ import { fetchBounded, parseJsonBytes, userAgentOf } from '../../core/transport/
8
34
  import { isRecord } from '../../core/types.js';
9
35
  import { postNLCode, postNLDomesticStage, postNLStatus } from './status.js';
10
36
  const PROVIDER = 'PostNL';
37
+ const RECOGNIZED = new RegExp(CARRIER_DEFINITIONS['spring-gds']?.tracking.recognitionPattern ?? '(?!)');
11
38
  const TOKEN_URL = 'https://postnl.post/api/v1/auth/token';
12
39
  const TRACK_URL = 'https://postnl.post/api/v1/tracking-items';
13
40
  const DOMESTIC_URL = 'https://jouw.postnl.nl/track-and-trace/api/trackAndTrace';
@@ -449,5 +476,8 @@ export const adapter = (environment) => {
449
476
  // on the same host, and each replays once inside the step.
450
477
  steps: ['domestic', 'direct'],
451
478
  track: (input, context) => tracker.fetch(input.number, context, input.postcode, input.postcodeCountry),
479
+ // Only the series the catalog's recognition pattern names: a 3S barcode PostNL
480
+ // does not find may still be on the domestic tracker, behind a postcode.
481
+ recognize: (number, context) => recognizeFromLookup(() => tracker.fetch(number, context), () => RECOGNIZED.test(comparableIdentifier(number))),
452
482
  };
453
483
  };
@@ -40,6 +40,10 @@
40
40
  "domestic",
41
41
  "direct"
42
42
  ],
43
+ "recognition": {
44
+ "rank": 524,
45
+ "pattern": "^1810\\d{14}$"
46
+ },
43
47
  "refresh": {
44
48
  "minMinutes": 30
45
49
  },
@@ -118,6 +122,11 @@
118
122
  "id": "spring-gds-3",
119
123
  "pattern": "^(?=.{13}$|.{15}$)3S[A-Z]{1,3}\\d+$",
120
124
  "confidence": "low"
125
+ },
126
+ {
127
+ "id": "spring-gds-1810",
128
+ "pattern": "^1810\\d{14}$",
129
+ "confidence": "low"
121
130
  }
122
131
  ]
123
132
  }
@@ -595,6 +595,23 @@
595
595
  "confidence": "high"
596
596
  },
597
597
  "note": "A PostNL tracking link archived by the Wayback Machine. PostNL's tracker returns its history, an item delivered abroad."
598
+ },
599
+ {
600
+ "number": "181011000000000017",
601
+ "role": "shipment",
602
+ "evidence": "synthetic",
603
+ "derivedFrom": "donated_real",
604
+ "shapeConfirmed": "2026-10-29",
605
+ "expect": {
606
+ "carrier": "unknown",
607
+ "confidence": "low",
608
+ "candidates": [
609
+ "spring-gds",
610
+ "bpost",
611
+ "ecoscooting"
612
+ ]
613
+ },
614
+ "note": "Made-up number in the shape of a parcel for Italy that PostNL's international tracker answered: 1810 and fourteen digits."
598
615
  }
599
616
  ]
600
617
  }
@@ -6,6 +6,7 @@
6
6
  {"code": "Warehousing_Packed", "wording": "Parcel has been packed and is ready for outbound shipping", "stage": "in_transit", "language": "en", "confirmedBy": "live", "firstSeen": "2026-10-21", "note": "Packed at the warehouse for the line abroad; its Chinese name is 包裹装箱."},
7
7
  {"code": "Warehousing_Departed", "wording": "Departed from the original facility", "stage": "in_transit", "language": "en", "confirmedBy": "live", "firstSeen": "2026-10-25", "note": "The parcel left Techlink's warehouse in China."},
8
8
  {"code": "Decl_ExportDone", "wording": "Export customs declaration completed", "stage": "in_transit", "language": "en", "confirmedBy": "live", "firstSeen": "2026-10-25", "note": "China's export declaration, written after the parcel left the warehouse; the parcel is not held in customs."},
9
- {"code": "InTransit_Departure", "wording": "Depart from the original airport", "stage": "in_transit", "language": "en", "confirmedBy": "live", "firstSeen": "2026-10-26", "note": "The flight left the airport in China."}
9
+ {"code": "InTransit_Departure", "wording": "Depart from the original airport", "stage": "in_transit", "language": "en", "confirmedBy": "live", "firstSeen": "2026-10-26", "note": "The flight left the airport in China."},
10
+ {"code": "InTransit_Arrival", "wording": "Arrive at the destination airport", "stage": "in_transit", "language": "en", "confirmedBy": "live", "firstSeen": "2026-10-29", "note": "The flight landed in the destination country, before its import clearance."}
10
11
  ]
11
12
  }
@@ -427,6 +427,8 @@
427
427
  "autoComplete": "postal-code"
428
428
  }
429
429
  ],
430
+ "recognitionRank": 524,
431
+ "recognitionPattern": "^1810\\d{14}$",
430
432
  "refresh": {
431
433
  "minMinutes": 30
432
434
  },
@@ -476,6 +478,10 @@
476
478
  {
477
479
  "pattern": "^(?=.{13}$|.{15}$)3S[A-Z]{1,3}\\d+$",
478
480
  "confidence": "low"
481
+ },
482
+ {
483
+ "pattern": "^1810\\d{14}$",
484
+ "confidence": "low"
479
485
  }
480
486
  ]
481
487
  },
@@ -27785,6 +27791,10 @@
27785
27791
  {
27786
27792
  "pattern": "^PKG\\d{5}(?:0[1-9]|1[0-2])(?:0[1-9]|[12]\\d|3[01])ES\\d{13}[A-Z]$",
27787
27793
  "confidence": "low"
27794
+ },
27795
+ {
27796
+ "pattern": "^WT\\d{16}$",
27797
+ "confidence": "low"
27788
27798
  }
27789
27799
  ]
27790
27800
  },
@@ -30508,7 +30518,7 @@
30508
30518
  ],
30509
30519
  "detectionRules": [
30510
30520
  {
30511
- "pattern": "^(?:AE|EG|GH|KE|KZ|MA|MU|MV|NG|PK|RE|RW|SA|TR|UG|ZA|ZM)\\d{12}T?$",
30521
+ "pattern": "^(?:AE|EG|GH|IE|KE|KZ|MA|MU|MV|NG|PK|RE|RW|SA|TR|UG|ZA|ZM)\\d{12}T?$",
30512
30522
  "confidence": "low"
30513
30523
  },
30514
30524
  {
@@ -298,6 +298,8 @@ export declare const CARRIER_CATALOG: {
298
298
  readonly inputMode: "text";
299
299
  readonly autoComplete: "postal-code";
300
300
  }];
301
+ readonly recognitionRank: 524;
302
+ readonly recognitionPattern: "^1810\\d{14}$";
301
303
  readonly refresh: {
302
304
  readonly minMinutes: 30;
303
305
  };
@@ -330,6 +332,9 @@ export declare const CARRIER_CATALOG: {
330
332
  }, {
331
333
  readonly pattern: "^(?=.{13}$|.{15}$)3S[A-Z]{1,3}\\d+$";
332
334
  readonly confidence: "low";
335
+ }, {
336
+ readonly pattern: "^1810\\d{14}$";
337
+ readonly confidence: "low";
333
338
  }];
334
339
  };
335
340
  readonly postlogistics: {
@@ -17803,6 +17808,9 @@ export declare const CARRIER_CATALOG: {
17803
17808
  }, {
17804
17809
  readonly pattern: "^PKG\\d{5}(?:0[1-9]|1[0-2])(?:0[1-9]|[12]\\d|3[01])ES\\d{13}[A-Z]$";
17805
17810
  readonly confidence: "low";
17811
+ }, {
17812
+ readonly pattern: "^WT\\d{16}$";
17813
+ readonly confidence: "low";
17806
17814
  }];
17807
17815
  };
17808
17816
  readonly "quicksilver-sa": {
@@ -19499,7 +19507,7 @@ export declare const CARRIER_CATALOG: {
19499
19507
  readonly params: readonly ["tradeNo"];
19500
19508
  }];
19501
19509
  readonly detectionRules: readonly [{
19502
- readonly pattern: "^(?:AE|EG|GH|KE|KZ|MA|MU|MV|NG|PK|RE|RW|SA|TR|UG|ZA|ZM)\\d{12}T?$";
19510
+ readonly pattern: "^(?:AE|EG|GH|IE|KE|KZ|MA|MU|MV|NG|PK|RE|RW|SA|TR|UG|ZA|ZM)\\d{12}T?$";
19503
19511
  readonly confidence: "low";
19504
19512
  }, {
19505
19513
  readonly pattern: "^(?:AE|EG|GH|KE|KZ|MA|MU|MV|NG|PK|RE|RW|SA|TR|UG|ZA|ZM)\\d{9}[ER]$";
@@ -428,6 +428,8 @@ export const CARRIER_CATALOG = {
428
428
  "autoComplete": "postal-code"
429
429
  }
430
430
  ],
431
+ "recognitionRank": 524,
432
+ "recognitionPattern": "^1810\\d{14}$",
431
433
  "refresh": {
432
434
  "minMinutes": 30
433
435
  },
@@ -477,6 +479,10 @@ export const CARRIER_CATALOG = {
477
479
  {
478
480
  "pattern": "^(?=.{13}$|.{15}$)3S[A-Z]{1,3}\\d+$",
479
481
  "confidence": "low"
482
+ },
483
+ {
484
+ "pattern": "^1810\\d{14}$",
485
+ "confidence": "low"
480
486
  }
481
487
  ]
482
488
  },
@@ -27786,6 +27792,10 @@ export const CARRIER_CATALOG = {
27786
27792
  {
27787
27793
  "pattern": "^PKG\\d{5}(?:0[1-9]|1[0-2])(?:0[1-9]|[12]\\d|3[01])ES\\d{13}[A-Z]$",
27788
27794
  "confidence": "low"
27795
+ },
27796
+ {
27797
+ "pattern": "^WT\\d{16}$",
27798
+ "confidence": "low"
27789
27799
  }
27790
27800
  ]
27791
27801
  },
@@ -30509,7 +30519,7 @@ export const CARRIER_CATALOG = {
30509
30519
  ],
30510
30520
  "detectionRules": [
30511
30521
  {
30512
- "pattern": "^(?:AE|EG|GH|KE|KZ|MA|MU|MV|NG|PK|RE|RW|SA|TR|UG|ZA|ZM)\\d{12}T?$",
30522
+ "pattern": "^(?:AE|EG|GH|IE|KE|KZ|MA|MU|MV|NG|PK|RE|RW|SA|TR|UG|ZA|ZM)\\d{12}T?$",
30513
30523
  "confidence": "low"
30514
30524
  },
30515
30525
  {
@@ -36392,7 +36402,7 @@ export const DETECTION_RULE_IDS = {
36392
36402
  "aliexpress": ["aliexpress-1", "aliexpress-cnfr", "aliexpress-2", "aliexpress-maersk", "aliexpress-lp-reference", "aliexpress-ap-reference", "aliexpress-cnbr", "aliexpress-cnmex", "aliexpress-cnusup", "aliexpress-cacainiao", "aliexpress-rl", "aliexpress-jncn", "aliexpress-gfus", "aliexpress-ecsc-aaro", "aliexpress-pa", "aliexpress-f", "aliexpress-9c-i", "aliexpress-9c-j", "aliexpress-rtz", "aliexpress-fmp", "aliexpress-sda-waybill", "aliexpress-ty", "aliexpress-mi", "aliexpress-xx"],
36393
36403
  "sunyou": ["sunyou-1", "sunyou-2", "sunyou-3"],
36394
36404
  "hermes": ["hermes-delivery-note"],
36395
- "spring-gds": ["spring-gds-1", "spring-gds-2", "spring-gds-3"],
36405
+ "spring-gds": ["spring-gds-1", "spring-gds-2", "spring-gds-3", "spring-gds-1810"],
36396
36406
  "postlogistics": ["postlogistics-dashed-reference", "postlogistics-compact-reference"],
36397
36407
  "dachser": [],
36398
36408
  "dhl": ["dhl-1", "dhl-14", "dhl-16", "dhl-15", "dhl-9", "dhl-8", "dhl-10", "dhl-3", "dhl-13", "dhl-12", "dhl-7"],
@@ -37050,7 +37060,7 @@ export const DETECTION_RULE_IDS = {
37050
37060
  "pushpak-courier": [],
37051
37061
  "quality-post": [],
37052
37062
  "quantium-solutions": [],
37053
- "quick-rabbit": ["quick-rabbit-1", "quick-rabbit-2"],
37063
+ "quick-rabbit": ["quick-rabbit-1", "quick-rabbit-2", "quick-rabbit-3"],
37054
37064
  "quicksilver-sa": ["quicksilver-sa-1"],
37055
37065
  "quiqup": [],
37056
37066
  "qwintry": ["qwintry-1"],
@@ -404,6 +404,7 @@ export const CARRIER_RECOGNITION_RANKS = {
404
404
  "speedaf": 989,
405
405
  "speedex": 938,
406
406
  "speedy": 280,
407
+ "spring-gds": 524,
407
408
  "spx-br": 982,
408
409
  "st-courier": 753,
409
410
  "stallion-express": 105,
@@ -560,13 +560,18 @@ const LOCAL_WALL_TIME = /^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}(?::\d{2}(?:\.\d+)?)?$/;
560
560
  // A flight written before it leaves is still to come: no scan, as the lines' own trackers drop it.
561
561
  // 17FEIA's estimated departure, and the flight DHLink, Intel-Valley and Mayi Yinfu book.
562
562
  const flightToCome = (label) => FLIGHT_ESTIMATE.test(label) || DHLINK_FLIGHT.test(label) || intelValleyFlight(label) || MAYIYINFU_FLIGHT.test(label);
563
+ // A carrier's schedule, as 17TRACK relays it beside the milestones: an ocean line's estimated vessel departure and
564
+ // arrival, each again once updated, and its cargo cut-off, and a flight's ETD or ETA. Each is dated when it is due,
565
+ // often weeks ahead, so it is no scan.
566
+ const SCHEDULE = /^(?:estimated vessel (?:departure|arrival)|cfs\/cy cut-off date)(?: \(last updated\))?$|^flight et[ad]\b/i;
563
567
  // A time or date in brackets with no words, as 17TRACK relays a Juxi Express row between the flight
564
- // being arranged at the airport and the departure: it says nothing happened, so it is no scan.
565
- const BARE_TIME = /^[((]\s*\d{1,2}\s*[::]\s*\d{1,2}\s*[))]$/;
568
+ // being arranged at the airport and the departure, and ParcelsApp one dated by month and day ("(10.20)")
569
+ // between its departure and arrival: it says nothing happened, so it is no scan.
570
+ const BARE_TIME = /^[((]\s*\d{1,2}\s*[::..]\s*\d{1,2}\s*[))]$/;
566
571
  function describe(description, stage) {
567
572
  // A copy of SunYou's departure drops the last-mile number, as SunYou's own result does.
568
573
  const label = sunYouWording(relayedNotice(text(description)).replace(CLEARANCE_STATUS, ''));
569
- if (!label || isNotice(label) || flightToCome(label) || BARE_TIME.test(label))
574
+ if (!label || isNotice(label) || flightToCome(label) || SCHEDULE.test(label) || BARE_TIME.test(label))
570
575
  return null;
571
576
  const declared = typeof stage === 'string' && Object.hasOwn(STAGES, stage) ? STAGES[stage] : undefined;
572
577
  // Established source semantics (e.g. handoff/negation) remain first. A real
@@ -2,7 +2,7 @@
2
2
  "openapi": "3.1.0",
3
3
  "info": {
4
4
  "title": "Universal Parcel Scraper",
5
- "version": "0.809.2-main.4367"
5
+ "version": "0.811.0-main.4377"
6
6
  },
7
7
  "paths": {
8
8
  "/health": {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "universal-parcel-scraper",
3
- "version": "0.809.2-main.4367",
3
+ "version": "0.811.0-main.4377",
4
4
  "description": "Self-hosted parcel tracking: carrier detection, dedicated scrapers and optional universal providers.",
5
5
  "type": "module",
6
6
  "license": "Apache-2.0",