Skip to content

Commit

Permalink
[Feature] download all photos/video of user
Browse files Browse the repository at this point in the history
  • Loading branch information
HoangTran0410 committed Mar 26, 2022
1 parent 5e7089f commit 5cd9806
Show file tree
Hide file tree
Showing 5 changed files with 250 additions and 5 deletions.
4 changes: 3 additions & 1 deletion config.js
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
// you can modify all the variables below
export const ACCESS_TOKEN = "YOUR_ACCESS_TOKEN";
export const WAIT_BEFORE_NEXT_FETCH = 0; // thời gian chờ (ms) trước mỗi lần fetch tiếp theo
export const WAIT_BEFORE_NEXT_FETCH_LARGEST_PHOTO = 200; // thời gian chờ (ms) trước khi tải ảnh có độ phân giải lớn. Nếu chờ ít thì rất dễ bị facebook ban
export const WAIT_BEFORE_NEXT_FETCH_LARGEST_PHOTO = 200; // thời gian chờ (ms) trước khi tải ảnh có độ phân giải lớn. Nếu chờ ít thì rất dễ bị facebook ban
export const ID_LINK_SEPERATOR = ";";
export const PHOTO_FILE_FORMAT = "png"; // OR jpg
export const VIDEO_FILE_FORMAT = "mp4"; // OR wav ?
export const FOLDER_TO_SAVE_LINKS = "downloads/links";
export const FOLDER_TO_SAVE_ALBUM_MEDIA = "downloads/album_media";
export const FOLDER_TO_SAVE_FEED_MEDIA = "downloads/feed_media";
export const FOLDER_TO_SAVE_USER_VIDEOS = "downloads/user_videos";
export const FOLDER_TO_SAVE_USER_PHOTOS = "downloads/user_photos";
92 changes: 92 additions & 0 deletions scripts/download_user_photos.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
import {
ACCESS_TOKEN,
FOLDER_TO_SAVE_USER_PHOTOS,
PHOTO_FILE_FORMAT,
WAIT_BEFORE_NEXT_FETCH,
} from "../config.js";
import { FB_API_HOST, S } from "./constants.js";
import { createIfNotExistDir, download, myFetch, sleep } from "./utils.js";

const fetchUserPhotos = async ({
targetId,
pageLimit = Infinity,
fromCursor,
pageFetchedCallback = () => {},
}) => {
const all_photos = [];
let page = 1;
let url = `${FB_API_HOST}/${targetId}/photos?type=uploaded&fields=largest_image,name,album&access_token=${ACCESS_TOKEN}`;

if (fromCursor) {
url += "&after=" + fromCursor;
}

while (url && page <= pageLimit) {
console.log(`ĐANG TẢI TRANG ${page}...`);
const fetchData = await myFetch(url);
page++;

if (!fetchData?.data) break;

const photos = fetchData.data;
all_photos.push(...photos);
console.log(
`> TÌM THẤY ${photos.length} ảnh. (TỔNG: ${all_photos.length})`
);
console.log(` > ID trang hiện tại: ${fetchData.paging?.cursors?.before}`);
console.log(` > ID trang sau: ${fetchData.paging?.cursors?.after}\n`);

// callback when each page fetched
await pageFetchedCallback(photos);

// get next paging
url = fetchData?.paging?.next;

// wait for next fetch - if needed
if (WAIT_BEFORE_NEXT_FETCH) {
console.log(`ĐANG TẠM DỪNG ${WAIT_BEFORE_NEXT_FETCH}ms...`);
await sleep(WAIT_BEFORE_NEXT_FETCH);
}
}

return all_photos;
};

export const downloadUserPhotos = async ({
targetId,
fromCursor,
pageLimit = Infinity,
}) => {
console.log(`ĐANG TẢI ẢNH CỦA USER ${targetId}...`);
let saved = 0;

await fetchUserPhotos({
targetId,
fromCursor,
pageLimit,
pageFetchedCallback: async (photos) => {
// create dir if not exist
const dir = `${FOLDER_TO_SAVE_USER_PHOTOS}/${targetId}`;
createIfNotExistDir(dir);

// save all videos to directory
for (let data of photos) {
const { largest_image, name, album, id } = data;
const savePath = `${dir}/${id}.${PHOTO_FILE_FORMAT}`;

try {
const moreInfo = `[${album?.name}] [${name || ""}]`;

console.log(`Đang lưu ${saved}: ${savePath}... ${moreInfo}`);
await download(largest_image.source, savePath);
saved++;
} catch (e) {
console.log(
S.BgRed + `[!] LỖI khi tải ${savePath}` + S.Reset,
e.toString()
);
}
}
},
});
};
104 changes: 104 additions & 0 deletions scripts/download_user_videos.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
import {
ACCESS_TOKEN,
FOLDER_TO_SAVE_USER_VIDEOS,
VIDEO_FILE_FORMAT,
WAIT_BEFORE_NEXT_FETCH,
} from "../config.js";
import { FB_API_HOST, S } from "./constants.js";
import { createIfNotExistDir, download, myFetch, sleep } from "./utils.js";

