gerdur-core 1.0.2 → 1.0.3
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/CHANGELOG.md +6 -0
- package/dist/lib/get-url.js +34 -11
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,11 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 1.0.3 - 2026-08-30
|
|
4
|
+
|
|
5
|
+
### Changed
|
|
6
|
+
|
|
7
|
+
- `getTrackDownloadUrl`: when `media.deezer.com/v1/get_url` returns 403/429/5xx (throttling or a stale license token), re-authenticate and retry with exponential backoff (up to 3×); if it still fails, fall through to the token-free legacy CDN instead of throwing.
|
|
8
|
+
|
|
3
9
|
## 1.0.2 - 2026-08-30
|
|
4
10
|
|
|
5
11
|
### Fixed
|
package/dist/lib/get-url.js
CHANGED
|
@@ -4,6 +4,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
4
4
|
};
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
6
|
exports.getTrackDownloadUrl = exports.ExpiredTrackToken = exports.GeoBlocked = exports.WrongLicense = void 0;
|
|
7
|
+
const delay_1 = __importDefault(require("delay"));
|
|
7
8
|
const decrypt_1 = require("../lib/decrypt");
|
|
8
9
|
const http_1 = require("../lib/http");
|
|
9
10
|
const request_1 = __importDefault(require("../lib/request"));
|
|
@@ -64,21 +65,35 @@ const dzAuthenticate = async () => {
|
|
|
64
65
|
};
|
|
65
66
|
return user_data;
|
|
66
67
|
};
|
|
67
|
-
const
|
|
68
|
+
const MEDIA_MAX_RETRIES = 3;
|
|
69
|
+
const getTrackUrlFromServer = async (track_token, format, attempt = 0) => {
|
|
68
70
|
const user = user_data ? user_data : await dzAuthenticate();
|
|
69
71
|
if ((format === 'FLAC' && !user.can_stream_lossless) || (format === 'MP3_320' && !user.can_stream_hq)) {
|
|
70
72
|
throw new WrongLicense(format);
|
|
71
73
|
}
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
media
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
74
|
+
let data;
|
|
75
|
+
try {
|
|
76
|
+
({ data } = await request_1.default.post('https://media.deezer.com/v1/get_url', {
|
|
77
|
+
license_token: user.license_token,
|
|
78
|
+
media: [
|
|
79
|
+
{
|
|
80
|
+
type: 'FULL',
|
|
81
|
+
formats: [{ format, cipher: 'BF_CBC_STRIPE' }],
|
|
82
|
+
},
|
|
83
|
+
],
|
|
84
|
+
track_tokens: [track_token],
|
|
85
|
+
}));
|
|
86
|
+
}
|
|
87
|
+
catch (err) {
|
|
88
|
+
// media.deezer.com throttles / 5xx / stale license_token — re-auth and back off
|
|
89
|
+
const status = err instanceof http_1.HttpStatusError ? err.statusCode : 0;
|
|
90
|
+
if ((status === 403 || status === 429 || status >= 500) && attempt < MEDIA_MAX_RETRIES) {
|
|
91
|
+
user_data = null;
|
|
92
|
+
await (0, delay_1.default)(500 * 2 ** attempt + Math.floor(Math.random() * 250));
|
|
93
|
+
return getTrackUrlFromServer(track_token, format, attempt + 1);
|
|
94
|
+
}
|
|
95
|
+
throw err;
|
|
96
|
+
}
|
|
82
97
|
if (data.data.length > 0) {
|
|
83
98
|
if (data.data[0].errors) {
|
|
84
99
|
const { code } = data.data[0].errors[0];
|
|
@@ -103,6 +118,7 @@ const getTrackDownloadUrl = async (track, quality) => {
|
|
|
103
118
|
let wrongLicense = null;
|
|
104
119
|
let geoBlocked = null;
|
|
105
120
|
let expiredToken = null;
|
|
121
|
+
let mediaBlocked = null;
|
|
106
122
|
let formatName;
|
|
107
123
|
switch (quality) {
|
|
108
124
|
case 9:
|
|
@@ -145,6 +161,10 @@ const getTrackDownloadUrl = async (track, quality) => {
|
|
|
145
161
|
else if (err instanceof ExpiredTrackToken) {
|
|
146
162
|
expiredToken = err;
|
|
147
163
|
}
|
|
164
|
+
else if (err instanceof http_1.HttpStatusError && (err.statusCode === 403 || err.statusCode === 429)) {
|
|
165
|
+
// media API is throttling this account — try the token-free legacy CDN below
|
|
166
|
+
mediaBlocked = err;
|
|
167
|
+
}
|
|
148
168
|
else {
|
|
149
169
|
throw err;
|
|
150
170
|
}
|
|
@@ -172,6 +192,9 @@ const getTrackDownloadUrl = async (track, quality) => {
|
|
|
172
192
|
if (expiredToken) {
|
|
173
193
|
throw expiredToken;
|
|
174
194
|
}
|
|
195
|
+
if (mediaBlocked) {
|
|
196
|
+
throw mediaBlocked;
|
|
197
|
+
}
|
|
175
198
|
return null;
|
|
176
199
|
};
|
|
177
200
|
exports.getTrackDownloadUrl = getTrackDownloadUrl;
|