universal-parcel-scraper 0.158.0-main.1233 → 0.159.0-main.1237

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.
Files changed (40) hide show
  1. package/README.md +2 -2
  2. package/data/catalog.json +34 -6
  3. package/data/coverage-summary.json +1 -1
  4. package/data/detection-golden.json +132 -0
  5. package/dist/browser/scraper.js +27 -7
  6. package/dist/carriers/gati/adapter.d.ts +20 -0
  7. package/dist/carriers/gati/adapter.js +105 -0
  8. package/dist/carriers/gati/carrier.json +49 -7
  9. package/dist/carriers/gati/numbers.json +67 -7
  10. package/dist/carriers/gati/parser.d.ts +13 -0
  11. package/dist/carriers/gati/parser.js +173 -0
  12. package/dist/carriers/gati/status.d.ts +7 -0
  13. package/dist/carriers/gati/status.js +37 -0
  14. package/dist/carriers/gati/statuses.json +12 -1
  15. package/dist/carriers/shadowfax/adapter.d.ts +19 -0
  16. package/dist/carriers/shadowfax/adapter.js +93 -0
  17. package/dist/carriers/shadowfax/carrier.json +55 -7
  18. package/dist/carriers/shadowfax/numbers.json +144 -8
  19. package/dist/carriers/shadowfax/parser.d.ts +28 -0
  20. package/dist/carriers/shadowfax/parser.js +206 -0
  21. package/dist/carriers/shadowfax/status.d.ts +12 -0
  22. package/dist/carriers/shadowfax/status.js +77 -0
  23. package/dist/carriers/shadowfax/statuses.json +16 -1
  24. package/dist/carriers/total-express/adapter.d.ts +15 -0
  25. package/dist/carriers/total-express/adapter.js +85 -0
  26. package/dist/carriers/total-express/carrier.json +81 -10
  27. package/dist/carriers/total-express/numbers.json +115 -1
  28. package/dist/carriers/total-express/parser.d.ts +24 -0
  29. package/dist/carriers/total-express/parser.js +195 -0
  30. package/dist/carriers/total-express/status.d.ts +7 -0
  31. package/dist/carriers/total-express/status.js +138 -0
  32. package/dist/carriers/total-express/statuses.json +101 -7
  33. package/dist/core/catalog/statusMaps.js +7 -3
  34. package/dist/data/catalog.json +34 -6
  35. package/dist/generated/catalog.d.ts +23 -6
  36. package/dist/generated/catalog.js +35 -7
  37. package/dist/generated/recognition.js +3 -0
  38. package/dist/generated/registry.js +9 -3
  39. package/dist/server/openapi.json +1 -1
  40. package/package.json +1 -1