const fetchUserVideos = async ({
targetId,
pageLimit = Infinity,
fromCursor,
pageFetchedCallback = () => {},
}) => {
const all_videos = [];
let page = 1;
let url = `${FB_API_HOST}/${targetId}/videos?type=uploaded&fields=source,download_hd_url,download_sd_url,length,description,has_hd_quality&access_token=${ACCESS_TOKEN}`;

if (fromCursor) {
url += "&after=" + fromCursor;
}

while (url && page <= pageLimit) {
console.log(`ĐANG TẢI TRANG ${page}...`);
const fetchData = await myFetch(url);
page++;

if (!fetchData?.data) break;

const videos = fetchData.data;
all_videos.push(...videos);
console.log(
`> TÌM THẤY ${videos.length} videos. (TỔNG: ${all_videos.length})`
);
console.log(` > ID trang hiện tại: ${fetchData.paging?.cursors?.before}`);
console.log(` > ID trang sau: ${fetchData.paging?.cursors?.after}\n`);

// callback when each page fetched
await pageFetchedCallback(videos);

// get next paging
url = fetchData?.paging?.next;

// wait for next fetch - if needed
if (WAIT_BEFORE_NEXT_FETCH) {
console.log(`ĐANG TẠM DỪNG ${WAIT_BEFORE_NEXT_FETCH}ms...`);
await sleep(WAIT_BEFORE_NEXT_FETCH);
}
}

return all_videos;
};

export const downloadUserVideos = async ({
targetId,
fromCursor,
pageLimit = Infinity,
}) => {
console.log(`ĐANG TẢI VIDEOS CỦA USER ${targetId}...`);
let saved = 0;

await fetchUserVideos({
targetId,
fromCursor,
pageLimit,
pageFetchedCallback: async (videos) => {
// create dir if not exist
const dir = `${FOLDER_TO_SAVE_USER_VIDEOS}/${targetId}`;
createIfNotExistDir(dir);

// save all videos to directory
for (let data of videos) {
const {
source,
download_hd_url,
download_sd_url,
id,
length,
description,
has_hd_quality,
} = data;
const url = download_hd_url || source || download_sd_url;
const savePath = `${dir}/${id}.${VIDEO_FILE_FORMAT}`;

try {
const moreInfo =
(has_hd_quality ? "[HD]" : "[sd]") +
` [${~~length}s]` +
(description ? ` [${description}]` : "");

console.log(`Đang lưu ${saved}: ${savePath}... ${moreInfo}`);
await download(url, savePath);
saved++;
} catch (e) {
console.log(
S.BgRed + `[!] LỖI khi tải ${savePath}` + S.Reset,
e.toString()
);
}
}
},
});
};
53 changes: 50 additions & 3 deletions scripts/menu.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ import {
fetchAlbumInfo,
} from "./download_album.js";
import { fetchTimeLineAlbumId_FBPage } from "./download_timeline_album.js";
import { downloadUserPhotos } from "./download_user_photos.js";
import { downloadUserVideos } from "./download_user_videos.js";
import {
downloadWallMedia,
downloadWallMediaLinks,
Expand Down Expand Up @@ -141,15 +143,57 @@ const menuDownloadWallMedia = async () => {
}
};

const menuDownloadPhotoVideoOfUser = async () => {
while (true) {
const action = await choose(
"FB Media Downloader Tool > Tải toàn bộ ảnh/video của user",
{
0: "<- Quay lại",
1: "Tải toàn bộ Ảnh được đăng bởi user",
2: "Tải toàn bộ Video được đăng bởi user",
}
);

if (action.key == 0) break;
if (action.key == 1 || action.key == 2) {
const target_id = await prompt(
"> Nhập id của user (Nhập -1 để quay lại): "
);
if (target_id != -1) {
const from_cursor = await prompt(
"> Tải từ trang nào (Nhập id trang. Nhập 0 để tải từ trang đầu): "
);
const page_limit = await prompt(
"> Tải bao nhiêu trang (Nhập 0 để tải tới khi hết): "
);
if (page_limit >= 0) {
action.key == 1
? await downloadUserPhotos({
targetId: target_id,
fromCursor: from_cursor == 0 ? null : from_cursor,
pageLimit: page_limit == 0 ? Infinity : page_limit,
})
: await downloadUserVideos({
targetId: target_id,
fromCursor: from_cursor == 0 ? null : from_cursor,
pageLimit: page_limit == 0 ? Infinity : page_limit,
});
}
}
}
}
};

export const menu = async () => {
while (true) {
const action = await choose("FB Media Downloader Tool", {
1: "Xem thông tin album",
2: "Tìm timeline album id của page",
3: "Tải album (của user/page/group)",
4: "Tải ảnh/video trên tường của đối tượng (user/group/page)",
5: "Hỗ trợ",
6: "Thoát",
5: "Tải toàn bộ ảnh/video của user",
6: "Hỗ trợ",
7: "Thoát",
});
if (action.key == 1) {
const album_id = await prompt("> Nhập album id (Nhập -1 để quay lại): ");
Expand Down Expand Up @@ -178,12 +222,15 @@ export const menu = async () => {
await menuDownloadWallMedia();
}
if (action.key == 5) {
await menuDownloadPhotoVideoOfUser();
}
if (action.key == 6) {
console.log(
"---- Liên hệ mình để được hỗ trợ: https://www.facebook.com/99.hoangtran/ ----"
);
await wait_for_key_pressed();
}
if (action.key == 6) break;
if (action.key == 7) break;
}

rl.close();
Expand Down
2 changes: 1 addition & 1 deletion scripts/utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ export const download = (url, destination) =>
});
})
.on("error", (error) => {
unlink(destination);
fs.unlinkSync(destination);
reject(error.message);
});
});

0 comments on commit 5cd9806

Please sign in to comment.