2020-12-21 12:52:48 +01:00
|
|
|
|
module.exports = function(tools) {
|
2020-12-01 20:16:51 +01:00
|
|
|
|
const config = require('../config')
|
2020-11-17 21:44:32 +01:00
|
|
|
|
const {spawn} = require('child_process')
|
|
|
|
|
const fs = require('fs')
|
|
|
|
|
this.downloadAndSave = (url, file_prefix = '', gifmp4, isYouTubeThumbnail) => {
|
2020-12-21 12:52:48 +01:00
|
|
|
|
/**
|
2020-11-17 21:44:32 +01:00
|
|
|
|
* This function downloads media (video or image) to disk.
|
|
|
|
|
* Returns a localized URL
|
2020-12-21 12:52:48 +01:00
|
|
|
|
*
|
2020-11-17 21:44:32 +01:00
|
|
|
|
* For example for images:
|
|
|
|
|
* https://external-preview.redd.it/DiaeK_j5fqpBqbatvo7GZzbHNJY2oxEym93B_3.jpg
|
|
|
|
|
* =>
|
|
|
|
|
* https://teddit.net/pics/DiaeK_j5fqpBqbatvo7GZzbHNJY2oxEym93B_3.jpg
|
|
|
|
|
*
|
|
|
|
|
* For videos:
|
|
|
|
|
* https://v.redd.it/f3lcdk4ydcl51/DASH_480.mp4?source=fallback
|
|
|
|
|
* =>
|
|
|
|
|
* https://teddit.net/vids/f3lcdk4ydcl51.mp4
|
|
|
|
|
*/
|
|
|
|
|
let valid_video_extensions = ['mp4', 'webm', 'ogg']
|
2020-11-28 17:37:18 +01:00
|
|
|
|
let invalid_urls = ['self', 'default', 'nsfw', 'image', 'spoiler', 'undefined', undefined, null, '']
|
2020-11-17 21:44:32 +01:00
|
|
|
|
return new Promise((resolve, reject) => {
|
|
|
|
|
if(!invalid_urls.includes(url)) {
|
|
|
|
|
(async () => {
|
|
|
|
|
let temp_url = new URL(url)
|
2020-12-01 20:16:51 +01:00
|
|
|
|
if(config.valid_media_domains.includes(temp_url.hostname)) {
|
2020-11-17 21:44:32 +01:00
|
|
|
|
let pathname = temp_url.pathname
|
|
|
|
|
let file_ext
|
|
|
|
|
let has_extension = true
|
2020-12-16 18:52:20 +01:00
|
|
|
|
let dir = ''
|
2020-11-17 21:44:32 +01:00
|
|
|
|
|
|
|
|
|
if(gifmp4) {
|
|
|
|
|
file_ext = 'mp4'
|
|
|
|
|
} else {
|
2020-12-21 12:52:48 +01:00
|
|
|
|
if (file_prefix === 'flair_') {
|
|
|
|
|
// Flair emojis end in the name without a file extension
|
|
|
|
|
file_ext = 'png'
|
|
|
|
|
} else if(!pathname.includes('.')) { /**
|
2020-11-17 21:44:32 +01:00
|
|
|
|
* Sometimes reddit API returns video without extension, like
|
|
|
|
|
* "DASH_480" and not "DASH_480.mp4".
|
|
|
|
|
*/
|
|
|
|
|
file_ext = 'mp4'
|
|
|
|
|
has_extension = false
|
2020-12-21 12:52:48 +01:00
|
|
|
|
} else {
|
2020-11-17 21:44:32 +01:00
|
|
|
|
file_ext = pathname.substring(pathname.lastIndexOf('.') + 1)
|
|
|
|
|
}
|
|
|
|
|
}
|
2020-12-21 12:52:48 +01:00
|
|
|
|
|
2020-12-16 18:52:20 +01:00
|
|
|
|
if(file_prefix === 'thumb_')
|
|
|
|
|
dir = 'thumbs/'
|
2020-12-21 12:52:48 +01:00
|
|
|
|
if(file_prefix === 'flair_')
|
2020-12-16 18:52:20 +01:00
|
|
|
|
dir = 'flairs/'
|
2020-11-17 21:44:32 +01:00
|
|
|
|
|
|
|
|
|
if(valid_video_extensions.includes(file_ext) || gifmp4) {
|
|
|
|
|
/* Is video. */
|
2020-12-01 20:16:51 +01:00
|
|
|
|
if(!config.video_enabled) {
|
2020-11-17 21:44:32 +01:00
|
|
|
|
resolve('')
|
|
|
|
|
} else {
|
|
|
|
|
let filename = `${temp_url.pathname.substr(1).split('/')[0]}.${file_ext}`
|
2020-12-25 22:14:24 +01:00
|
|
|
|
let path = `./static/vids/${dir}${filename}`
|
|
|
|
|
let temp_path = `./static/vids/${dir}temp_${filename}`
|
2020-11-17 21:44:32 +01:00
|
|
|
|
if(!fs.existsSync(path)) {
|
|
|
|
|
const download = await downloadFile(cleanUrl(url))
|
|
|
|
|
if(download.success === true) {
|
|
|
|
|
const write = await writeToDisk(download.data, temp_path)
|
|
|
|
|
if(write.success === true) {
|
|
|
|
|
let audio_url
|
|
|
|
|
if(has_extension) {
|
|
|
|
|
audio_url = `${url.split('_')[0]}_audio.mp4`
|
|
|
|
|
} else {
|
|
|
|
|
let ending = `${temp_url.pathname.split('/').slice(-1)[0]}`
|
|
|
|
|
audio_url = url.replace(ending, 'audio')
|
|
|
|
|
}
|
|
|
|
|
const download_audio = await downloadFile(cleanUrl(audio_url))
|
|
|
|
|
if(download_audio.success === true) {
|
2020-12-25 22:14:24 +01:00
|
|
|
|
let audio_path = `./static/vids/${dir}temp_audio_${filename}`
|
2020-11-17 21:44:32 +01:00
|
|
|
|
const write_audio = await writeToDisk(download_audio.data, audio_path)
|
|
|
|
|
if(write_audio.success === true) {
|
|
|
|
|
let processVideo = spawn('ffmpeg', ['-y', '-i', temp_path, '-i', audio_path, '-c', 'copy', path])
|
|
|
|
|
processVideo.on('exit', (code) => {
|
|
|
|
|
if(code === 0) {
|
2020-12-16 18:52:20 +01:00
|
|
|
|
let final_url = `/vids/${dir}${filename}`
|
2020-11-17 21:44:32 +01:00
|
|
|
|
let temp_files = [temp_path, audio_path]
|
|
|
|
|
deleteFiles(temp_files, (error) => {
|
|
|
|
|
if(error) {
|
|
|
|
|
console.log(`Error while deleting temporay files:`, error)
|
|
|
|
|
}
|
|
|
|
|
})
|
|
|
|
|
resolve(final_url)
|
|
|
|
|
} else {
|
|
|
|
|
console.log(`ffmpeg error, exited with code: `, code)
|
|
|
|
|
resolve('')
|
|
|
|
|
}
|
|
|
|
|
})
|
|
|
|
|
} else {
|
|
|
|
|
console.log(`Error while writing temp audio file.`)
|
|
|
|
|
resolve('')
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
/**
|
|
|
|
|
* Either the video doesn't have any audio track, or we
|
|
|
|
|
* failed downloading it. Let's return the video only.
|
|
|
|
|
*/
|
|
|
|
|
fs.rename(temp_path, path, (error) => {
|
|
|
|
|
if(error) {
|
|
|
|
|
console.log(`Error while renaming the temp video file: ${temp_path} => ${path}.`, error)
|
|
|
|
|
} else {
|
2020-12-16 18:52:20 +01:00
|
|
|
|
let final_url = `/vids/${dir}${filename}`
|
2020-11-17 21:44:32 +01:00
|
|
|
|
resolve(final_url)
|
|
|
|
|
}
|
|
|
|
|
})
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
console.log(`Error while writing video file.`)
|
|
|
|
|
resolve('')
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
console.log(`Error while downloading video file.`)
|
|
|
|
|
resolve('')
|
|
|
|
|
}
|
|
|
|
|
} else {
|
2020-12-16 18:52:20 +01:00
|
|
|
|
resolve(`/vids/${dir}${filename}`)
|
2020-11-17 21:44:32 +01:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
/* Is image. */
|
|
|
|
|
let path, youtubeThumbUrl, filename
|
|
|
|
|
if(isYouTubeThumbnail) {
|
|
|
|
|
filename = `${file_prefix}${temp_url.pathname.split('/').slice(-2)[0]}_hqdefault.jpg`
|
|
|
|
|
} else {
|
|
|
|
|
let width = ''
|
|
|
|
|
if(temp_url.searchParams.get('width')) {
|
|
|
|
|
width = temp_url.searchParams.get('width')
|
|
|
|
|
}
|
2020-12-21 12:52:48 +01:00
|
|
|
|
if(file_prefix === 'flair_') {
|
|
|
|
|
// Flair emojis have a full path of `UUID/name`,
|
|
|
|
|
// so we need to incorporate the UUID to avoid duplicates
|
|
|
|
|
// since names alone are not unique across all of reddit
|
|
|
|
|
filename = `${pathname.slice(1).replace('/', '_')}.png` // Only first replacement is fine
|
|
|
|
|
} else {
|
|
|
|
|
filename = `${file_prefix}w:${temp_url.searchParams.get('width')}_${temp_url.pathname.split('/').slice(-1)}`
|
|
|
|
|
}
|
2020-11-17 21:44:32 +01:00
|
|
|
|
}
|
2020-12-25 22:14:24 +01:00
|
|
|
|
path = `./static/pics/${dir}${filename}`
|
2020-11-17 21:44:32 +01:00
|
|
|
|
if(!fs.existsSync(path)) {
|
|
|
|
|
const download = await downloadFile(cleanUrl(url))
|
|
|
|
|
if(download.success === true) {
|
|
|
|
|
const write = await writeToDisk(download.data, path)
|
|
|
|
|
if(write.success === true) {
|
2020-12-16 18:52:20 +01:00
|
|
|
|
let final_url = `/pics/${dir}${filename}`
|
2020-11-17 21:44:32 +01:00
|
|
|
|
resolve(final_url)
|
|
|
|
|
} else {
|
|
|
|
|
console.log(`Error while writing image file.`, write)
|
|
|
|
|
resolve('')
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
console.log(`Error while downloading image file.`)
|
|
|
|
|
resolve('')
|
|
|
|
|
}
|
|
|
|
|
} else {
|
2020-12-16 18:52:20 +01:00
|
|
|
|
resolve(`/pics/${dir}${filename}`)
|
2020-11-17 21:44:32 +01:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
console.log(`Invalid URL for downloading media: ${temp_url.hostname}.`)
|
|
|
|
|
resolve('')
|
|
|
|
|
}
|
|
|
|
|
})()
|
|
|
|
|
} else {
|
|
|
|
|
resolve('self')
|
|
|
|
|
}
|
|
|
|
|
})
|
|
|
|
|
}
|
|
|
|
|
}
|