Skip to content

Commit

Permalink
Encoder now supports download from FTP URLs
Browse files Browse the repository at this point in the history
  • Loading branch information
Daniel Neto committed Jan 29, 2025
1 parent 7e9eb3e commit 8e32981
Show file tree
Hide file tree
Showing 5 changed files with 177 additions and 63 deletions.
55 changes: 32 additions & 23 deletions objects/Encoder.php
Original file line number Diff line number Diff line change
Expand Up @@ -682,7 +682,7 @@ public static function downloadFile($queue_id)
return $obj;
}

if (file_exists($obj->pathFileName)) {
if (file_exists($obj->pathFileName) && filesize($obj->pathFileName) > 20) {
if ($q->getStatus() == 'queue') {
self::setDownloaded($queue_id, $obj->pathFileName);
}
Expand All @@ -708,25 +708,34 @@ public static function downloadFile($queue_id)

if (!empty($q->getVideoDownloadedLink())) {
$videoURL = $q->getVideoDownloadedLink();
$downloadWithPytubeFilename = '';
if (self::isPythonAndPytubeInstalled() && isYouTubeUrl($videoURL)) {
$downloadWithPytubeFilename = 'video_download_' . $queue_id;
$response = self::downloadWithPytube($videoURL, $downloadWithPytubeFilename);
}
if(empty($downloadWithPytubeFilename) || $response->error){
//begin youtube-dl downloading and symlink it to the video temp file
$response = static::getYoutubeDl($videoURL, $queue_id, $obj->pathFileName);
if (!empty($response)) {
_error_log("downloadFile:getYoutubeDl SUCCESS queue_id = {$queue_id}");
$obj->pathFileName = $response;
$obj->error = false;
} else {
_error_log("downloadFile:getYoutubeDl ERROR queue_id = {$queue_id}");
$obj->error = false;
}

if(isFTPURL($videoURL)){
require_once __DIR__ . '/FTPDownloader.php';
FTPDownloader::copy($videoURL, $obj->pathFileName);
$obj->error = !file_exists($obj->pathFileName);
}else{
$obj->pathFileName = "{$global['systemRootPath']}videos/pytube/{$downloadWithPytubeFilename}/video.mp4";

$downloadWithPytubeFilename = '';
if (self::isPythonAndPytubeInstalled() && isYouTubeUrl($videoURL)) {
$downloadWithPytubeFilename = 'video_download_' . $queue_id;
$response = self::downloadWithPytube($videoURL, $downloadWithPytubeFilename);
}
if(empty($downloadWithPytubeFilename) || $response->error){
//begin youtube-dl downloading and symlink it to the video temp file
$response = static::getYoutubeDl($videoURL, $queue_id, $obj->pathFileName);
if (!empty($response)) {
_error_log("downloadFile:getYoutubeDl SUCCESS queue_id = {$queue_id}");
$obj->pathFileName = $response;
$obj->error = false;
} else {
_error_log("downloadFile:getYoutubeDl ERROR queue_id = {$queue_id}");
$obj->error = false;
}
}else{
$obj->pathFileName = "{$global['systemRootPath']}videos/pytube/{$downloadWithPytubeFilename}/video.mp4";
}
}

} else {
_error_log("downloadFile: not using getYoutubeDl");
//symlink the downloaded file to the video temp file ($obj-pathFileName)
Expand Down Expand Up @@ -980,9 +989,9 @@ public static function getQueue($status = array(), $streamers_id = 0)
$sql .= " AND streamers_id = {$streamers_id} ";
}

$sql .= " ORDER BY
CASE WHEN priority IS NULL THEN 1 ELSE 0 END ASC,
priority ASC,
$sql .= " ORDER BY
CASE WHEN priority IS NULL THEN 1 ELSE 0 END ASC,
priority ASC,
e.id ASC ";
//var_dump($sql);
/**
Expand Down Expand Up @@ -2794,7 +2803,7 @@ public static function getTitleFromLink($link, $streamers_id, $addOauthFromProvi
if (!isWindows()) {
$prepend = 'LC_ALL=en_US.UTF-8 ';
}

$link = str_replace("'", '', $link);
$link = escapeshellarg($link);
$response = array('error' => true, 'output' => '');
Expand Down Expand Up @@ -2896,7 +2905,7 @@ public static function getDescriptionFromLink($link, $streamers_id, $addOauthFro
if (empty($link)) {
return '';
}

if (self::isPythonAndPytubeInstalled() && isYouTubeUrl($link)) {
$resp = self::getDescriptionFromLinkWithPytube($link);
if(!empty($resp)){
Expand Down
84 changes: 84 additions & 0 deletions objects/FTPDownloader.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
<?php

class FTPDownloader
{
private $ftpUrl;
private $ftpHost;
private $ftpUser;
private $ftpPass;
private $ftpPort;
private $ftpConn;
private $remotePath = '/';

public function __construct($ftpUrl)
{
global $global;
$this->ftpUrl = addLastSlash($ftpUrl);
$this->parseFtpUrl($ftpUrl);
}

private function parseFtpUrl($ftpUrl)
{
$parsedUrl = parse_url($ftpUrl);
if (!$parsedUrl || !isset($parsedUrl['scheme']) || $parsedUrl['scheme'] !== 'ftp') {
throw new Exception("Invalid FTP URL");
}

$this->ftpHost = $parsedUrl['host'] ?? '';
$this->ftpUser = $parsedUrl['user'] ?? 'anonymous';
$this->ftpPass = $parsedUrl['pass'] ?? '';
$this->ftpPort = $parsedUrl['port'] ?? 21;
$this->remotePath = $parsedUrl['path'] ?? '/';
}

public function connect()
{
$this->ftpConn = ftp_connect($this->ftpHost, $this->ftpPort);
if (!$this->ftpConn) {
throw new Exception("Could not connect to FTP server");
}

if (!ftp_login($this->ftpConn, $this->ftpUser, $this->ftpPass)) {
throw new Exception("Could not log in to FTP server");
}

ftp_pasv($this->ftpConn, true); // Enable passive mode
}

public function queueFiles()
{
$files = ftp_nlist($this->ftpConn, $this->remotePath);
if ($files === false) {
throw new Exception("Could not list files in directory");
}

foreach ($files as $file) {
if (preg_match('/\.(mp4|mp3)$/i', $file)) {
$basename = basename($file);
$link = "{$this->ftpUrl}{$basename}";
addVideo($link, Login::getStreamerId(), $basename);
}
}
}

static function copy($ftpUrl, $savePath)
{
_error_log("FTP copy($ftpUrl, $savePath)");

$savePath = str_replace('..', '', $savePath);

$command = "wget -O \"$savePath\" \"$ftpUrl\" ";

exec($command);

return file_exists($savePath) && filesize($savePath) > 20;
}


public function close()
{
if ($this->ftpConn) {
ftp_close($this->ftpConn);
}
}
}
6 changes: 5 additions & 1 deletion objects/functions.php
Original file line number Diff line number Diff line change
Expand Up @@ -1432,6 +1432,10 @@ function _error_log($message)
error_log($str);
}

function isFTPURL($url){
return preg_match('/^ftps?:/i', $url);
}

function addVideo($link, $streamers_id, $title = "") {
$obj = new stdClass();
// remove list parameter from
Expand Down Expand Up @@ -1599,7 +1603,7 @@ function addQueryStringParameter($url, $varname, $value)
parse_str($parsedUrl['query'], $query);
}
$query[$varname] = $value;

// Ensure 'current' is the last parameter
$currentValue = null;
if (isset($query['current'])) {
Expand Down
2 changes: 1 addition & 1 deletion objects/security.php
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@

foreach ($filterURL as $key => $value) {
if (!empty($scanThis[$value])) {
if (!filter_var($scanThis[$value], FILTER_VALIDATE_URL) || !preg_match("/^http.*/i", $scanThis[$value])) {
if (!filter_var($scanThis[$value], FILTER_VALIDATE_URL) || !preg_match("/^(http|ftp).*/i", $scanThis[$value])) {
//_error_log($value.' attack ' . json_encode($_SERVER), AVideoLog::$SECURITY);
unset($scanThis[$value]);
} else {
Expand Down
93 changes: 55 additions & 38 deletions view/youtubeDl.json.php
Original file line number Diff line number Diff line change
Expand Up @@ -10,51 +10,68 @@

session_write_close();

if (!empty($_REQUEST['webSiteRootURL']) && !empty($_REQUEST['user']) && !empty($_REQUEST['pass']) && empty($_REQUEST['justLogin'])) {
error_log("youtubeDl.json: Login::run");
Login::run($_REQUEST['user'], $_REQUEST['pass'], $_REQUEST['webSiteRootURL'], true);
}

if (!Login::canUpload()) {
$obj->msg = "This user can not upload files";
if (empty($_REQUEST['videoURL'])) {
$obj->msg = "videoURL is empty";
} else {
if (!($streamers_id = Login::getStreamerId())) {
$obj->msg = "There is no streamer site";
if (!empty($_REQUEST['webSiteRootURL']) && !empty($_REQUEST['user']) && !empty($_REQUEST['pass']) && empty($_REQUEST['justLogin'])) {
error_log("youtubeDl.json: Login::run");
Login::run($_REQUEST['user'], $_REQUEST['pass'], $_REQUEST['webSiteRootURL'], true);
}

if (!Login::canUpload()) {
$obj->msg = "This user can not upload files";
} else {
// if it is a channel
$rexexp = "/^(http(s)?:\/\/)?((w){3}.)?youtu(be|.be)?(\.com)?\/(channel|user).+/";
if (preg_match($rexexp, $_REQUEST['videoURL'])) {
if (!Login::canBulkEncode()) {
$obj->msg = "Channel Import is disabled";
die(json_encode($obj));
}
$start = 0;
$end = 100;
if (!empty($_REQUEST['startIndex'])) {
$start = $current = intval($_REQUEST['startIndex']);
}
if (!empty($_REQUEST['endIndex'])) {
$end = intval($_REQUEST['endIndex']);
}
error_log("Processing Channel {$start} to {$end}");
$list = Encoder::getReverseVideosJsonListFromLink($_REQUEST['videoURL'], Login::getStreamerId());
$i = $start;
for (; $i <= $end; $i++) {
if (is_object($list[$i]) && empty($list[$i]->id)) {
error_log(($i) . " Not Object " . print_r($list[$i], true));
continue;
if (!($streamers_id = Login::getStreamerId())) {
$obj->msg = "There is no streamer site";
} else {
// if it is a channel
$rexexp = "/^(http(s)?:\/\/)?((w){3}.)?youtu(be|.be)?(\.com)?\/(channel|user).+/";
if (preg_match($rexexp, $_REQUEST['videoURL'])) {
if (!Login::canBulkEncode()) {
$obj->msg = "Channel Import is disabled";
die(json_encode($obj));
}
$start = 0;
$end = 100;
if (!empty($_REQUEST['startIndex'])) {
$start = $current = intval($_REQUEST['startIndex']);
}
if (!empty($_REQUEST['endIndex'])) {
$end = intval($_REQUEST['endIndex']);
}
error_log("Processing Channel {$start} to {$end}");
$list = Encoder::getReverseVideosJsonListFromLink($_REQUEST['videoURL'], Login::getStreamerId());
$i = $start;
for (; $i <= $end; $i++) {
if (is_object($list[$i]) && empty($list[$i]->id)) {
error_log(($i) . " Not Object " . print_r($list[$i], true));
continue;
}
error_log(($i) . " Process Video {$list[$i]->id}");
$url = "https://www.youtube.com/watch?v={$list[$i]->url}";
$obj = addVideo($url, $streamers_id, $list[$i]->title);
}
error_log("Process Done Total {$i}");
} else {
if (isFTPURL($_REQUEST['videoURL'])) {
require_once __DIR__ . '/../objects/FTPDownloader.php';
try {
$downloader = new FTPDownloader($_REQUEST['videoURL']);
$downloader->connect();
$downloader->queueFiles();
$downloader->close();
} catch (Exception $e) {
echo "Error: " . $e->getMessage() . "\n";
}
} else {
$obj = addVideo($_REQUEST['videoURL'], $streamers_id, @$_REQUEST['videoTitle']);
}
error_log(($i) . " Process Video {$list[$i]->id}");
$url = "https://www.youtube.com/watch?v={$list[$i]->url}";
$obj = addVideo($url, $streamers_id, $list[$i]->title);
}
error_log("Process Done Total {$i}");
} else {
$obj = addVideo($_REQUEST['videoURL'], $streamers_id, @$_REQUEST['videoTitle']);
}
}
}
if(empty($doNotDie)){

if (empty($doNotDie)) {
echo (json_encode($obj));
exit;
}

0 comments on commit 8e32981

Please sign in to comment.