universal-parcel-scraper 0.55.0-main.708 → 0.56.0-main.720

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.
@@ -23,14 +23,17 @@ const CATALOG_NAMES = new Set([
23
23
  // Postal lookup candidates, not proof of which operator delivers a shipment.
24
24
  // Only operators whose dedicated adapter looks up mail from abroad by its S10
25
25
  // number are useful here: India Post's, Pos Malaysia's, CTT's and Poste
26
- // Italiane's take only numbers of their own. Poczta Polska and Ukrposhta give
27
- // wall clocks without an offset, so a host cannot tell their scans follow the
28
- // origin's. The host also checks adapter availability and required inputs
29
- // before making a request.
26
+ // Italiane's take only numbers of their own. Poczta Polska dates scans at its
27
+ // delivery office, and other inward scans when they name a Polish office; those
28
+ // relayed from the origin keep its wall clock. Ukrposhta now dates its scans in
29
+ // Ukraine, but its status API can miss mail from abroad, and its portal then
30
+ // needs a browser session for every lookup. The host also checks adapter
31
+ // availability and required inputs before making a request.
30
32
  const NATIONAL_POSTS = new Map([
31
33
  ['AU', 'australia-post'], ['CA', 'canada-post'], ['CH', 'swiss-post'], ['DE', 'dhl'],
32
34
  ['ES', 'correos-spain'], ['FI', 'posti'], ['FR', 'la-poste'], ['GB', 'royal-mail'],
33
- ['JP', 'japan-post'], ['NL', 'spring-gds'], ['SE', 'postnord'], ['US', 'usps'],
35
+ ['JP', 'japan-post'], ['NL', 'spring-gds'], ['PL', 'poczta-polska'], ['SE', 'postnord'],
36
+ ['US', 'usps'],
34
37
  ]);
35
38
  const englishCountries = new Intl.DisplayNames(['en'], { type: 'region' });
36
39
  // Deprecated codes carry their successor's name, so fold them into it ("FX" is France).
@@ -44,12 +44,31 @@ export function deliveryForecastRemainder(description) {
44
44
  const CARRIER_STEP = String.raw `(?:dispatched|despatched|shipped|sent|received|processed|handed (?:over|in)|posted)\b`;
45
45
  /** A handover to a carrier or courier, not to the recipient's side or to customs. */
46
46
  const HANDED_TO_CARRIER = String.raw `handed (?:over )?to (?!(?:the |a |an |your )?(?:recipient|addressee|consignee|customer|receiver|neighbou?r|customs|you|person)\b)`;
47
+ /** A carrier by its brand, as handovers to one are worded. */
48
+ const CARRIER_BRAND = String.raw `(?:gls|dpd|dhl|ups|fedex|tnt|hermes|colissimo|chronopost|brt|sda|inpost)\b`;
49
+ /** A place a carrier delivers to, worded after the brand or noun of its network: "DHL Packstation". */
50
+ const CARRIER_PLACE = String.raw `(?:packstation|paketstation|paketshop|parcelshop|shop|filiale|access point|pick ?up|locker|consigne|relais|restante|fermopoint|point|punto|box|station)\b`;
51
+ /** A carrier named on its own, not one of its places. */
52
+ const NOT_A_PLACE = String.raw `(?! ${CARRIER_PLACE})`;
53
+ /**
54
+ * The same handover negated in French ("n'a pas encore été remis à GLS"),
55
+ * German ("wurde noch nicht an GLS übergeben", or a heading such as "Paket
56
+ * noch nicht an DPD übergeben") and Italian ("non è ancora stato affidato a
57
+ * GLS"): one that has not happened, to a carrier or an operator, not one that
58
+ * cannot or will not happen, nor one to the carrier's shop, locker or pickup
59
+ * point.
60
+ */
61
+ const NOT_HANDED_TO_CARRIER = [
62
+ String.raw `(?:\bn'(?:a|ont)(?: toujours)? (?:pas|jamais)(?: encore)? ete|\bpas encore) (?:remis|confie)e?s? (?:a|au|aux) (?:(?:la|le|les) |l')?(?:(?:transporteur|livreur|coursier|messagerie|operateur|prestataire)s?|poste|${CARRIER_BRAND})\b${NOT_A_PLACE}`,
63
+ String.raw `(?:\b(?:wurde|wurden|ist|sind|war|waren)\b(?: [\w'-]+){0,4}? |(?:^|[.;:] )(?:(?:das|die|der|ihr|ihre) )?(?:[\w-]+ )?(?:noch )?)nicht an (?:(?:den|die|das|dem|der|unseren|unsere|unserem) )?(?:[\w-]+ )?(?:zusteller|paketzusteller|paketdienst|kurier|kurierdienst|versanddienst|spediteur|post|${CARRIER_BRAND}) ubergeben\b(?! werden)`,
64
+ String.raw `\bnon (?:(?:e|sono|ancora|stat[oaie]|mai) )*affidat[oaie] (?:(?:a|ad|al|allo|alla|ai|agli|alle) |all')(?:corrier[ei]|vettor[ei]|trasportator[ei]|spedizionier[ei]|operatore|posta|poste|${CARRIER_BRAND})\b${NOT_A_PLACE}`,
65
+ ].join('|');
47
66
  /**
48
67
  * A step the carrier has not taken yet ("not yet received", "not dispatched
49
68
  * yet") or a handover that has not happened ("has not been handed over to
50
69
  * GLS"), from the negation to the end of its sentence.
51
70
  */
52
- const NOT_YET = new RegExp(String.raw `(?:\bnot (?:yet (?:been )?${CARRIER_STEP}|(?:been )?${CARRIER_STEP}(?: \w+){0,3}? yet\b)|(?:\bnot|n't)(?: been)? ${HANDED_TO_CARRIER})${SENTENCE}*`, 'g');
71
+ const NOT_YET = new RegExp(String.raw `(?:\bnot (?:yet (?:been )?${CARRIER_STEP}|(?:been )?${CARRIER_STEP}(?: \w+){0,3}? yet\b)|(?:\bnot|n't)(?: been)? ${HANDED_TO_CARRIER}|(?:\bnot|n't) yet(?: been)? ${HANDED_TO_CARRIER}(?!(?:the |a |an |your )?(?:[\w-]+ )?${CARRIER_PLACE})|${NOT_HANDED_TO_CARRIER})${SENTENCE}*`, 'g');
53
72
  /** A handover the carrier made, not a pickup order passed on or the sender's own hand-in. */
54
73
  const HANDED_TO = String.raw `(?<!\b(?:(?:pick ?up|collection) (?:order|request)|sender|shipper|seller|merchant|consignor)(?: has| have)?(?: been)? )\bhanded (?:over )?to `;
55
74
  /**
@@ -59,6 +78,8 @@ const HANDED_TO = String.raw `(?<!\b(?:(?:pick ?up|collection) (?:order|request)
59
78
  const COURIER = String.raw `(?:(?:the|a|an|our|your) )?(?:delivery )?couriers?\b(?! (?:compan|service|partner|network|guy\b))`;
60
79
  const HANDED_TO_COURIER = new RegExp(`${HANDED_TO}${COURIER}`);
61
80
  const HANDED_TO_NETWORK = new RegExp(String.raw `${HANDED_TO}(?!${COURIER})(?:the |a |an |our |your )?(?:[\w-]+ ){0,2}?(?:courier|carrier)s?\b`);
81
+ /** Customs or clearance named in any language. */
82
+ const CUSTOMS = /customs|clearance|douan|formalites (?:d')?(?:import|export)|zoll|dogan|\b(?:des)?aduan[ae]|alfandeg|\bceln|government agency|autorite gouvernementale|staatliche behorde|autorita governativa/;
62
83
  /** The side of customs a scan may name: "import", "export", "import/export". */
63
84
  const CUSTOMS_SIDE = String.raw `(?:(?:import|export)(?:\/(?:import|export))? |local |destination |origin )?`;
64
85
  /**
@@ -167,7 +188,7 @@ export function trackingLanguageStage(description) {
167
188
  if (/^(?:a )?(?:new|next|another|further) (?:delivery )?attempt\b/.test(text)
168
189
  && !/\b(?:not|unable|fail(?:ed|ure)?|unsuccessful|missed|absent|closed|refused|nobody|no one)\b|n't\b/.test(text))
169
190
  return 'in_transit';
170
- if (/not (?:yet )?delivered|\bundelivered\b|could not.*deliver|\bcan(?: ?not|'t) be delivered\b|unable to deliver|delivery (?:attempt|failed)|non livre|n'(?:a|avons) (?:pas )?pu.*(?:remis|remettre)|n'a pas pu etre (?:distribue|livre)|\bne (?:peut|pourra|pourrait|pouvait) (?:pas )?etre (?:distribue|livre)|livraison (?:impossible|echouee)|\bechec (?:de (?:la )?)?livraison|tentative de livraison|nicht zugestellt|nicht zugestellt werden|zustellung.*(?:fehlgeschlagen|nicht moglich)|zustellversuch|non consegnat[oa]|non e stato possibile consegnare|consegna (?:fallita|non riuscita)|tentativo di consegna/.test(text))
191
+ if (/not (?:yet )?delivered|\bundelivered\b|could not.*deliver|\bcan(?: ?not|'t) be delivered\b|unable to deliver|delivery (?:attempt|failed)|non livre|n'(?:a|avons) (?:pas )?pu.*(?:remis|remettre)|n'a pas pu etre (?:distribue|livre)|\bne (?:peut|pourra|pourrait|pouvait) (?:pas )?etre (?:distribue|livre)|livraison (?:impossible|echouee)|\bechec (?:de (?:la )?)?livraison|tentative de livraison|nicht zugestellt|nicht zugestellt werden|zustellung.*(?:fehlgeschlagen|nicht moglich)|zustellversuch|non consegnat[oa]|\bmancata consegna\b|non e stato possibile consegnare|consegna (?:fallita|non riuscita)|tentativo di consegna/.test(text))
171
192
  return 'failed_attempt';
172
193
  if (/\bno (?:(?:ha|han|hemos|se|le|lo|la|fue|sido|ser|es|era|pudo|puede|podido|posible|todavia|aun) )*(?:entregad[oa]s?|entregar(?:lo|la|le|se)?|repartid[oa]s?|realizar la entrega|efectuar la entrega)\b|\bsin entregar\b|\b(?:entrega|reparto) (?:fallid[oa]|imposible|no (?:(?:ha|han|se|fue|sido|ser|pudo|puede|podido) )*(?:realizad[oa]|efectuad[oa]|completad[oa]|posible|conseguid[oa]))\b|\bimposible (?:entregar|realizar la entrega|efectuar la entrega)\b|\bfallo (?:en la|de) entrega\b|\bintento fallido\b|\bintento de (?:entrega|reparto)\b(?! (?:programad|previst|para (?:hoy|manana|el)|manana|hoy))|\bnao (?:(?:foi|foram|ser|sera|pode|podemos|conseguimos|conseguiu|se|possivel|e|ainda|tem sido|esta|estava) )*(?:entregues?|entregar|efetuar a entrega|efectuar a entrega|realizar a entrega)\b|\bentrega (?:falhada|sem sucesso|impossivel|nao (?:(?:foi|pode|ser|sera|tem sido) )*(?:efetuada|efectuada|realizada|conseguida|concretizada|possivel))\b|\bfalha (?:na|de) entrega\b|\btentativa (?:de entrega|sem sucesso)\b(?! (?:agendada|prevista|programada|para (?:hoje|amanha)|amanha|hoje))|\bcarteiro nao atendido\b/.test(text))
173
194
  return 'failed_attempt';
@@ -263,11 +284,16 @@ export function trackingLanguageStage(description) {
263
284
  return 'registered';
264
285
  // The carrier has not had the parcel yet: "Shipment not yet received or
265
286
  // processed". What else the scan reports still counts: "Arrived at hub; not
266
- // yet processed" is in transit, and a clearance delay stays with customs.
287
+ // yet processed" is in transit, and a clearance delay stays with customs,
288
+ // even worded within the step's own sentence ("Not handed over to the
289
+ // carrier: awaiting customs clearance"), as a release there moves it on
290
+ // unless it is still to come ("clearance not completed").
267
291
  if (!/\b(?:at|in|by) (?:the )?(?:destination|delivery|recipient|consignee|addressee|customer|customs|office of exchange)\b/.test(text)) {
268
292
  const rest = text.replace(NOT_YET, ' ');
269
- if (rest !== text)
270
- return trackingLanguageStage(rest.replace(/^[\s,;:.!?]+|[\s,;:]+$/g, '')) ?? 'registered';
293
+ if (rest !== text) {
294
+ return trackingLanguageStage(rest.replace(/^[\s,;:.!?]+|[\s,;:]+$/g, ''))
295
+ ?? (CUSTOMS.test(text) ? (!CUSTOMS_PENDING.test(text) && CUSTOMS_RELEASED.test(text) ? 'in_transit' : 'customs') : 'registered');
296
+ }
271
297
  }
272
298
  if (/^(?:reported|recorded|announced|item created|enregistre|annonce|erfasst|angekundigt|registrato|annunciato)$/.test(text))
273
299
  return 'registered';
@@ -280,7 +306,7 @@ export function trackingLanguageStage(description) {
280
306
  return 'customs';
281
307
  if (CUSTOMS_RELEASED.test(text))
282
308
  return 'in_transit';
283
- if (/customs|clearance|douan|formalites (?:d')?(?:import|export)|zoll|dogan|\b(?:des)?aduan[ae]|alfandeg|\bceln|government agency|autorite gouvernementale|staatliche behorde|autorita governativa/.test(text))
309
+ if (CUSTOMS.test(text))
284
310
  return 'customs';
285
311
  if (/out for (?:physical )?delivery|\bout with (?:the |a |our |your )?(?:delivery )?(?:courier|driver)s?\b(?! for (?:pick ?up|collection|return))|being delivered|in delivery|(?:loading|loaded).*delivery vehicle|on (?:\w+ )?vehicle for delivery|(?:courier|driver|delivery champion) has (?:the|your) (?:shipment|parcel|package|item)|en cours de livraison|en livraison|de la livraison de (?:son|votre) colis ce jour|charg(?:e|ement).*vehicule de livraison|in zustellung|zustellfahrzeug.*(?:geladen|verladen)|(?:beladen|verladung).*zustellfahrzeug|in consegna|caric(?:at|amento).*veicolo.*consegna/.test(text))
286
312
  return 'out_for_delivery';
@@ -4846,7 +4846,7 @@
4846
4846
  "domains": [
4847
4847
  "tracking.dpd.de"
4848
4848
  ],
4849
- "path": "^/status/[a-z]{2}_[A-Z]{2}/parcel/(\\d{14})/?$"
4849
+ "path": "^/status/[a-z]{2}_[A-Z]{2}/parcel/(\\d{14}[0-9A-Z]?)/?$"
4850
4850
  },
4851
4851
  {
4852
4852
  "domains": [
@@ -4909,6 +4909,12 @@
4909
4909
  "pattern": "^13\\d{12}$",
4910
4910
  "confidence": "low",
4911
4911
  "preferred": true
4912
+ },
4913
+ {
4914
+ "pattern": "^13\\d{12}[0-9A-Z]$",
4915
+ "confidence": "low",
4916
+ "checksum": "dpd",
4917
+ "preferred": true
4912
4918
  }
4913
4919
  ]
4914
4920
  },
@@ -4999,6 +5005,41 @@
4999
5005
  }
5000
5006
  ]
5001
5007
  },
5008
+ "emile": {
5009
+ "displayName": "Emile",
5010
+ "color": "#e42920",
5011
+ "aliases": [
5012
+ "Emile Express"
5013
+ ],
5014
+ "countries": [
5015
+ "CA"
5016
+ ],
5017
+ "selectable": true,
5018
+ "timezone": "UTC",
5019
+ "tracking": {
5020
+ "mode": "link-only",
5021
+ "adapter": null
5022
+ },
5023
+ "canaryUrl": "https://www.emileps.com/",
5024
+ "trackingUrlTemplate": "https://www.emileps.com/tracking?tracking={trackingNumber}",
5025
+ "trackingSearchUrl": "https://www.emileps.com/tracking",
5026
+ "linkRules": [
5027
+ {
5028
+ "domains": [
5029
+ "emileps.com"
5030
+ ],
5031
+ "params": [
5032
+ "tracking"
5033
+ ]
5034
+ }
5035
+ ],
5036
+ "detectionRules": [
5037
+ {
5038
+ "pattern": "^EM\\d{12}CA$",
5039
+ "confidence": "low"
5040
+ }
5041
+ ]
5042
+ },
5002
5043
  "evri-uk": {
5003
5044
  "displayName": "Evri UK",
5004
5045
  "color": "#00014d",
@@ -3321,7 +3321,7 @@ export declare const CARRIER_CATALOG: {
3321
3321
  readonly trackingSearchUrl: "https://www.dpd.com/de/en/empfangen/sendungsverfolgung-und-live-tracking/";
3322
3322
  readonly linkRules: readonly [{
3323
3323
  readonly domains: readonly ["tracking.dpd.de"];
3324
- readonly path: "^/status/[a-z]{2}_[A-Z]{2}/parcel/(\\d{14})/?$";
3324
+ readonly path: "^/status/[a-z]{2}_[A-Z]{2}/parcel/(\\d{14}[0-9A-Z]?)/?$";
3325
3325
  }, {
3326
3326
  readonly domains: readonly ["my.dpd.de"];
3327
3327
  readonly params: readonly ["parcelno"];
@@ -3362,6 +3362,11 @@ export declare const CARRIER_CATALOG: {
3362
3362
  readonly pattern: "^13\\d{12}$";
3363
3363
  readonly confidence: "low";
3364
3364
  readonly preferred: true;
3365
+ }, {
3366
+ readonly pattern: "^13\\d{12}[0-9A-Z]$";
3367
+ readonly confidence: "low";
3368
+ readonly checksum: "dpd";
3369
+ readonly preferred: true;
3365
3370
  }];
3366
3371
  };
3367
3372
  readonly "dpd-uk": {
@@ -3424,6 +3429,29 @@ export declare const CARRIER_CATALOG: {
3424
3429
  readonly confidence: "high";
3425
3430
  }];
3426
3431
  };
3432
+ readonly emile: {
3433
+ readonly displayName: "Emile";
3434
+ readonly color: "#e42920";
3435
+ readonly aliases: readonly ["Emile Express"];
3436
+ readonly countries: readonly ["CA"];
3437
+ readonly selectable: true;
3438
+ readonly timezone: "UTC";
3439
+ readonly tracking: {
3440
+ readonly mode: "link-only";
3441
+ readonly adapter: null;
3442
+ };
3443
+ readonly canaryUrl: "https://www.emileps.com/";
3444
+ readonly trackingUrlTemplate: "https://www.emileps.com/tracking?tracking={trackingNumber}";
3445
+ readonly trackingSearchUrl: "https://www.emileps.com/tracking";
3446
+ readonly linkRules: readonly [{
3447
+ readonly domains: readonly ["emileps.com"];
3448
+ readonly params: readonly ["tracking"];
3449
+ }];
3450
+ readonly detectionRules: readonly [{
3451
+ readonly pattern: "^EM\\d{12}CA$";
3452
+ readonly confidence: "low";
3453
+ }];
3454
+ };
3427
3455
  readonly "evri-uk": {
3428
3456
  readonly displayName: "Evri UK";
3429
3457
  readonly color: "#00014d";
@@ -3684,7 +3712,7 @@ export declare const CARRIER_CATALOG: {
3684
3712
  }];
3685
3713
  };
3686
3714
  };
3687
- export declare const CARRIER_IDS: readonly ["swiss-post", "swiss-post-cargo", "quickpac", "planzer", "aliexpress", "sunyou", "hermes", "spring-gds", "postlogistics", "dachser", "dhl", "dhl-ecommerce", "ups", "amazon-logistics", "amazon-shipping", "fedex", "gls-ch", "dpd", "dpd-fr", "mondial-relay", "relais-colis", "la-poste", "chronopost", "gls-fr", "colis-prive", "geodis", "colisweb", "c-chez-vous", "heppner", "ciblex", "paack", "asendia", "shipup", "india-post", "hermes-de", "gls-de", "delivengo", "intl-post", "unknown", "royal-mail", "parcelforce", "evri", "inpost", "an-post", "bpost", "austrian-post", "postnord", "posti", "correos-express", "seur", "mrw", "nacex", "ctt", "ctt-express", "poste-italiane", "brt", "ecoscooting", "tipsa", "ukrposhta", "usps", "canada-post", "purolator", "canpar", "ontrac", "speedx", "uniuni", "landmark-global", "old-dominion", "spee-dee", "gofo", "estafeta", "correios-br", "correos-chile", "yunexpress", "four-px", "blue-dart", "delhivery", "nz-post", "singapore-post", "japan-post", "sf-express", "sto", "yunda", "yto", "zto", "jd-logistics", "yamato", "korea-post", "thailand-post", "dtdc", "australia-post", "hongkong-post", "pos-malaysia", "ninja-van", "china-post", "packeta", "poczta-polska", "bring-posten", "aramex", "tnt", "correos-spain", "yanwen", "the-courier-guy", "j-and-t", "ems", "cne", "dhl-ecommerce-es", "dhl-ecommerce-nl", "dhl-ecommerce-pl", "dhl-ecommerce-uk", "dhl-express", "dpd-de", "dpd-pl", "dpd-uk", "ekart", "evri-uk", "intelcom", "j-and-t-cargo", "lbc-express", "nova-poshta", "omgo", "sagawa", "speedpak", "spx-ph", "xpressbees"];
3715
+ export declare const CARRIER_IDS: readonly ["swiss-post", "swiss-post-cargo", "quickpac", "planzer", "aliexpress", "sunyou", "hermes", "spring-gds", "postlogistics", "dachser", "dhl", "dhl-ecommerce", "ups", "amazon-logistics", "amazon-shipping", "fedex", "gls-ch", "dpd", "dpd-fr", "mondial-relay", "relais-colis", "la-poste", "chronopost", "gls-fr", "colis-prive", "geodis", "colisweb", "c-chez-vous", "heppner", "ciblex", "paack", "asendia", "shipup", "india-post", "hermes-de", "gls-de", "delivengo", "intl-post", "unknown", "royal-mail", "parcelforce", "evri", "inpost", "an-post", "bpost", "austrian-post", "postnord", "posti", "correos-express", "seur", "mrw", "nacex", "ctt", "ctt-express", "poste-italiane", "brt", "ecoscooting", "tipsa", "ukrposhta", "usps", "canada-post", "purolator", "canpar", "ontrac", "speedx", "uniuni", "landmark-global", "old-dominion", "spee-dee", "gofo", "estafeta", "correios-br", "correos-chile", "yunexpress", "four-px", "blue-dart", "delhivery", "nz-post", "singapore-post", "japan-post", "sf-express", "sto", "yunda", "yto", "zto", "jd-logistics", "yamato", "korea-post", "thailand-post", "dtdc", "australia-post", "hongkong-post", "pos-malaysia", "ninja-van", "china-post", "packeta", "poczta-polska", "bring-posten", "aramex", "tnt", "correos-spain", "yanwen", "the-courier-guy", "j-and-t", "ems", "cne", "dhl-ecommerce-es", "dhl-ecommerce-nl", "dhl-ecommerce-pl", "dhl-ecommerce-uk", "dhl-express", "dpd-de", "dpd-pl", "dpd-uk", "ekart", "emile", "evri-uk", "intelcom", "j-and-t-cargo", "lbc-express", "nova-poshta", "omgo", "sagawa", "speedpak", "spx-ph", "xpressbees"];
3688
3716
  export type CarrierId = (typeof CARRIER_IDS)[number];
3689
3717
  /** Each carrier's detection rule ids, in the order of its `detectionRules`. */
3690
3718
  export declare const DETECTION_RULE_IDS: Readonly<Record<CarrierId, readonly string[]>>;
@@ -4847,7 +4847,7 @@ export const CARRIER_CATALOG = {
4847
4847
  "domains": [
4848
4848
  "tracking.dpd.de"
4849
4849
  ],
4850
- "path": "^/status/[a-z]{2}_[A-Z]{2}/parcel/(\\d{14})/?$"
4850
+ "path": "^/status/[a-z]{2}_[A-Z]{2}/parcel/(\\d{14}[0-9A-Z]?)/?$"
4851
4851
  },
4852
4852
  {
4853
4853
  "domains": [
@@ -4910,6 +4910,12 @@ export const CARRIER_CATALOG = {
4910
4910
  "pattern": "^13\\d{12}$",
4911
4911
  "confidence": "low",
4912
4912
  "preferred": true
4913
+ },
4914
+ {
4915
+ "pattern": "^13\\d{12}[0-9A-Z]$",
4916
+ "confidence": "low",
4917
+ "checksum": "dpd",
4918
+ "preferred": true
4913
4919
  }
4914
4920
  ]
4915
4921
  },
@@ -5000,6 +5006,41 @@ export const CARRIER_CATALOG = {
5000
5006
  }
5001
5007
  ]
5002
5008
  },
5009
+ "emile": {
5010
+ "displayName": "Emile",
5011
+ "color": "#e42920",
5012
+ "aliases": [
5013
+ "Emile Express"
5014
+ ],
5015
+ "countries": [
5016
+ "CA"
5017
+ ],
5018
+ "selectable": true,
5019
+ "timezone": "UTC",
5020
+ "tracking": {
5021
+ "mode": "link-only",
5022
+ "adapter": null
5023
+ },
5024
+ "canaryUrl": "https://www.emileps.com/",
5025
+ "trackingUrlTemplate": "https://www.emileps.com/tracking?tracking={trackingNumber}",
5026
+ "trackingSearchUrl": "https://www.emileps.com/tracking",
5027
+ "linkRules": [
5028
+ {
5029
+ "domains": [
5030
+ "emileps.com"
5031
+ ],
5032
+ "params": [
5033
+ "tracking"
5034
+ ]
5035
+ }
5036
+ ],
5037
+ "detectionRules": [
5038
+ {
5039
+ "pattern": "^EM\\d{12}CA$",
5040
+ "confidence": "low"
5041
+ }
5042
+ ]
5043
+ },
5003
5044
  "evri-uk": {
5004
5045
  "displayName": "Evri UK",
5005
5046
  "color": "#00014d",
@@ -5523,6 +5564,7 @@ export const CARRIER_IDS = [
5523
5564
  "dpd-pl",
5524
5565
  "dpd-uk",
5525
5566
  "ekart",
5567
+ "emile",
5526
5568
  "evri-uk",
5527
5569
  "intelcom",
5528
5570
  "j-and-t-cargo",
@@ -5648,9 +5690,10 @@ export const DETECTION_RULE_IDS = {
5648
5690
  "dhl-ecommerce-uk": ["dhl-ecommerce-uk-2", "dhl-ecommerce-uk-1"],
5649
5691
  "dhl-express": ["dhl-express-waybill"],
5650
5692
  "dpd-de": ["dpd-de-1", "dpd-de-2"],
5651
- "dpd-pl": ["dpd-pl-1", "dpd-pl-2"],
5693
+ "dpd-pl": ["dpd-pl-1", "dpd-pl-2", "dpd-pl-3"],
5652
5694
  "dpd-uk": ["dpd-uk-3", "dpd-uk-4", "dpd-uk-1", "dpd-uk-2"],
5653
5695
  "ekart": ["ekart-ecommerce"],
5696
+ "emile": ["emile-1"],
5654
5697
  "evri-uk": ["evri-uk-1", "evri-uk-2", "evri-uk-3"],
5655
5698
  "intelcom": ["intelcom-1", "intelcom-2", "intelcom-3"],
5656
5699
  "j-and-t-cargo": ["j-and-t-cargo-1"],
@@ -278,6 +278,7 @@ export const REGISTRY = {
278
278
  "dtdc": "dtdc",
279
279
  "ecoscooting": "ecoscooting",
280
280
  "ekart": "ekart",
281
+ "emile": null,
281
282
  "ems": "ems",
282
283
  "estafeta": "estafeta",
283
284
  "evri": "evri",
@@ -2,7 +2,7 @@
2
2
  "openapi": "3.1.0",
3
3
  "info": {
4
4
  "title": "Universal Parcel Scraper",
5
- "version": "0.55.0"
5
+ "version": "0.56.0"
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.55.0-main.708",
3
+ "version": "0.56.0-main.720",
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",