fluncle 0.67.0 → 0.68.0
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/bin/fluncle.mjs +80 -5
- package/package.json +1 -1
package/bin/fluncle.mjs
CHANGED
|
@@ -423,7 +423,7 @@ function parseVersion(version) {
|
|
|
423
423
|
var currentVersion;
|
|
424
424
|
var init_version = __esm(() => {
|
|
425
425
|
init_output();
|
|
426
|
-
currentVersion = "0.
|
|
426
|
+
currentVersion = "0.68.0".trim() ? "0.68.0".trim() : "0.1.0";
|
|
427
427
|
});
|
|
428
428
|
|
|
429
429
|
// src/update-notifier.ts
|
|
@@ -2138,7 +2138,7 @@ function parseVersion2(version) {
|
|
|
2138
2138
|
var currentVersion2, latestReleaseUrl = "https://api.github.com/repos/mauricekleine/fluncle/releases/latest";
|
|
2139
2139
|
var init_version2 = __esm(() => {
|
|
2140
2140
|
init_output();
|
|
2141
|
-
currentVersion2 = "0.
|
|
2141
|
+
currentVersion2 = "0.68.0".trim() ? "0.68.0".trim() : "0.1.0";
|
|
2142
2142
|
});
|
|
2143
2143
|
|
|
2144
2144
|
// ../../packages/registry/src/index.ts
|
|
@@ -3162,6 +3162,73 @@ var init_admin_tracks = __esm(() => {
|
|
|
3162
3162
|
init_recent2();
|
|
3163
3163
|
});
|
|
3164
3164
|
|
|
3165
|
+
// src/version-match.ts
|
|
3166
|
+
function isRemix(title) {
|
|
3167
|
+
return REMIX_MARKER.test(title);
|
|
3168
|
+
}
|
|
3169
|
+
function stripVersionSuffix(title) {
|
|
3170
|
+
const parts = title.split(/\s+-\s+/);
|
|
3171
|
+
if (parts.length > 1 && VERSION_MARKER.test(parts[parts.length - 1] ?? "")) {
|
|
3172
|
+
return parts.slice(0, -1).join(" - ").trim();
|
|
3173
|
+
}
|
|
3174
|
+
return title.trim();
|
|
3175
|
+
}
|
|
3176
|
+
function tokenize(value) {
|
|
3177
|
+
return value.toLowerCase().normalize("NFKD").replace(/[̀-ͯ]/g, "").replace(/[^a-z0-9]+/g, " ").trim().split(" ").filter(Boolean);
|
|
3178
|
+
}
|
|
3179
|
+
function versionTokens(title) {
|
|
3180
|
+
const parts = title.split(/\s+-\s+/);
|
|
3181
|
+
const tail = parts.length > 1 ? parts[parts.length - 1] ?? "" : "";
|
|
3182
|
+
if (parts.length > 1 && VERSION_MARKER.test(tail)) {
|
|
3183
|
+
return new Set(tokenize(tail));
|
|
3184
|
+
}
|
|
3185
|
+
const bracketed = /[([]([^)\]]*?)[)\]]/.exec(title);
|
|
3186
|
+
if (bracketed?.[1] && VERSION_MARKER.test(bracketed[1])) {
|
|
3187
|
+
return new Set(tokenize(bracketed[1]));
|
|
3188
|
+
}
|
|
3189
|
+
return new Set;
|
|
3190
|
+
}
|
|
3191
|
+
function versionMatches(findingTitle, candidateTitle) {
|
|
3192
|
+
const findingIsRemix = isRemix(findingTitle);
|
|
3193
|
+
const candidateIsRemix = isRemix(candidateTitle);
|
|
3194
|
+
if (findingIsRemix) {
|
|
3195
|
+
if (!candidateIsRemix) {
|
|
3196
|
+
return false;
|
|
3197
|
+
}
|
|
3198
|
+
const want = [...versionTokens(findingTitle)].filter((t) => !VERSION_STOPWORDS.has(t));
|
|
3199
|
+
if (want.length === 0) {
|
|
3200
|
+
return true;
|
|
3201
|
+
}
|
|
3202
|
+
const have = versionTokens(candidateTitle);
|
|
3203
|
+
for (const token of want) {
|
|
3204
|
+
if (!have.has(token)) {
|
|
3205
|
+
return false;
|
|
3206
|
+
}
|
|
3207
|
+
}
|
|
3208
|
+
return true;
|
|
3209
|
+
}
|
|
3210
|
+
return !candidateIsRemix;
|
|
3211
|
+
}
|
|
3212
|
+
function baseTitleMatches(findingTitle, candidateTitle) {
|
|
3213
|
+
const want = new Set(tokenize(stripVersionSuffix(findingTitle)));
|
|
3214
|
+
const have = new Set(tokenize(stripVersionSuffix(candidateTitle)));
|
|
3215
|
+
if (want.size === 0) {
|
|
3216
|
+
return false;
|
|
3217
|
+
}
|
|
3218
|
+
for (const token of want) {
|
|
3219
|
+
if (!have.has(token)) {
|
|
3220
|
+
return false;
|
|
3221
|
+
}
|
|
3222
|
+
}
|
|
3223
|
+
return true;
|
|
3224
|
+
}
|
|
3225
|
+
var VERSION_MARKER, REMIX_MARKER, VERSION_STOPWORDS;
|
|
3226
|
+
var init_version_match = __esm(() => {
|
|
3227
|
+
VERSION_MARKER = /\b(mix|edit|version|remix|dub|vip|bootleg|rework|re-?edit|flip|refix|remaster(?:ed)?|instrumental)\b/i;
|
|
3228
|
+
REMIX_MARKER = /\b(remix|bootleg|vip|rework|re-?edit|flip|refix)\b/i;
|
|
3229
|
+
VERSION_STOPWORDS = new Set(["mix", "the", "and", "feat", "ft", "edit", "version", "remix"]);
|
|
3230
|
+
});
|
|
3231
|
+
|
|
3165
3232
|
// src/commands/preview-archive.ts
|
|
3166
3233
|
var exports_preview_archive = {};
|
|
3167
3234
|
__export(exports_preview_archive, {
|
|
@@ -3265,16 +3332,22 @@ async function resolveDeezerByIsrc(isrc) {
|
|
|
3265
3332
|
return;
|
|
3266
3333
|
}
|
|
3267
3334
|
}
|
|
3335
|
+
function durationAgrees(findingMs, candidateSeconds) {
|
|
3336
|
+
if (!findingMs || !candidateSeconds) {
|
|
3337
|
+
return true;
|
|
3338
|
+
}
|
|
3339
|
+
return Math.abs(candidateSeconds - findingMs / 1000) <= DURATION_TOLERANCE_S;
|
|
3340
|
+
}
|
|
3268
3341
|
async function resolveDeezerSearch(track) {
|
|
3269
3342
|
const artist = track.artists[0]?.trim();
|
|
3270
3343
|
if (!artist || !track.title.trim()) {
|
|
3271
3344
|
return;
|
|
3272
3345
|
}
|
|
3273
3346
|
try {
|
|
3274
|
-
const query = `artist:"${artist}" track:"${track.title.trim()}"`;
|
|
3347
|
+
const query = `artist:"${artist}" track:"${stripVersionSuffix(track.title.trim())}"`;
|
|
3275
3348
|
const response = await fetch(`https://api.deezer.com/search?q=${encodeURIComponent(query)}`);
|
|
3276
3349
|
const body = await response.json();
|
|
3277
|
-
const hit = (body.data ?? []).find((item) => item.preview);
|
|
3350
|
+
const hit = (body.data ?? []).find((item) => item.preview && versionMatches(track.title, item.title ?? "") && baseTitleMatches(track.title, item.title ?? "") && durationAgrees(track.durationMs, item.duration));
|
|
3278
3351
|
return downloadPreview(hit?.preview, "deezer:search");
|
|
3279
3352
|
} catch {
|
|
3280
3353
|
return;
|
|
@@ -3288,7 +3361,7 @@ async function resolveItunes(track) {
|
|
|
3288
3361
|
try {
|
|
3289
3362
|
const response = await fetch(`https://itunes.apple.com/search?term=${encodeURIComponent(`${artist} ${track.title}`)}&media=music&limit=10`);
|
|
3290
3363
|
const body = await response.json();
|
|
3291
|
-
const hit = (body.results ?? []).find((item) => item.previewUrl && normalize(item.artistName ?? "").includes(normalize(artist)));
|
|
3364
|
+
const hit = (body.results ?? []).find((item) => item.previewUrl && normalize(item.artistName ?? "").includes(normalize(artist)) && versionMatches(track.title, item.trackName ?? "") && baseTitleMatches(track.title, item.trackName ?? "") && durationAgrees(track.durationMs, item.trackTimeMillis ? item.trackTimeMillis / 1000 : undefined));
|
|
3292
3365
|
return downloadPreview(hit?.previewUrl, "itunes");
|
|
3293
3366
|
} catch {
|
|
3294
3367
|
return;
|
|
@@ -3350,8 +3423,10 @@ function extensionForMime(mime) {
|
|
|
3350
3423
|
function normalize(value) {
|
|
3351
3424
|
return value.toLowerCase().replace(/[^a-z0-9]/g, "");
|
|
3352
3425
|
}
|
|
3426
|
+
var DURATION_TOLERANCE_S = 5;
|
|
3353
3427
|
var init_preview_archive = __esm(() => {
|
|
3354
3428
|
init_api();
|
|
3429
|
+
init_version_match();
|
|
3355
3430
|
});
|
|
3356
3431
|
|
|
3357
3432
|
// src/commands/mixtape-youtube.ts
|
package/package.json
CHANGED