package/README.md CHANGED
@@ -13,7 +13,7 @@ The engine behind [Peek](https://peektracker.com) ([GitHub](https://github.com/p
13
13
  [![License: Apache-2.0](https://img.shields.io/badge/core-Apache--2.0-blue.svg)](LICENSE)
14
14
 
15
15
  <!-- GENERATED:summary -->
16
- **3,500+ carriers** through **218 dedicated adapters** and **5 universal fallbacks**
16
+ **3,500+ carriers** through **221 dedicated adapters** and **5 universal fallbacks**
17
17
 
18
18
  <sub>358 catalog entries · 91 countries represented</sub>
19
19
  <!-- /GENERATED:summary -->
@@ -155,7 +155,7 @@ createTracker({ providers: ['ParcelsApp', 'Ship24', '17TRACK', 'Postal Ninja', '
155
155
  <!-- GENERATED:stages -->
156
156
  <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">
157
157
 
158
- The carrier folders record 7,642 such statuses, each filed under one stage.
158
+ The carrier folders record 7,762 such statuses, each filed under one stage.
159
159
  <!-- /GENERATED:stages -->
160
160
 
161
161
  Wording nobody recorded yet goes through a classifier that reads seven European languages.
package/data/catalog.json CHANGED
@@ -8858,7 +8858,8 @@
8858
8858
  "timezone": "Asia/Kolkata",
8859
8859
  "tracking": {
8860
8860
  "mode": "automatic",
8861
- "adapter": "universal"
8861
+ "adapter": "gati",
8862
+ "recognitionRank": 43
8862
8863
  },
8863
8864
  "canaryUrl": "https://www.allcargologistics.com/track-shipment",
8864
8865
  "trackingSearchUrl": "https://www.allcargologistics.com/track-shipment",
@@ -13037,7 +13038,8 @@
13037
13038
  "timezone": "Asia/Kolkata",
13038
13039
  "tracking": {
13039
13040
  "mode": "automatic",
13040
- "adapter": "universal"
13041
+ "adapter": "shadowfax",
13042
+ "recognitionRank": 595
13041
13043
  },
13042
13044
  "canaryUrl": "https://www.shadowfax.in/track",
13043
13045
  "trackingUrlTemplate": "https://tracker.shadowfax.in/#/awb/{trackingNumber}",
@@ -14043,11 +14045,37 @@
14043
14045
  "timezone": "America/Sao_Paulo",
14044
14046
  "tracking": {
14045
14047
  "mode": "automatic",
14046
- "adapter": "universal"
14048
+ "adapter": "total-express",
14049
+ "recognitionRank": 975,
14050
+ "localClocks": true
14047
14051
  },
14048
- "canaryUrl": "https://totalexpress.com.br/rastrear-um-produto/",
14049
- "linkRules": [],
14050
- "detectionRules": []
14052
+ "canaryUrl": "https://totalconecta.totalexpress.com.br/rastreamento",
14053
+ "trackingUrlTemplate": "https://totalconecta.totalexpress.com.br/rastreamento?codigo={trackingNumber}",
14054
+ "trackingSearchUrl": "https://totalconecta.totalexpress.com.br/rastreamento",
14055
+ "linkRules": [
14056
+ {
14057
+ "domains": [
14058
+ "totalconecta.totalexpress.com.br"
14059
+ ],
14060
+ "path": "^/rastreamento/rastreamento/encomendas/([^/?#]+)/?$"
14061
+ },
14062
+ {
14063
+ "domains": [
14064
+ "totalconecta.totalexpress.com.br"
14065
+ ],
14066
+ "pathPattern": "^/rastreamento/?$",
14067
+ "params": [
14068
+ "codigo"
14069
+ ],
14070
+ "ownNumbersOnly": true
14071
+ }
14072
+ ],
14073
+ "detectionRules": [
14074
+ {
14075
+ "pattern": "^(?:TX[A-Z]{2}|AMZB)\\d{9}TX$",
14076
+ "confidence": "high"
14077
+ }
14078
+ ]
14051
14079
  },
14052
14080
  "trackon": {
14053
14081
  "displayName": "Trackon Couriers",
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "catalog": 358,
3
- "activeAdapters": 218,
3
+ "activeAdapters": 221,
4
4
  "countries": 91,
5
5
  "referenceCarriers": 100,
6
6
  "comparison": {
@@ -10096,6 +10096,12 @@
10096
10096
  "dhl-ecommerce-pl"
10097
10097
  ]
10098
10098
  },
10099
+ {
10100
+ "input": "139815455",
10101
+ "carrier": "unknown",
10102
+ "confidence": "none",
10103
+ "candidates": []
10104
+ },
10099
10105
  {
10100
10106
  "input": "13CF4B49016730467J",
10101
10107
  "carrier": "zeleris",
@@ -23536,6 +23542,20 @@
23536
23542
  "dhl-ecommerce-pl"
23537
23543
  ]
23538
23544
  },
23545
+ {
23546
+ "input": "412933252",
23547
+ "carrier": "unknown",
23548
+ "confidence": "low",
23549
+ "candidates": [
23550
+ "tnt"
23551
+ ],
23552
+ "preferred": [
23553
+ "tnt"
23554
+ ],
23555
+ "asked": [
23556
+ "tnt"
23557
+ ]
23558
+ },
23539
23559
  {
23540
23560
  "input": "41505910017980",
23541
23561
  "carrier": "unknown",
@@ -37360,6 +37380,12 @@
37360
37380
  "brt"
37361
37381
  ]
37362
37382
  },
37383
+ {
37384
+ "input": "988397715",
37385
+ "carrier": "unknown",
37386
+ "confidence": "none",
37387
+ "candidates": []
37388
+ },
37363
37389
  {
37364
37390
  "input": "988C01701257F",
37365
37391
  "carrier": "unknown",
@@ -38894,6 +38920,14 @@
38894
38920
  "mtscn"
38895
38921
  ]
38896
38922
  },
38923
+ {
38924
+ "input": "AMZB664764467tx",
38925
+ "carrier": "total-express",
38926
+ "confidence": "high",
38927
+ "candidates": [
38928
+ "total-express"
38929
+ ]
38930
+ },
38897
38931
  {
38898
38932
  "input": "AN725955",
38899
38933
  "carrier": "unknown",
@@ -51474,6 +51508,20 @@
51474
51508
  "confidence": "low",
51475
51509
  "candidates": [
51476
51510
  "shadowfax"
51511
+ ],
51512
+ "asked": [
51513
+ "shadowfax"
51514
+ ]
51515
+ },
51516
+ {
51517
+ "input": "R1858467302TIU",
51518
+ "carrier": "unknown",
51519
+ "confidence": "low",
51520
+ "candidates": [
51521
+ "shadowfax"
51522
+ ],
51523
+ "asked": [
51524
+ "shadowfax"
51477
51525
  ]
51478
51526
  },
51479
51527
  {
@@ -53556,6 +53604,12 @@
53556
53604
  "shadowfax"
53557
53605
  ]
53558
53606
  },
53607
+ {
53608
+ "input": "SF1904798183E",
53609
+ "carrier": "unknown",
53610
+ "confidence": "none",
53611
+ "candidates": []
53612
+ },
53559
53613
  {
53560
53614
  "input": "SF211225399443FPL",
53561
53615
  "carrier": "shadowfax",
@@ -53572,6 +53626,22 @@
53572
53626
  "shadowfax"
53573
53627
  ]
53574
53628
  },
