-
Notifications
You must be signed in to change notification settings - Fork 65
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
[Feature] download all photos/video of user
- Loading branch information
1 parent
5e7089f
commit 5cd9806
Showing
5 changed files
with
250 additions
and
5 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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"; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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() | ||
); | ||
} | ||
} | ||
}, | ||
}); | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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() | ||
); | ||
} | ||
} | ||
}, | ||
}); | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters