frostpv 1.0.12 → 1.0.14

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 (2) hide show
  1. package/index.js +62 -96
  2. package/package.json +1 -1
package/index.js CHANGED
@@ -4,7 +4,7 @@ const path = require("path");
4
4
  const os = require("os");
5
5
  const FormData = require("form-data");
6
6
  const crypto = require("crypto");
7
- const { igdl, ttdl, fbdown, mediafire, capcut, gdrive, pinterest } = require("btch-downloader");
7
+ const { igdl, ttdl, fbdown, mediafire, capcut, gdrive, pinterest, twitter } = require("btch-downloader");
8
8
  const { TwitterDL } = require("twitter-downloader");
9
9
  const btch = require("btch-downloader");
10
10
  const btchOld = require("btch-downloader-old");
@@ -47,6 +47,7 @@ const videoPlatforms = [
47
47
  "https://www.fb.watch",
48
48
  "https://fb.com",
49
49
  "https://www.fb.com",
50
+ "https://web.facebook.com",
50
51
  "https://www.mediafire.com",
51
52
  "https://mediafire.com",
52
53
  "https://www.capcut.com",
@@ -886,25 +887,16 @@ const MediaDownloader = async (url, options = {}) => {
886
887
  // Function to process downloaded file
887
888
  async function processDownloadedFile(fileName, config, platform = null) {
888
889
  let processedFile = path.resolve(fileName);
889
-
890
- // Check if file is video or image based on extension
891
- const ext = path.extname(processedFile).toLowerCase();
892
- const isVideo = ['.mp4', '.mov', '.webm', '.mkv'].includes(ext);
893
-
894
- // Only apply video processing if it is a video
895
- if (isVideo) {
896
- if (config.rotation) {
897
- processedFile = await rotateVideo(processedFile, config.rotation);
898
- }
899
- if (config.autocrop) {
900
- processedFile = await autoCrop(processedFile);
901
- }
902
- processedFile = await checkAndCompressVideo(processedFile, config.limitSizeMB, platform);
903
- if (config.outputFormat) {
904
- processedFile = await convertVideoFormat(processedFile, String(config.outputFormat).toLowerCase());
905
- }
890
+ if (config.rotation) {
891
+ processedFile = await rotateVideo(processedFile, config.rotation);
892
+ }
893
+ if (config.autocrop) {
894
+ processedFile = await autoCrop(processedFile);
895
+ }
896
+ processedFile = await checkAndCompressVideo(processedFile, config.limitSizeMB, platform);
897
+ if (config.outputFormat) {
898
+ processedFile = await convertVideoFormat(processedFile, String(config.outputFormat).toLowerCase());
906
899
  }
907
-
908
900
  return processedFile;
909
901
  }
910
902
 
@@ -1072,47 +1064,45 @@ async function downloadSmartVideo(url, config) {
1072
1064
  }
1073
1065
  case "twitter": {
1074
1066
  try {
1075
- // Validate and clean the Twitter URL
1076
- const cleanUrl = validateTwitterUrl(url);
1077
- const data = await TwitterDL(cleanUrl, {});
1078
-
1079
- if (data && data.result) {
1080
- // Try multiple possible response structures
1081
- if (data.result.media && data.result.media[0] &&
1082
- data.result.media[0].videos && data.result.media[0].videos[0] &&
1083
- data.result.media[0].videos[0].url) {
1084
- videoUrl = data.result.media[0].videos[0].url;
1085
- } else if (data.result.video && data.result.video[0] && data.result.video[0].url) {
1086
- videoUrl = data.result.video[0].url;
1087
- } else if (data.result.url) {
1088
- videoUrl = data.result.url;
1089
- } else if (data.result.media && data.result.media[0] && data.result.media[0].url) {
1090
- videoUrl = data.result.media[0].url;
1091
- } else {
1092
- // Search for any video URL in the response
1093
- const findVideoUrl = (obj) => {
1094
- if (typeof obj === 'string' && obj.includes('http') &&
1095
- (obj.includes('.mp4') || obj.includes('video') || obj.includes('media'))) {
1096
- return obj;
1097
- }
1098
- if (typeof obj === 'object' && obj !== null) {
1099
- for (const key in obj) {
1100
- const result = findVideoUrl(obj[key]);
1101
- if (result) return result;
1102
- }
1103
- }
1104
- return null;
1105
- };
1106
-
1107
- const foundUrl = findVideoUrl(data.result);
1108
- if (foundUrl) {
1109
- videoUrl = foundUrl;
1067
+ const data = await twitter(url);
1068
+ if (data && data.url) {
1069
+ // Se data.url for um array, procuramos por qualidade HD
1070
+ if (Array.isArray(data.url)) {
1071
+ // Tentar encontrar HD especificamente
1072
+ const hdVideo = data.url.find(v => v.hd);
1073
+ if (hdVideo) {
1074
+ videoUrl = hdVideo.hd;
1110
1075
  } else {
1111
- throw new Error("No video URL found in Twitter response structure");
1076
+ // Tentar encontrar por label ou qualidade
1077
+ const highQuality = data.url.find(v =>
1078
+ (v.quality && typeof v.quality === 'string' && v.quality.toUpperCase().includes('HD')) ||
1079
+ (v.label && typeof v.label === 'string' && v.label.toUpperCase().includes('HD'))
1080
+ );
1081
+
1082
+ if (highQuality) {
1083
+ videoUrl = highQuality.url;
1084
+ } else {
1085
+ // Fallback: pega o primeiro que tiver url
1086
+ const anyVideo = data.url.find(v => v.url);
1087
+ videoUrl = anyVideo ? anyVideo.url : data.url[0];
1088
+ }
1112
1089
  }
1090
+ } else if (typeof data.url === 'string') {
1091
+ videoUrl = data.url;
1113
1092
  }
1114
- } else {
1115
- throw new Error("Invalid Twitter response structure");
1093
+ }
1094
+
1095
+ if (!videoUrl) {
1096
+ // Fallback para estrutura antiga ou diferente
1097
+ if (Array.isArray(data) && data[0] && data[0].url) {
1098
+ videoUrl = data[0].url;
1099
+ } else if (data && data.HD) {
1100
+ videoUrl = data.HD;
1101
+ }
1102
+ }
1103
+
1104
+ if (!videoUrl) {
1105
+ throw new Error("No video URL found in btch-downloader twitter response");
1116
1106
  }
1117
1107
  } catch (error) {
1118
1108
  throw new Error(`Twitter download failed: ${error.message}`);
@@ -1127,7 +1117,7 @@ async function downloadSmartVideo(url, config) {
1127
1117
  throw new Error("Returned video URL is invalid or unavailable.");
1128
1118
  }
1129
1119
 
1130
- // Download the video/image with better error handling
1120
+ // Download the video with better error handling
1131
1121
  const response = await axios({
1132
1122
  url: videoUrl,
1133
1123
  method: "GET",
@@ -1138,35 +1128,23 @@ async function downloadSmartVideo(url, config) {
1138
1128
  }
1139
1129
  });
1140
1130
 
1141
- // Detect file type from content-type
1142
- const contentType = response.headers['content-type'] || 'video/mp4';
1143
- let ext = 'mp4'; // default
1144
-
1145
- if (contentType.includes('image/jpeg')) ext = 'jpg';
1146
- else if (contentType.includes('image/png')) ext = 'png';
1147
- else if (contentType.includes('image/webp')) ext = 'webp';
1148
- else if (contentType.includes('image/gif')) ext = 'gif';
1149
- else if (contentType.includes('video/webm')) ext = 'webm';
1150
- else if (contentType.includes('video/quicktime')) ext = 'mov';
1151
- else if (contentType.includes('video/x-matroska')) ext = 'mkv';
1152
-
1153
1131
  // Create minimal unique file name in output dir
1154
- let fileName = path.join(OUTPUT_DIR, `v_${uuidv4().slice(0, 4)}.${ext}`);
1132
+ let fileName = path.join(OUTPUT_DIR, `v_${uuidv4().slice(0, 4)}.mp4`);
1155
1133
 
1156
- const writer = fs.createWriteStream(fileName);
1157
- response.data.pipe(writer);
1134
+ const videoWriter = fs.createWriteStream(fileName);
1135
+ response.data.pipe(videoWriter);
1158
1136
 
1159
1137
  return new Promise((resolve, reject) => {
1160
- writer.on("finish", async () => {
1138
+ videoWriter.on("finish", async () => {
1161
1139
  try {
1162
1140
  const finalFilePath = await processDownloadedFile(fileName, config, platform);
1163
1141
  resolve(finalFilePath);
1164
1142
  } catch (error) {
1165
- reject(new Error(`Error processing downloaded file: ${error.message}`));
1143
+ reject(new Error(`Error processing downloaded video: ${error.message}`));
1166
1144
  }
1167
1145
  });
1168
- writer.on("error", (error) => {
1169
- reject(new Error(`Error saving file: ${error.message}`));
1146
+ videoWriter.on("error", (error) => {
1147
+ reject(new Error(`Error saving video: ${error.message}`));
1170
1148
  });
1171
1149
  });
1172
1150
  } catch (error) {
@@ -1187,35 +1165,23 @@ async function downloadDirectVideo(url, config) {
1187
1165
  }
1188
1166
  });
1189
1167
 
1190
- // Detect file type from content-type
1191
- const contentType = response.headers['content-type'] || 'video/mp4';
1192
- let ext = 'mp4'; // default
1193
-
1194
- if (contentType.includes('image/jpeg')) ext = 'jpg';
1195
- else if (contentType.includes('image/png')) ext = 'png';
1196
- else if (contentType.includes('image/webp')) ext = 'webp';
1197
- else if (contentType.includes('image/gif')) ext = 'gif';
1198
- else if (contentType.includes('video/webm')) ext = 'webm';
1199
- else if (contentType.includes('video/quicktime')) ext = 'mov';
1200
- else if (contentType.includes('video/x-matroska')) ext = 'mkv';
1201
-
1202
1168
  // Create minimal unique file name in output dir
1203
- let fileName = path.join(OUTPUT_DIR, `v_${uuidv4().slice(0, 4)}.${ext}`);
1169
+ let fileName = path.join(OUTPUT_DIR, `v_${uuidv4().slice(0, 4)}.mp4`);
1204
1170
 
1205
- const writer = fs.createWriteStream(fileName);
1206
- response.data.pipe(writer);
1171
+ const videoWriter = fs.createWriteStream(fileName);
1172
+ response.data.pipe(videoWriter);
1207
1173
 
1208
1174
  return new Promise((resolve, reject) => {
1209
- writer.on("finish", async () => {
1175
+ videoWriter.on("finish", async () => {
1210
1176
  try {
1211
1177
  const finalFilePath = await processDownloadedFile(fileName, config, "unknown");
1212
1178
  resolve(finalFilePath);
1213
1179
  } catch (error) {
1214
- reject(new Error(`Error processing downloaded file: ${error.message}`));
1180
+ reject(new Error(`Error processing downloaded video: ${error.message}`));
1215
1181
  }
1216
1182
  });
1217
- writer.on("error", (error) => {
1218
- reject(new Error(`Error saving file: ${error.message}`));
1183
+ videoWriter.on("error", (error) => {
1184
+ reject(new Error(`Error saving video: ${error.message}`));
1219
1185
  });
1220
1186
  });
1221
1187
  } catch (error) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "frostpv",
3
- "version": "1.0.12",
3
+ "version": "1.0.14",
4
4
  "description": "downloads",
5
5
  "main": "index.js",
6
6
  "scripts": {