53629
+ {
53630
+ "input": "SF2917969609ARA",
53631
+ "carrier": "shadowfax",
53632
+ "confidence": "high",
53633
+ "candidates": [
53634
+ "shadowfax"
53635
+ ]
53636
+ },
53637
+ {
53638
+ "input": "SF3033213302ARA",
53639
+ "carrier": "shadowfax",
53640
+ "confidence": "high",
53641
+ "candidates": [
53642
+ "shadowfax"
53643
+ ]
53644
+ },
53575
53645
  {
53576
53646
  "input": "SF332188411FPL",
53577
53647
  "carrier": "shadowfax",
@@ -53596,6 +53666,28 @@
53596
53666
  "shadowfax"
53597
53667
  ]
53598
53668
  },
53669
+ {
53670
+ "input": "SF3667163853YWR",
53671
+ "carrier": "shadowfax",
53672
+ "confidence": "high",
53673
+ "candidates": [
53674
+ "shadowfax"
53675
+ ]
53676
+ },
53677
+ {
53678
+ "input": "SF3772148429KR",
53679
+ "carrier": "unknown",
53680
+ "confidence": "none",
53681
+ "candidates": []
53682
+ },
53683
+ {
53684
+ "input": "SF4073772682DEU",
53685
+ "carrier": "shadowfax",
53686
+ "confidence": "high",
53687
+ "candidates": [
53688
+ "shadowfax"
53689
+ ]
53690
+ },
53599
53691
  {
53600
53692
  "input": "SF6042542297687",
53601
53693
  "carrier": "sf-express",
@@ -54761,6 +54853,46 @@
54761
54853
  "tsjy"
54762
54854
  ]
54763
54855
  },
