universal-parcel-scraper 0.69.2-main.888 → 0.69.4-main.892
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/data/catalog.json +4 -3
- package/dist/browser/scraper.js +4 -3
- package/dist/carriers/canada-post/app.d.ts +2 -0
- package/dist/carriers/canada-post/app.js +7 -0
- package/dist/carriers/canada-post/parser.js +12 -8
- package/dist/carriers/ctt/adapter.js +7 -3
- package/dist/carriers/ctt/app.d.ts +2 -0
- package/dist/carriers/ctt/app.js +6 -0
- package/dist/carriers/nz-post/identity.js +3 -1
- package/dist/carriers/nz-post/parser.js +12 -7
- package/dist/carriers/swiss-post/app.js +4 -0
- package/dist/carriers/usps/adapter.js +6 -17
- package/dist/carriers/usps/carrier.json +4 -3
- package/dist/core/catalog/eventIdentity.js +3 -1
- package/dist/data/catalog.json +4 -3
- package/dist/generated/catalog.d.ts +3 -2
- package/dist/generated/catalog.js +4 -3
- package/dist/server/openapi.json +1 -1
- package/package.json +1 -1
package/data/catalog.json
CHANGED
|
@@ -2702,8 +2702,8 @@
|
|
|
2702
2702
|
"browserRecognitionRank": 65
|
|
2703
2703
|
},
|
|
2704
2704
|
"canaryUrl": "https://www.usps.com/",
|
|
2705
|
-
"trackingUrlTemplate": "https://tools.usps.com/
|
|
2706
|
-
"trackingSearchUrl": "https://tools.usps.com/
|
|
2705
|
+
"trackingUrlTemplate": "https://tools.usps.com/tracking/{trackingNumber}",
|
|
2706
|
+
"trackingSearchUrl": "https://tools.usps.com/tracking/",
|
|
2707
2707
|
"linkRules": [
|
|
2708
2708
|
{
|
|
2709
2709
|
"domains": [
|
|
@@ -2712,7 +2712,8 @@
|
|
|
2712
2712
|
],
|
|
2713
2713
|
"params": [
|
|
2714
2714
|
"tLabels"
|
|
2715
|
-
]
|
|
2715
|
+
],
|
|
2716
|
+
"path": "^/tracking/(\\d{20}|\\d{22}|\\d{26}|[A-Z]{2}\\d{9}[A-Z]{2})/?$"
|
|
2716
2717
|
}
|
|
2717
2718
|
],
|
|
2718
2719
|
"detectionRules": [
|
package/dist/browser/scraper.js
CHANGED
|
@@ -2290,11 +2290,12 @@ var ye = {
|
|
|
2290
2290
|
browserRecognitionRank: 65
|
|
2291
2291
|
},
|
|
2292
2292
|
canaryUrl: "https://www.usps.com/",
|
|
2293
|
-
trackingUrlTemplate: "https://tools.usps.com/
|
|
2294
|
-
trackingSearchUrl: "https://tools.usps.com/
|
|
2293
|
+
trackingUrlTemplate: "https://tools.usps.com/tracking/{trackingNumber}",
|
|
2294
|
+
trackingSearchUrl: "https://tools.usps.com/tracking/",
|
|
2295
2295
|
linkRules: [{
|
|
2296
2296
|
domains: ["tools.usps.com", "usps.com"],
|
|
2297
|
-
params: ["tLabels"]
|
|
2297
|
+
params: ["tLabels"],
|
|
2298
|
+
path: "^/tracking/(\\d{20}|\\d{22}|\\d{26}|[A-Z]{2}\\d{9}[A-Z]{2})/?$"
|
|
2298
2299
|
}],
|
|
2299
2300
|
detectionRules: [
|
|
2300
2301
|
{
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
// Scans relayed from other posts kept Canada Post's -05:00 or -04:00 until
|
|
2
|
+
// October 2026, and those in a country with one clock now show its offset.
|
|
3
|
+
// The old label is read as -05:00, the one Canada Post gives them in winter and
|
|
4
|
+
// often in summer; a row stored under -04:00 is not recognized.
|
|
5
|
+
export const sameInstantIdentityPolicy = {
|
|
6
|
+
sourceCarrierId: 'canada-post', storedSources: ['canada-post'], requireProviderCode: true, relabelledFrom: 'Etc/GMT+5',
|
|
7
|
+
};
|
|
@@ -81,8 +81,9 @@ const EXCHANGE_SCANS = new Set(['4000', '4100', '4202', '4310', '4311', '4330',
|
|
|
81
81
|
* Post's own page, a Korean one is on Korea Post's clock, a Montana delivery
|
|
82
82
|
* office's "05:05 -05:00" is 05:05 MDT on USPS's page, and the Toronto
|
|
83
83
|
* exchange office's "01:11 -05:00" fell in summer time (checked 2026-10-10).
|
|
84
|
-
* Such a scan is read on its country's single clock; elsewhere it
|
|
85
|
-
*
|
|
84
|
+
* Such a scan is read on its country's single clock; elsewhere it keeps
|
|
85
|
+
* Canada Post's offset, the last guess: hours off, but the reply keeps its
|
|
86
|
+
* instant. Null for a scan whose offset stands.
|
|
86
87
|
*/
|
|
87
88
|
function relayedClock(code, country, region) {
|
|
88
89
|
const abroad = country !== '' && country !== 'CA';
|
|
@@ -104,12 +105,12 @@ function eventClock(value, relayed = null) {
|
|
|
104
105
|
const placed = relayed?.zone ? isoTime(local, relayed.zone) : null;
|
|
105
106
|
if (placed)
|
|
106
107
|
return { time: placed.iso };
|
|
107
|
-
if (
|
|
108
|
+
if (/^(?:Z|[+-](?:(?:0\d|1[0-3]):[0-5]\d|14:00))$/i.test(offset)) {
|
|
108
109
|
const parsed = explicitOffsetTime(`${local}${offset}`);
|
|
109
110
|
if (parsed)
|
|
110
111
|
return { time: parsed.iso };
|
|
111
112
|
}
|
|
112
|
-
else if (
|
|
113
|
+
else if (!offset) {
|
|
113
114
|
// UTC validates the calendar only; no timezone is attached to local digits.
|
|
114
115
|
const parsed = DateTime.fromISO(local, { zone: 'UTC' });
|
|
115
116
|
const valid = parsed.isValid ? parsed.toISO({ includeOffset: false, suppressMilliseconds: true }) : null;
|
|
@@ -184,14 +185,17 @@ export function parseCanadaPostTrackingResponse(payload, trackingNumber) {
|
|
|
184
185
|
const location = isRecord(raw.locationAddr)
|
|
185
186
|
? [textField(raw.locationAddr, 'city', 160), region].filter(Boolean).join(', ') : '';
|
|
186
187
|
const stage = type === 'Signature' || code === '20' ? null : canadaPostScanStage(code, description) ?? canadaPostStage(description);
|
|
187
|
-
const
|
|
188
|
+
const relayed = relayedClock(code, country, region);
|
|
189
|
+
const clock = eventClock(raw.datetime, relayed);
|
|
190
|
+
const event = { ...clock, description: stage === 'delivered' ? 'Delivered' : description,
|
|
188
191
|
provider_code: code, ...(stage ? { stage } : {}), ...(location ? { location } : {}) };
|
|
189
192
|
return { event, type, region, country, sourceDate: isRecord(raw.datetime) ? calendarDate(raw.datetime.date) : null,
|
|
190
|
-
returnCue: returnStarted(description) || type === 'RtsLabelProc' };
|
|
193
|
+
returnCue: returnStarted(description) || type === 'RtsLabelProc', guessed: relayed?.zone === null && 'time' in clock };
|
|
191
194
|
});
|
|
192
195
|
// Native detail history is newest first. Compare instants only when every
|
|
193
|
-
// row resolves; an unresolved latest row must not
|
|
194
|
-
|
|
196
|
+
// row resolves, and none only by a guess; an unresolved latest row must not
|
|
197
|
+
// fall behind old scans, nor a guessed one behind a scan placed abroad.
|
|
198
|
+
if (rows.every(row => row.event.time && !row.guessed))
|
|
195
199
|
rows.sort((a, b) => Date.parse(b.event.time) - Date.parse(a.event.time));
|
|
196
200
|
let returning = false;
|
|
197
201
|
for (const row of [...rows].reverse()) {
|
|
@@ -89,9 +89,10 @@ const WALL_CLOCK = /^(\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2})(?:\.\d{1,3})?(?:Z|\+0
|
|
|
89
89
|
* A scan's clock. CTT's Z is no offset: the digits are the wall clock where
|
|
90
90
|
* the scan happened (see clock.ts). That is the destination's, for a
|
|
91
91
|
* partner post's scan of a parcel bound abroad (`abroad`), unless the
|
|
92
|
-
* location names an office or a site of CTT's; Portugal's otherwise.
|
|
93
|
-
* destination with several zones
|
|
94
|
-
*
|
|
92
|
+
* location names an office or a site of CTT's; Portugal's otherwise. In a
|
|
93
|
+
* destination with several zones the scan keeps CTT's Z, the last guess:
|
|
94
|
+
* hours off, but the reply keeps its instant. Only a wall clock sent with no
|
|
95
|
+
* Z stays a wall time there. Any other offset is taken as sent.
|
|
95
96
|
*/
|
|
96
97
|
function scanClock(value, location, abroad) {
|
|
97
98
|
const raw = typeof value === 'string' ? value.trim() : '';
|
|
@@ -104,6 +105,9 @@ function scanClock(value, location, abroad) {
|
|
|
104
105
|
const placed = zone ? isoTime(wall, zone) : null;
|
|
105
106
|
if (placed)
|
|
106
107
|
return { time: placed.iso, timestamp: placed.timestamp };
|
|
108
|
+
const labelled = explicitOffsetTime(raw);
|
|
109
|
+
if (labelled)
|
|
110
|
+
return { time: labelled.iso, timestamp: labelled.timestamp };
|
|
107
111
|
const read = Date.parse(`${wall}Z`);
|
|
108
112
|
return Number.isFinite(read) ? { local_time: wall, timestamp: read } : null;
|
|
109
113
|
}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
// Scan times were read as the UTC their Z says until October 2026, and now show
|
|
2
|
+
// the clock of the place the scan happened: Lisbon's, the Azores' or the
|
|
3
|
+
// destination's. Lisbon's winter scans keep their instants under +00:00.
|
|
4
|
+
export const sameInstantIdentityPolicy = {
|
|
5
|
+
sourceCarrierId: 'ctt', storedSources: ['ctt'], requireProviderCode: true, relabelledFrom: 'UTC',
|
|
6
|
+
};
|
|
@@ -14,7 +14,9 @@ function matches(incoming, stored) {
|
|
|
14
14
|
&& wording === normalized(stored.description)
|
|
15
15
|
&& (location === savedLocation || (!location && isNzPostPlaceholderLocation(savedLocation)));
|
|
16
16
|
}
|
|
17
|
+
// Scans abroad were read on Auckland's clock until October 2026 and now show
|
|
18
|
+
// the offset of the country they happened in, unless nothing places them.
|
|
17
19
|
export const sameInstantIdentityPolicy = {
|
|
18
20
|
sourceCarrierId: 'nz-post', storedSources: ['nz-post'], requireProviderCode: true,
|
|
19
|
-
matchEachScan: true, matches,
|
|
21
|
+
matchEachScan: true, matches, relabelledFrom: 'Pacific/Auckland',
|
|
20
22
|
};
|
|
@@ -53,7 +53,8 @@ function abroadWall(clocked) {
|
|
|
53
53
|
* an airline's included ("China"), else the nearest later one's. All of them
|
|
54
54
|
* are the destination post's or the flight's to it; a transit hub's country
|
|
55
55
|
* can be wrong, but Hong Kong, Singapore and China keep one clock. Null when
|
|
56
|
-
* that country has several clocks or none is named: the scan
|
|
56
|
+
* that country has several clocks or none is named: the scan keeps NZ Post's
|
|
57
|
+
* Auckland reading, the last guess.
|
|
57
58
|
*/
|
|
58
59
|
function abroadZone(scans, position) {
|
|
59
60
|
const country = scans[position].country ?? scans.slice(0, position).reverse().find(other => other.country)?.country
|
|
@@ -119,23 +120,27 @@ export function parseNzPost(payload, number) {
|
|
|
119
120
|
return { ...clocked, description, provider_code: code,
|
|
120
121
|
...(location ? { location } : {}), ...(mapped ? { stage: mapped.stage } : {}) };
|
|
121
122
|
});
|
|
123
|
+
// A scan nothing places keeps NZ Post's Auckland reading, the last guess:
|
|
124
|
+
// hours off, but the reply keeps its instant.
|
|
125
|
+
let guessed = false;
|
|
122
126
|
afterDeparture.forEach((scan, position) => {
|
|
123
127
|
// An airline's scan only lends its country: its clock was not checked.
|
|
124
128
|
if (!scan.wall)
|
|
125
129
|
return;
|
|
126
130
|
const zone = abroadZone(afterDeparture, position);
|
|
127
131
|
const placed = zone ? isoTime(scan.wall, zone) : null;
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
+
if (placed)
|
|
133
|
+
projected[scan.index] = { ...projected[scan.index], time: placed.iso };
|
|
134
|
+
else
|
|
135
|
+
guessed = true;
|
|
132
136
|
});
|
|
133
137
|
if (!projected.length)
|
|
134
138
|
throw new IndeterminateError('nz-post', 'NZ Post returned no parcel history');
|
|
135
139
|
// The consumer client treats the last source row as current. Preserve that
|
|
136
|
-
// order if any clock is unresolved instead of promoting an
|
|
140
|
+
// order if any clock is unresolved, or only guessed, instead of promoting an
|
|
141
|
+
// older dated row: a guessed clock can fall hours behind one placed abroad.
|
|
137
142
|
projected.reverse();
|
|
138
|
-
if (projected.every(event => event.time))
|
|
143
|
+
if (!guessed && projected.every(event => event.time))
|
|
139
144
|
projected.sort((a, b) => Date.parse(b.time) - Date.parse(a.time));
|
|
140
145
|
const seen = new Set();
|
|
141
146
|
const events = projected.filter(event => {
|
|
@@ -1,6 +1,10 @@
|
|
|
1
1
|
import { matchesLocationEnrichment } from '../../core/catalog/locationIdentity.js';
|
|
2
|
+
// The destination post's scans of a parcel sent abroad came with Swiss Post's
|
|
3
|
+
// Zurich offset until October 2026, and now show the destination's when it
|
|
4
|
+
// keeps one clock.
|
|
2
5
|
export const sameInstantIdentityPolicy = {
|
|
3
6
|
sourceCarrierId: 'swiss-post', storedSources: ['swiss-post'], requireProviderCode: true,
|
|
4
7
|
matchEachScan: true,
|
|
5
8
|
matches: matchesLocationEnrichment,
|
|
9
|
+
relabelledFrom: 'Europe/Zurich',
|
|
6
10
|
};
|
|
@@ -12,21 +12,12 @@ import { uspsStage, uspsStatus } from './status.js';
|
|
|
12
12
|
/**
|
|
13
13
|
* USPS, through the server-rendered tracking page.
|
|
14
14
|
*
|
|
15
|
-
* The page
|
|
16
|
-
*
|
|
17
|
-
*
|
|
18
|
-
*
|
|
19
|
-
* can vary by session. The lookup has a single
|
|
20
|
-
* step: the private browser service loads the page, and the rendered DOM is
|
|
21
|
-
* parsed. Nothing is ever replayed over plain HTTP.
|
|
22
|
-
*
|
|
23
|
-
* Markup provenance: the live page shell (`.track-bar-container`,
|
|
24
|
-
* `#trackingNum`, `.latest-update-banner-wrapper .banner-header`,
|
|
25
|
-
* `.current-tracking-status-wrapper`), inspected 2026-09-20. Positive lookups
|
|
26
|
-
* on 2026-09-22 use `.tb-step` timeline cards, including collapsed history.
|
|
27
|
-
* The older table-shaped fixture remains a parsing fallback.
|
|
15
|
+
* The `/tracking/{number}` page carries the verdict and collapsed history
|
|
16
|
+
* in its HTML. The legacy query route can return only the global header,
|
|
17
|
+
* so load the package path directly. The browser handles verification;
|
|
18
|
+
* nothing is replayed over plain HTTP.
|
|
28
19
|
*/
|
|
29
|
-
const TRACKING_BASE = 'https://tools.usps.com/
|
|
20
|
+
const TRACKING_BASE = 'https://tools.usps.com/tracking/';
|
|
30
21
|
const MAX_BYTES = 10_000_000;
|
|
31
22
|
const DEFAULT_TIMEOUT_MS = 90_000;
|
|
32
23
|
const MAX_EVENTS_TO_RETURN = 100;
|
|
@@ -47,9 +38,7 @@ export function normalizeUSPSNumber(raw) {
|
|
|
47
38
|
return value;
|
|
48
39
|
}
|
|
49
40
|
export function uspsTrackingUrl(trackingNumber) {
|
|
50
|
-
|
|
51
|
-
url.searchParams.set('tLabels', normalizeUSPSNumber(trackingNumber));
|
|
52
|
-
return url.toString();
|
|
41
|
+
return new URL(normalizeUSPSNumber(trackingNumber), TRACKING_BASE).toString();
|
|
53
42
|
}
|
|
54
43
|
const MONTHS = '(January|February|March|April|May|June|July|August|September|October|November|December)';
|
|
55
44
|
const DATE_PATTERN = new RegExp(`${MONTHS}\\s+\\d{1,2},?\\s+\\d{4}`, 'i');
|
|
@@ -30,8 +30,8 @@
|
|
|
30
30
|
"eta"
|
|
31
31
|
],
|
|
32
32
|
"portal": {
|
|
33
|
-
"url": "https://tools.usps.com/
|
|
34
|
-
"searchUrl": "https://tools.usps.com/
|
|
33
|
+
"url": "https://tools.usps.com/tracking/{trackingNumber}",
|
|
34
|
+
"searchUrl": "https://tools.usps.com/tracking/",
|
|
35
35
|
"canaryUrl": "https://www.usps.com/",
|
|
36
36
|
"shows": [
|
|
37
37
|
"status",
|
|
@@ -60,7 +60,8 @@
|
|
|
60
60
|
],
|
|
61
61
|
"params": [
|
|
62
62
|
"tLabels"
|
|
63
|
-
]
|
|
63
|
+
],
|
|
64
|
+
"path": "^/tracking/(\\d{20}|\\d{22}|\\d{26}|[A-Z]{2}\\d{9}[A-Z]{2})/?$"
|
|
64
65
|
}
|
|
65
66
|
],
|
|
66
67
|
"detection": [
|
|
@@ -2,9 +2,11 @@ import { sameInstantIdentityPolicy as aliexpress } from '../../carriers/aliexpre
|
|
|
2
2
|
import { sameInstantIdentityPolicy as amazonShipping } from '../../carriers/amazon-shipping/app.js';
|
|
3
3
|
import { sameInstantIdentityPolicy as australiaPost } from '../../carriers/australia-post/app.js';
|
|
4
4
|
import { sameInstantIdentityPolicy as austrianPost } from '../../carriers/austrian-post/identity.js';
|
|
5
|
+
import { sameInstantIdentityPolicy as canadaPost } from '../../carriers/canada-post/app.js';
|
|
5
6
|
import { sameInstantIdentityPolicy as chronopost } from '../../carriers/chronopost/identity.js';
|
|
6
7
|
import { sameInstantIdentityPolicy as ciblex } from '../../carriers/ciblex/identity.js';
|
|
7
8
|
import { sameInstantIdentityPolicy as correosExpress } from '../../carriers/correos-express/identity.js';
|
|
9
|
+
import { sameInstantIdentityPolicy as ctt } from '../../carriers/ctt/app.js';
|
|
8
10
|
import { sameInstantIdentityPolicy as dpd } from '../../carriers/dpd/app.js';
|
|
9
11
|
import { sameInstantIdentityPolicy as dpdFrance } from '../../carriers/dpd-fr/identity.js';
|
|
10
12
|
import { sameInstantIdentityPolicy as hermesGermany } from '../../carriers/hermes-de/identity.js';
|
|
@@ -23,7 +25,7 @@ import { sameInstantIdentityPolicy as ups } from '../../carriers/ups/app.js';
|
|
|
23
25
|
import { sameInstantIdentityPolicy as swissPost } from '../../carriers/swiss-post/app.js';
|
|
24
26
|
import { sameInstantIdentityPolicy as yanwen } from '../../carriers/yanwen/app.js';
|
|
25
27
|
import { sameInstantIdentityPolicy as universal } from '../../providers/shared/app.js';
|
|
26
|
-
const policies = new Map([aliexpress, amazonShipping, australiaPost, austrianPost, chronopost, ciblex, correosExpress, dpd, dpdFrance, hermesGermany, indiaPost, jdLogistics, lbcExpress, mondialRelay, mrw, nzPost, posMalaysia, posteItaliane, posti, speedpak, sunYou, ups, swissPost, yanwen, universal].map((policy) => [policy.sourceCarrierId, policy]));
|
|
28
|
+
const policies = new Map([aliexpress, amazonShipping, australiaPost, austrianPost, canadaPost, chronopost, ciblex, correosExpress, ctt, dpd, dpdFrance, hermesGermany, indiaPost, jdLogistics, lbcExpress, mondialRelay, mrw, nzPost, posMalaysia, posteItaliane, posti, speedpak, sunYou, ups, swissPost, yanwen, universal].map((policy) => [policy.sourceCarrierId, policy]));
|
|
27
29
|
/** Unlisted sources cannot identify a reworded scan by its instant alone. */
|
|
28
30
|
export function sameInstantIdentityPolicy(sourceCarrierId, options = {}) {
|
|
29
31
|
const policy = policies.get(sourceCarrierId);
|
package/dist/data/catalog.json
CHANGED
|
@@ -2702,8 +2702,8 @@
|
|
|
2702
2702
|
"browserRecognitionRank": 65
|
|
2703
2703
|
},
|
|
2704
2704
|
"canaryUrl": "https://www.usps.com/",
|
|
2705
|
-
"trackingUrlTemplate": "https://tools.usps.com/
|
|
2706
|
-
"trackingSearchUrl": "https://tools.usps.com/
|
|
2705
|
+
"trackingUrlTemplate": "https://tools.usps.com/tracking/{trackingNumber}",
|
|
2706
|
+
"trackingSearchUrl": "https://tools.usps.com/tracking/",
|
|
2707
2707
|
"linkRules": [
|
|
2708
2708
|
{
|
|
2709
2709
|
"domains": [
|
|
@@ -2712,7 +2712,8 @@
|
|
|
2712
2712
|
],
|
|
2713
2713
|
"params": [
|
|
2714
2714
|
"tLabels"
|
|
2715
|
-
]
|
|
2715
|
+
],
|
|
2716
|
+
"path": "^/tracking/(\\d{20}|\\d{22}|\\d{26}|[A-Z]{2}\\d{9}[A-Z]{2})/?$"
|
|
2716
2717
|
}
|
|
2717
2718
|
],
|
|
2718
2719
|
"detectionRules": [
|
|
@@ -1830,11 +1830,12 @@ export declare const CARRIER_CATALOG: {
|
|
|
1830
1830
|
readonly browserRecognitionRank: 65;
|
|
1831
1831
|
};
|
|
1832
1832
|
readonly canaryUrl: "https://www.usps.com/";
|
|
1833
|
-
readonly trackingUrlTemplate: "https://tools.usps.com/
|
|
1834
|
-
readonly trackingSearchUrl: "https://tools.usps.com/
|
|
1833
|
+
readonly trackingUrlTemplate: "https://tools.usps.com/tracking/{trackingNumber}";
|
|
1834
|
+
readonly trackingSearchUrl: "https://tools.usps.com/tracking/";
|
|
1835
1835
|
readonly linkRules: readonly [{
|
|
1836
1836
|
readonly domains: readonly ["tools.usps.com", "usps.com"];
|
|
1837
1837
|
readonly params: readonly ["tLabels"];
|
|
1838
|
+
readonly path: "^/tracking/(\\d{20}|\\d{22}|\\d{26}|[A-Z]{2}\\d{9}[A-Z]{2})/?$";
|
|
1838
1839
|
}];
|
|
1839
1840
|
readonly detectionRules: readonly [{
|
|
1840
1841
|
readonly pattern: "^(?!9[23]61)(?:91\\d{2}9\\d{17}|92\\d{3}9\\d{16}|93\\d{3}[0-8]\\d{16}|9[45]\\d{20})$";
|
|
@@ -2703,8 +2703,8 @@ export const CARRIER_CATALOG = {
|
|
|
2703
2703
|
"browserRecognitionRank": 65
|
|
2704
2704
|
},
|
|
2705
2705
|
"canaryUrl": "https://www.usps.com/",
|
|
2706
|
-
"trackingUrlTemplate": "https://tools.usps.com/
|
|
2707
|
-
"trackingSearchUrl": "https://tools.usps.com/
|
|
2706
|
+
"trackingUrlTemplate": "https://tools.usps.com/tracking/{trackingNumber}",
|
|
2707
|
+
"trackingSearchUrl": "https://tools.usps.com/tracking/",
|
|
2708
2708
|
"linkRules": [
|
|
2709
2709
|
{
|
|
2710
2710
|
"domains": [
|
|
@@ -2713,7 +2713,8 @@ export const CARRIER_CATALOG = {
|
|
|
2713
2713
|
],
|
|
2714
2714
|
"params": [
|
|
2715
2715
|
"tLabels"
|
|
2716
|
-
]
|
|
2716
|
+
],
|
|
2717
|
+
"path": "^/tracking/(\\d{20}|\\d{22}|\\d{26}|[A-Z]{2}\\d{9}[A-Z]{2})/?$"
|
|
2717
2718
|
}
|
|
2718
2719
|
],
|
|
2719
2720
|
"detectionRules": [
|
package/dist/server/openapi.json
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "universal-parcel-scraper",
|
|
3
|
-
"version": "0.69.
|
|
3
|
+
"version": "0.69.4-main.892",
|
|
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",
|