tphim 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/package.json +1 -1
- package/pro-terminal.mjs +72 -12
package/package.json
CHANGED
package/pro-terminal.mjs
CHANGED
|
@@ -41,6 +41,37 @@ function removeVietnameseTones(str) {
|
|
|
41
41
|
.trim();
|
|
42
42
|
}
|
|
43
43
|
|
|
44
|
+
function validateUrl(url) {
|
|
45
|
+
try {
|
|
46
|
+
new URL(url);
|
|
47
|
+
return true;
|
|
48
|
+
} catch {
|
|
49
|
+
return false;
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
function extractTitleFromUrl(url) {
|
|
54
|
+
const urlParts = url.split('/').filter(p => p && p !== 'http:' && p !== 'https:');
|
|
55
|
+
const lastPart = urlParts[urlParts.length - 1];
|
|
56
|
+
const secondLastPart = urlParts[urlParts.length - 2];
|
|
57
|
+
|
|
58
|
+
// Clean up parts
|
|
59
|
+
const cleanLast = lastPart?.replace(/\.(mp4|m3u8|mkv|avi|mov|flv|webm|html|htm)$/i, '').replace(/[_\-]/g, ' ').trim();
|
|
60
|
+
const cleanSecond = secondLastPart?.replace(/[_\-]/g, ' ').trim();
|
|
61
|
+
|
|
62
|
+
// Prefer second to last part (usually folder/slug structure)
|
|
63
|
+
if (cleanSecond && cleanSecond.length > 2 && !['index', 'master', 'video', 'movie', 'play'].includes(cleanSecond.toLowerCase())) {
|
|
64
|
+
return cleanSecond;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
// Fallback to last part
|
|
68
|
+
if (cleanLast && cleanLast.length > 2 && !['index', 'master', 'video', 'movie', 'play'].includes(cleanLast.toLowerCase())) {
|
|
69
|
+
return cleanLast;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
return `movie-${Date.now()}`;
|
|
73
|
+
}
|
|
74
|
+
|
|
44
75
|
function checkEnv() {
|
|
45
76
|
const required = [
|
|
46
77
|
'TEBI_ENDPOINT',
|
|
@@ -141,6 +172,15 @@ async function main() {
|
|
|
141
172
|
hint: chalk.yellow('Separate multiple links with COMMA (,)'),
|
|
142
173
|
validate: (value) => {
|
|
143
174
|
if (!value) return 'System requires a data source.';
|
|
175
|
+
|
|
176
|
+
const links = value.split(',').map(l => l.trim()).filter(l => l);
|
|
177
|
+
const invalidLinks = links.filter(link => !validateUrl(link));
|
|
178
|
+
|
|
179
|
+
if (invalidLinks.length > 0) {
|
|
180
|
+
return `Invalid URL(s): ${invalidLinks.join(', ')}`;
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
return undefined;
|
|
144
184
|
},
|
|
145
185
|
}),
|
|
146
186
|
title: () =>
|
|
@@ -192,20 +232,40 @@ async function main() {
|
|
|
192
232
|
try {
|
|
193
233
|
s.message('🛰️ Fetching metadata...');
|
|
194
234
|
const { execSync } = await import('child_process');
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
235
|
+
|
|
236
|
+
// Try multiple methods to get title
|
|
237
|
+
let fetchedTitle = '';
|
|
238
|
+
|
|
239
|
+
// Method 1: Try yt-dlp title
|
|
240
|
+
try {
|
|
241
|
+
fetchedTitle = execSync(
|
|
242
|
+
`yt-dlp --print title --skip-download "${inputUrl}"`,
|
|
243
|
+
{ encoding: 'utf-8', stdio: ['ignore', 'pipe', 'ignore'], timeout: 10000 }
|
|
244
|
+
).trim();
|
|
245
|
+
} catch (e1) {
|
|
246
|
+
// Method 2: Try yt-dlp with different flags
|
|
247
|
+
try {
|
|
248
|
+
fetchedTitle = execSync(
|
|
249
|
+
`yt-dlp --get-title --no-download "${inputUrl}"`,
|
|
250
|
+
{ encoding: 'utf-8', stdio: ['ignore', 'pipe', 'ignore'], timeout: 10000 }
|
|
251
|
+
).trim();
|
|
252
|
+
} catch (e2) {
|
|
253
|
+
// Method 3: Try generic approach
|
|
254
|
+
try {
|
|
255
|
+
const info = execSync(
|
|
256
|
+
`yt-dlp --dump-json --no-download "${inputUrl}"`,
|
|
257
|
+
{ encoding: 'utf-8', stdio: ['ignore', 'pipe', 'ignore'], timeout: 15000 }
|
|
258
|
+
);
|
|
259
|
+
const parsed = JSON.parse(info);
|
|
260
|
+
fetchedTitle = parsed.title || parsed.fulltitle || parsed.description?.split('\n')[0] || '';
|
|
261
|
+
} catch (e3) {
|
|
262
|
+
// Method 4: Extract from URL as last resort
|
|
263
|
+
fetchedTitle = extractTitleFromUrl(inputUrl);
|
|
264
|
+
}
|
|
265
|
+
}
|
|
206
266
|
}
|
|
207
267
|
|
|
208
|
-
currentTitle = fetchedTitle;
|
|
268
|
+
currentTitle = fetchedTitle || extractTitleFromUrl(inputUrl);
|
|
209
269
|
} catch (e) {
|
|
210
270
|
currentTitle = `movie-${Date.now()}`;
|
|
211
271
|
}
|