54856
+ {
54857
+ "input": "TXAQ243268174TX",
54858
+ "carrier": "total-express",
54859
+ "confidence": "high",
54860
+ "candidates": [
54861
+ "total-express"
54862
+ ]
54863
+ },
54864
+ {
54865
+ "input": "TXAQ402565477tx",
54866
+ "carrier": "total-express",
54867
+ "confidence": "high",
54868
+ "candidates": [
54869
+ "total-express"
54870
+ ]
54871
+ },
54872
+ {
54873
+ "input": "TXAQ549180149tx",
54874
+ "carrier": "total-express",
54875
+ "confidence": "high",
54876
+ "candidates": [
54877
+ "total-express"
54878
+ ]
54879
+ },
54880
+ {
54881
+ "input": "TXAQ589033943TX",
54882
+ "carrier": "total-express",
54883
+ "confidence": "high",
54884
+ "candidates": [
54885
+ "total-express"
54886
+ ]
54887
+ },
54888
+ {
54889
+ "input": "TXAS426107751tx",
54890
+ "carrier": "total-express",
54891
+ "confidence": "high",
54892
+ "candidates": [
54893
+ "total-express"
54894
+ ]
54895
+ },
54764
54896
  {
54765
54897
  "input": "TYPQYU501214190",
54766
54898
  "carrier": "unknown",
@@ -6903,7 +6903,8 @@ var Ae = {
6903
6903
  timezone: "Asia/Kolkata",
6904
6904
  tracking: {
6905
6905
  mode: "automatic",
6906
- adapter: "universal"
6906
+ adapter: "gati",
6907
+ recognitionRank: 43
6907
6908
  },
6908
6909
  canaryUrl: "https://www.allcargologistics.com/track-shipment",
6909
6910
  trackingSearchUrl: "https://www.allcargologistics.com/track-shipment",
@@ -10043,7 +10044,8 @@ var Ae = {
10043
10044
  timezone: "Asia/Kolkata",
10044
10045
  tracking: {
10045
10046
  mode: "automatic",
10046
- adapter: "universal"
10047
+ adapter: "shadowfax",
10048
+ recognitionRank: 595
10047
10049
  },
10048
10050
  canaryUrl: "https://www.shadowfax.in/track",
10049
10051
  trackingUrlTemplate: "https://tracker.shadowfax.in/#/awb/{trackingNumber}",
@@ -10762,11 +10764,26 @@ var Ae = {
10762
10764
  timezone: "America/Sao_Paulo",
10763
10765
  tracking: {
10764
10766
  mode: "automatic",
10765
- adapter: "universal"
10767
+ adapter: "total-express",
10768
+ recognitionRank: 975,
10769
+ localClocks: !0
10766
10770
  },
10767
- canaryUrl: "https://totalexpress.com.br/rastrear-um-produto/",
10768
- linkRules: [],
10769
- detectionRules: []
10771
+ canaryUrl: "https://totalconecta.totalexpress.com.br/rastreamento",
10772
+ trackingUrlTemplate: "https://totalconecta.totalexpress.com.br/rastreamento?codigo={trackingNumber}",
10773
+ trackingSearchUrl: "https://totalconecta.totalexpress.com.br/rastreamento",
10774
+ linkRules: [{
10775
+ domains: ["totalconecta.totalexpress.com.br"],
10776
+ path: "^/rastreamento/rastreamento/encomendas/([^/?#]+)/?$"
10777
+ }, {
10778
+ domains: ["totalconecta.totalexpress.com.br"],
10779
+ pathPattern: "^/rastreamento/?$",
10780
+ params: ["codigo"],
10781
+ ownNumbersOnly: !0
10782
+ }],
10783
+ detectionRules: [{
10784
+ pattern: "^(?:TX[A-Z]{2}|AMZB)\\d{9}TX$",
10785
+ confidence: "high"
10786
+ }]
10770
10787
  },
10771
10788
  trackon: {
10772
10789
  displayName: "Trackon Couriers",
@@ -11965,7 +11982,7 @@ var Ae = {
11965
11982
  "tforce-freight": [],
11966
11983
  thhy: ["thhy-1"],
11967
11984
  toptrans: [],
11968
- "total-express": [],
11985
+ "total-express": ["total-express-awb"],
11969
11986
  trackon: [],
11970
11987
  "trans-o-flex": [],
11971
11988
  "trendyol-express": [],
@@ -17118,6 +17135,7 @@ var nl = {
17118
17135
  "fan-courier": 330,
17119
17136
  "four-px": 570,
17120
17137
  foxpost: 200,
17138
+ gati: 43,
17121
17139
  geis: 90,
17122
17140
  "geniki-taxydromiki": 140,
17123
17141
  "geodis-pl": 994,
@@ -17178,6 +17196,7 @@ var nl = {
17178
17196
  saia: 12,
17179
17197
  sameday: 370,
17180
17198
  seur: 870,
17199
+ shadowfax: 595,
17181
17200
  "slovak-parcel-service": 180,
17182
17201
  "slovenska-posta": 170,
17183
17202
  speedaf: 989,
@@ -17189,6 +17208,7 @@ var nl = {
17189
17208
  thhy: 987,
17190
17209
  tipsa: 680,
17191
17210
  tnt: 880,
17211
+ "total-express": 975,
17192
17212
  tsjy: 992,
17193
17213
  "ubi-smart-parcel": 45,
17194
17214
  ukrposhta: 490,
@@ -0,0 +1,20 @@
1
+ import { type AdapterFactory, type TrackingContext } from '../../core/adapter/index.js';
2
+ import type { CarrierResult } from '../../core/result/index.js';
3
+ import { type StepRecorder } from '../../core/telemetry/index.js';
4
+ /** The page token the tracking page on www.allcargologistics.com asks for when it loads. */
5
+ export declare const GATI_TOKEN_URL = "https://admin.allcargologistics.com/api/frontend/token";
6
+ /** The lookup the tracking page makes for the docket number typed in. */
7
+ export declare const GATI_TRACKING_URL = "https://admin.allcargologistics.com/api/track-shipment";
8
+ export declare class GatiTracker {
9
+ private readonly options;
10
+ constructor(options?: {
11
+ fetcher?: typeof fetch;
12
+ recorder?: StepRecorder;
13
+ userAgent?: string;
14
+ });
15
+ fetch(raw: string, context?: TrackingContext): Promise<CarrierResult>;
16
+ private read;
17
+ /** A page token, as the tracking page gets one on every visit; it lasts five minutes. */
18
+ private token;
19
+ }
20
+ export declare const adapter: AdapterFactory;
@@ -0,0 +1,105 @@
1
+ import { accepted, recognizeFromLookup } from '../../core/adapter/index.js';
2
+ import { ChallengeError, SchemaError, TransportError, UpstreamHttpError, UpstreamNetworkError } from '../../core/errors/index.js';
3
+ import { runSteps } from '../../core/runner/index.js';
4
+ import { NOOP_RECORDER } from '../../core/telemetry/index.js';
5
+ import { decodeText, fetchBounded, userAgentOf } from '../../core/transport/index.js';
6
+ import { isRecord } from '../../core/types.js';
7
+ import { GATI_MAX_BYTES, normalizeGatiNumber, parseGati, PROVIDER } from './parser.js';
8
+ /** The page token the tracking page on www.allcargologistics.com asks for when it loads. */
9
+ export const GATI_TOKEN_URL = 'https://admin.allcargologistics.com/api/frontend/token';
10
+ /** The lookup the tracking page makes for the docket number typed in. */
11
+ export const GATI_TRACKING_URL = 'https://admin.allcargologistics.com/api/track-shipment';
12
+ // The site answers the lookup only for its own pages.
13
+ const ORIGIN = 'https://www.allcargologistics.com';
14
+ const REDIRECTS = [301, 302, 303, 307, 308];
15
+ // Bot checks a CDN or firewall could put in place of the reply.
16
+ const CHALLENGE = /_cf_chl_opt|cf-turnstile|<title>\s*Just a moment|AwsWafIntegration|awswaf\.com|g-recaptcha|h-captcha/i;
17
+ // The token is a number, a bar and forty letters and digits.
18
+ const TOKEN = /^[\w|.~+/=-]{8,512}$/;
19
+ function json(bytes) {
20
+ const body = decodeText(bytes);
21
+ try {
22
+ return JSON.parse(body);
23
+ }
24
+ catch (cause) {
25
+ if (CHALLENGE.test(body.slice(0, 64_000)))
26
+ throw new ChallengeError(PROVIDER, 'AllcargoGATI answered with a browser check', { cause });
27
+ throw new SchemaError(PROVIDER, 'AllcargoGATI returned a reply that is not JSON', { cause });
28
+ }
29
+ }
30
+ /**
31
+ * The same failure without the request details fetchBounded attaches: they
32
+ * hold the page token.
33
+ */
34
+ function withoutToken(error) {
35
+ if (error instanceof UpstreamHttpError)
36
+ return new UpstreamHttpError(error.provider, error.status, error.retryAfterMs);
37
+ if (error instanceof UpstreamNetworkError)
38
+ return new UpstreamNetworkError(error.provider, error.cause);
39
+ return error;
40
+ }
41
+ export class GatiTracker {
42
+ options;
43
+ constructor(options = {}) {
44
+ this.options = options;
45
+ }
46
+ async fetch(raw, context = {}) {
47
+ const number = normalizeGatiNumber(raw);
48
+ // One read with the whole budget: the site waits up to thirty seconds for
49
+ // the tracking service behind it, which some dockets never answer.
50
+ return runSteps({ carrier: 'gati', budgetMs: context.budgetMs ?? 20_000, signal: context.signal,
51
+ recorder: this.options.recorder ?? NOOP_RECORDER }, [
52
+ { id: 'direct', run: ({ signal, remainingMs }) => this.read(number, signal, remainingMs) },
53
+ ]);
54
+ }
55
+ async read(number, signal, budgetMs) {
56
+ const deadline = performance.now() + budgetMs;
57
+ const timeoutMs = () => Math.max(1, Math.floor(deadline - performance.now()));
58
+ const userAgent = userAgentOf(this.options.userAgent);
59
+ const token = await this.token(userAgent, signal, timeoutMs());
60
+ signal.throwIfAborted();
61
+ try {
62
+ const { response, bytes } = await fetchBounded(GATI_TRACKING_URL, { method: 'POST', signal, headers: {
63
+ Accept: 'application/json', 'Content-Type': 'application/json', Authorization: `Bearer ${token}`, Origin: ORIGIN, 'User-Agent': userAgent,
64
+ }, body: JSON.stringify({ docketNo: number }) }, { provider: PROVIDER, timeoutMs: timeoutMs(), maxBytes: GATI_MAX_BYTES,
65
+ redirect: 'manual', fetcher: this.options.fetcher, allowHttpStatuses: [...REDIRECTS, 401, 403, 404, 410, 422] });
66
+ if (REDIRECTS.includes(response.status))
67
+ throw new TransportError(PROVIDER, 'AllcargoGATI redirected its tracking lookup');
68
+ if (response.status === 404 || response.status === 410)
69
+ throw new TransportError(PROVIDER, 'AllcargoGATI tracking lookup is unavailable');
70
+ // The token was just issued and the origin is the site's own, so a refusal is a changed gate.
71
+ if (response.status === 401 || response.status === 403) {
72
+ throw new ChallengeError(PROVIDER, 'AllcargoGATI refused the tracking page token', { status: response.status });
73
+ }
74
+ // A refused number is HTTP 422 with the reasons, which the parser reads.
75
+ return parseGati(json(bytes), number);
76
+ }
77
+ catch (error) {
78
+ throw withoutToken(error);
79
+ }
80
+ }
81
+ /** A page token, as the tracking page gets one on every visit; it lasts five minutes. */
82
+ async token(userAgent, signal, timeoutMs) {
83
+ const { response, bytes } = await fetchBounded(GATI_TOKEN_URL, { method: 'POST', signal, headers: {
84
+ Accept: 'application/json', 'Content-Type': 'application/json', Origin: ORIGIN, 'User-Agent': userAgent,
85
+ }, body: '{}' }, { provider: PROVIDER, timeoutMs, maxBytes: 64_000, redirect: 'manual', fetcher: this.options.fetcher,
86
+ allowHttpStatuses: [...REDIRECTS, 404, 410] });
87
+ if (REDIRECTS.includes(response.status) || response.status === 404 || response.status === 410) {
88
+ throw new TransportError(PROVIDER, 'AllcargoGATI tracking page token is unavailable');
89
+ }
90
+ const grant = json(bytes);
91
+ const token = isRecord(grant) && typeof grant.token === 'string' ? grant.token : '';
92
+ if (!TOKEN.test(token) || !isRecord(grant) || String(grant.type).toLowerCase() !== 'bearer') {
93
+ throw new SchemaError(PROVIDER, 'AllcargoGATI did not issue a tracking page token');
94
+ }
95
+ return token;
96
+ }
97
+ }
98
+ export const adapter = (environment) => {
99
+ const tracker = new GatiTracker({ fetcher: environment.fetcher, recorder: environment.recorder, userAgent: environment.userAgent });
100
+ return {
101
+ id: 'gati', recordsSteps: true, steps: ['direct'],
102
+ track: (input, context) => tracker.fetch(input.number, context),
103
+ recognize: (number, context) => recognizeFromLookup(() => tracker.fetch(number, context), () => accepted(() => normalizeGatiNumber(number))),
104
+ };
105
+ };
@@ -22,17 +22,59 @@
22
22
  "timezone": "Asia/Kolkata",
23
23
  "tracking": {
24
24
  "mode": "automatic",
25
- "adapter": "universal",
26
- "steps": []
25
+ "adapter": "gati",
26
+ "steps": [
27
+ "direct"
28
+ ],
29
+ "recognition": {
30
+ "rank": 43
31
+ }
27
32
  },
28
- "capabilities": [],
33
+ "capabilities": [
34
+ "history",
35
+ "location",
36
+ "provider_code",
37
+ "delivered_at",
38
+ "eta",
39
+ "weight"
40
+ ],
29
41
  "portal": {
30
42
  "searchUrl": "https://www.allcargologistics.com/track-shipment",
31
43
  "canaryUrl": "https://www.allcargologistics.com/track-shipment",
32
- "shows": [],
33
- "scraped": [],
34
- "discarded": [],
35
- "unavailable": []
44
+ "shows": [
45
+ "status",
46
+ "history",
47
+ "origin",
48
+ "departure_date",
49
+ "destination",
50
+ "delivered_at",
51
+ "eta",
52
+ "recipient_name",
53
+ "remarks",
54
+ "proof_of_delivery"
55
+ ],
56
+ "scraped": [
57
+ "status",
58
+ "history",
59
+ "location",
60
+ "provider_code",
61
+ "delivered_at",
62
+ "eta",
63
+ "weight"
64
+ ],
65
+ "discarded": [
66
+ "origin",
67
+ "departure_date",
68
+ "destination",
69
+ "recipient_name",
70
+ "remarks",
71
+ "proof_of_delivery"
72
+ ],
73
+ "unavailable": [
74
+ "offset_timestamps",
75
+ "pickup_point",
76
+ "delivery_partner"
77
+ ]
36
78
  },
37
79
  "links": [
38
80
  {
@@ -88,7 +88,7 @@
88
88
  "access": "full_page"
89
89
  },
90
90
  "context": {
91
- "assessment": "candidate"
91
+ "assessment": "confirmed"
92
92
  },
93
93
  "expect": {
94
94
  "carrier": "unknown",
@@ -107,7 +107,7 @@
107
107
  "access": "full_page"
108
108
  },
109
109
  "context": {
110
- "assessment": "candidate"
110
+ "assessment": "confirmed"
111
111
  },
112
112
  "expect": {
113
113
  "carrier": "unknown",
@@ -126,7 +126,7 @@
126
126
  "access": "full_page"
127
127
  },
128
128
  "context": {
129
- "assessment": "candidate"
129
+ "assessment": "confirmed"
130
130
  },
131
131
  "expect": {
132
132
  "carrier": "unknown",
@@ -145,7 +145,7 @@
145
145
  "access": "full_page"
146
146
  },
147
147
  "context": {
148
- "assessment": "candidate"
148
+ "assessment": "confirmed"
149
149
  },
150
150
  "expect": {
151
151
  "carrier": "unknown",
@@ -164,7 +164,7 @@
164
164
  "access": "full_page"
165
165
  },
166
166
  "context": {
167
- "assessment": "candidate"
167
+ "assessment": "confirmed"
168
168
  },
169
169
  "expect": {
170
170
  "carrier": "unknown",
@@ -183,7 +183,7 @@
183
183
  "access": "full_page"
184
184
  },
185
185
  "context": {
186
- "assessment": "candidate"
186
+ "assessment": "confirmed"
187
187
  },
188
188
  "expect": {
189
189
  "carrier": "unknown",
@@ -202,7 +202,7 @@
202
202
  "access": "full_page"
203
203
  },
204
204
  "context": {
205
- "assessment": "candidate"
205
+ "assessment": "confirmed"
206
206
  },
207
207
  "expect": {
208
208
  "carrier": "unknown",
@@ -247,6 +247,66 @@
247
247
  "confidence": "none"
248
248
  },
249
249
  "note": "A customer review on TrackingMore's GATI Courier review page asks for delivery of this number."
250
+ },
251
+ {
252
+ "number": "412933252",
253
+ "role": "shipment",
254
+ "evidence": "public_shipment_report",
255
+ "source": {
256
+ "url": "https://www.trackingmore.com/review-gati-kwe.html",
257
+ "date": "2021-11-15",
258
+ "dateKind": "comment",
259
+ "access": "full_page"
260
+ },
261
+ "context": {
262
+ "assessment": "confirmed"
263
+ },
264
+ "expect": {
265
+ "carrier": "unknown",
266
+ "confidence": "low",
267
+ "candidates": [
268
+ "tnt"
269
+ ]
270
+ },
271
+ "note": "A customer review on TrackingMore's Gati KWE review page asks where the courier with this number is."
272
+ },
273
+ {
274
+ "number": "988397715",
275
+ "role": "shipment",
276
+ "evidence": "public_shipment_report",
277
+ "source": {
278
+ "url": "https://www.trackingmore.com/review-gati-kwe.html",
279
+ "date": "2021-09-03",
280
+ "dateKind": "comment",
281
+ "access": "full_page"
282
+ },
283
+ "context": {
284
+ "assessment": "candidate"
285
+ },
286
+ "expect": {
287
+ "carrier": "unknown",
288
+ "confidence": "none"
289
+ },
290
+ "note": "A customer review on TrackingMore's Gati KWE review page gives it as a Gati courier number."
291
+ },
292
+ {
293
+ "number": "139815455",
294
+ "role": "shipment",
295
+ "evidence": "public_shipment_report",
296
+ "source": {
297
+ "url": "https://www.trackingmore.com/review-gaticn.html",
298
+ "date": "2020-12-16",
299
+ "dateKind": "comment",
300
+ "access": "full_page"
301
+ },
302
+ "context": {
303
+ "assessment": "confirmed"
304
+ },
305
+ "expect": {
306
+ "carrier": "unknown",
307
+ "confidence": "none"
308
+ },
309
+ "note": "A customer review on TrackingMore's GATI Courier review page gives it as the docket of a shipment that arrived on time."
250
310
  }
251
311
  ]
252
312
  }