mirror of
https://github.com/DanielnetoDotCom/YouPHPTube
synced 2025-10-06 03:50:04 +02:00
This commit is contained in:
parent
d14af6c6c9
commit
e562f6ff91
2 changed files with 197 additions and 233 deletions
78
plugin/BulkEmbed/search.json.php
Normal file
78
plugin/BulkEmbed/search.json.php
Normal file
|
@ -0,0 +1,78 @@
|
||||||
|
<?php
|
||||||
|
require_once '../../videos/configuration.php';
|
||||||
|
header('Content-Type: application/json');
|
||||||
|
|
||||||
|
if (!User::isLogged()) {
|
||||||
|
die(json_encode(['error' => 'You must be logged in to search']));
|
||||||
|
}
|
||||||
|
|
||||||
|
$query = $_POST['query'] ?? '';
|
||||||
|
$pageToken = $_POST['pageToken'] ?? '';
|
||||||
|
|
||||||
|
if (empty($query)) {
|
||||||
|
die(json_encode(['error' => 'Search query cannot be empty']));
|
||||||
|
}
|
||||||
|
|
||||||
|
$obj = AVideoPlugin::getObjectData("BulkEmbed");
|
||||||
|
$apiKey = $obj->API_KEY;
|
||||||
|
|
||||||
|
// Construct the YouTube API URL with pagination (if pageToken is provided)
|
||||||
|
$youtubeApiUrl = "https://www.googleapis.com/youtube/v3/search?part=snippet&q=" . urlencode($query) . "&type=video&maxResults=50&videoEmbeddable=true&key=" . $apiKey;
|
||||||
|
|
||||||
|
if (!empty($pageToken)) {
|
||||||
|
$youtubeApiUrl .= "&pageToken=" . $pageToken;
|
||||||
|
}
|
||||||
|
|
||||||
|
$response = file_get_contents($youtubeApiUrl);
|
||||||
|
$responseData = json_decode($response, true);
|
||||||
|
|
||||||
|
if (empty($responseData) || !isset($responseData['items'])) {
|
||||||
|
die(json_encode(['error' => 'Failed to retrieve data from YouTube']));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Prepare the result array to include the embedding status
|
||||||
|
$results = [];
|
||||||
|
|
||||||
|
foreach ($responseData['items'] as $item) {
|
||||||
|
if (!isset($item['id']['videoId'])) {
|
||||||
|
continue; // Skip if videoId is not present
|
||||||
|
}
|
||||||
|
|
||||||
|
$videoId = $item['id']['videoId'];
|
||||||
|
$link = "https://youtube.com/embed/" . $videoId;
|
||||||
|
|
||||||
|
// Check if the video is already embedded in the database
|
||||||
|
$isEmbedded = false;
|
||||||
|
$embeddedVideoId = null;
|
||||||
|
|
||||||
|
$sql = "SELECT id, videoLink FROM `videos` WHERE `videoLink` = ? LIMIT 1";
|
||||||
|
$res = sqlDAL::readSql($sql, "s", [$link]);
|
||||||
|
$data = sqlDAL::fetchAssoc($res);
|
||||||
|
sqlDAL::close($res);
|
||||||
|
|
||||||
|
if (!empty($data['id'])) {
|
||||||
|
$isEmbedded = true;
|
||||||
|
$embeddedVideos_Id = $data['id']; // Capture the videoId when already embedded
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add item data to results
|
||||||
|
$results[] = [
|
||||||
|
'link' => $link,
|
||||||
|
'videoId' => $videoId,
|
||||||
|
'title' => $item['snippet']['title'],
|
||||||
|
'description' => $item['snippet']['description'],
|
||||||
|
'thumbs' => $item['snippet']['thumbnails']['high']['url'],
|
||||||
|
'date' => $item['snippet']['publishedAt'],
|
||||||
|
'isEmbedded' => $isEmbedded,
|
||||||
|
'embeddedVideos_Id' => $embeddedVideos_Id // Add embedded videoId if embedded
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
// Return the data and pagination tokens to the client
|
||||||
|
die(json_encode([
|
||||||
|
'data' => [
|
||||||
|
'items' => $results,
|
||||||
|
'nextPageToken' => $responseData['nextPageToken'] ?? null,
|
||||||
|
'prevPageToken' => $responseData['prevPageToken'] ?? null
|
||||||
|
]
|
||||||
|
]));
|
|
@ -95,7 +95,7 @@ $_page = new Page(array('Search'));
|
||||||
|
|
||||||
<div class="panel panel-default">
|
<div class="panel panel-default">
|
||||||
<div class="panel-heading">
|
<div class="panel-heading">
|
||||||
<form id="search-form" name="search-form" onsubmit="return search()">
|
<form id="search-form" name="search-form">
|
||||||
<div id="custom-search-input">
|
<div id="custom-search-input">
|
||||||
<div class="input-group col-md-12">
|
<div class="input-group col-md-12">
|
||||||
<input type="search" id="query" class="form-control input-lg" placeholder="Search YouTube / PlayList URL" />
|
<input type="search" id="query" class="form-control input-lg" placeholder="Search YouTube / PlayList URL" />
|
||||||
|
@ -124,23 +124,24 @@ $_page = new Page(array('Search'));
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<script>
|
<script>
|
||||||
var gapikey = '<?php echo $obj->API_KEY; ?>';
|
|
||||||
var playListName = '';
|
var playListName = '';
|
||||||
|
|
||||||
$(function() {
|
$(function() {
|
||||||
$('#search-form').submit(function(e) {
|
$('#search-form').submit(function(e) {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
|
search(); // Call the new search function
|
||||||
});
|
});
|
||||||
|
|
||||||
$('#getAll').click(function() {
|
$('#getAll').click(function() {
|
||||||
var videoLink = new Array();
|
var videoLink = [];
|
||||||
$("input:checkbox[name=videoCheckbox]").each(function() {
|
$("input:checkbox[name=videoCheckbox]").each(function() {
|
||||||
videoLink.push($(this).val());
|
videoLink.push($(this).val());
|
||||||
});
|
});
|
||||||
saveIt(videoLink);
|
saveIt(videoLink);
|
||||||
});
|
});
|
||||||
|
|
||||||
$('#getSelected').click(function() {
|
$('#getSelected').click(function() {
|
||||||
var videoLink = new Array();
|
var videoLink = [];
|
||||||
$("input:checkbox[name=videoCheckbox]:checked").each(function() {
|
$("input:checkbox[name=videoCheckbox]:checked").each(function() {
|
||||||
videoLink.push($(this).val());
|
videoLink.push($(this).val());
|
||||||
});
|
});
|
||||||
|
@ -148,49 +149,6 @@ $_page = new Page(array('Search'));
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
function saveIt(videoLink) {
|
|
||||||
modal.showPleaseWait();
|
|
||||||
setTimeout(function() {
|
|
||||||
var itemsToSave = [];
|
|
||||||
for (x in videoLink) {
|
|
||||||
if (typeof videoLink[x] === 'function') {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
$.ajax({
|
|
||||||
url: "https://www.googleapis.com/youtube/v3/videos?id=" + videoLink[x] + "&part=id,snippet,contentDetails&key=" + gapikey,
|
|
||||||
async: false,
|
|
||||||
success: function(data) {
|
|
||||||
var item = {};
|
|
||||||
item.link = "https://youtube.com/embed/" + data.items[0].id;
|
|
||||||
item.title = data.items[0].snippet.title;
|
|
||||||
item.description = data.items[0].snippet.description;
|
|
||||||
item.duration = data.items[0].contentDetails.duration;
|
|
||||||
item.thumbs = data.items[0].snippet.thumbnails.high.url;
|
|
||||||
item.date = data.items[0].snippet.publishedAt;
|
|
||||||
console.log(data.items[0].snippet, item);
|
|
||||||
itemsToSave.push(item);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
$.ajax({
|
|
||||||
url: webSiteRootURL + 'plugin/BulkEmbed/save.json.php',
|
|
||||||
data: {
|
|
||||||
"itemsToSave": itemsToSave,
|
|
||||||
playListName: playListName
|
|
||||||
},
|
|
||||||
type: 'post',
|
|
||||||
success: function(response) {
|
|
||||||
if (!response.error) {
|
|
||||||
avideoAlertSuccess(__("Your videos have been saved!"));
|
|
||||||
} else {
|
|
||||||
avideoAlertError(response.msg.join("<br>"));
|
|
||||||
}
|
|
||||||
modal.hidePleaseWait();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}, 500);
|
|
||||||
}
|
|
||||||
|
|
||||||
function validURL(str) {
|
function validURL(str) {
|
||||||
var pattern = new RegExp('^(https?:\\/\\/)?' + // protocol
|
var pattern = new RegExp('^(https?:\\/\\/)?' + // protocol
|
||||||
'((([a-z\\d]([a-z\\d-]*[a-z\\d])*)\\.)+[a-z]{2,}|' + // domain name
|
'((([a-z\\d]([a-z\\d-]*[a-z\\d])*)\\.)+[a-z]{2,}|' + // domain name
|
||||||
|
@ -223,227 +181,155 @@ $_page = new Page(array('Search'));
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
function search() {
|
function search(pageToken = '') {
|
||||||
// clear
|
// Clear previous results
|
||||||
$('#results').html('');
|
$('#results').html('');
|
||||||
$('#buttons').html('');
|
$('#buttons').html('');
|
||||||
|
|
||||||
// get form input
|
var query = $('#query').val();
|
||||||
q = $('#query').val(); // this probably shouldn't be created as a global
|
|
||||||
|
|
||||||
var playListId = getPlayListId(q);
|
// Make AJAX call to the PHP search page
|
||||||
|
$.ajax({
|
||||||
if (playListId) {
|
url: webSiteRootURL + 'plugin/BulkEmbed/search.json.php',
|
||||||
$.get(
|
type: 'POST',
|
||||||
"https://www.googleapis.com/youtube/v3/playlists", {
|
data: {
|
||||||
part: 'snippet',
|
query: query,
|
||||||
key: gapikey,
|
pageToken: pageToken
|
||||||
id: playListId
|
|
||||||
},
|
},
|
||||||
function(data) {
|
success: function(response) {
|
||||||
playListName = data.items[0].snippet.title;
|
//console.log(response); // Log the full response here
|
||||||
$.get(
|
if (response.error) {
|
||||||
"https://www.googleapis.com/youtube/v3/playlistItems", {
|
avideoAlertError(response.error);
|
||||||
part: 'snippet, id',
|
|
||||||
q: q,
|
|
||||||
type: 'video',
|
|
||||||
key: gapikey,
|
|
||||||
maxResults: 50,
|
|
||||||
videoEmbeddable: "true",
|
|
||||||
videoSyndicated: "true",
|
|
||||||
playlistId: playListId
|
|
||||||
},
|
|
||||||
function(data) {
|
|
||||||
processData(data);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
} else {
|
} else {
|
||||||
playListName = '';
|
processData(response.data);
|
||||||
// run get request on API
|
|
||||||
$.get(
|
|
||||||
"https://www.googleapis.com/youtube/v3/search", {
|
|
||||||
part: 'snippet, id',
|
|
||||||
q: q,
|
|
||||||
type: 'video',
|
|
||||||
key: gapikey,
|
|
||||||
maxResults: 50,
|
|
||||||
videoSyndicated: "true",
|
|
||||||
videoEmbeddable: "true"
|
|
||||||
},
|
|
||||||
function(data) {
|
|
||||||
processData(data);
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
error: function(xhr, status, error) {
|
||||||
|
console.log("An error occurred: " + error);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
function processData(data) {
|
function processData(data) {
|
||||||
var nextPageToken = data.nextPageToken;
|
// Check if items array exists
|
||||||
var prevPageToken = data.prevPageToken;
|
if (!data || !data.items || !Array.isArray(data.items)) {
|
||||||
|
console.error('Invalid data format received from the server:', data);
|
||||||
// Log data
|
avideoAlertError("Invalid data format received from the server");
|
||||||
//console.log(data);
|
return;
|
||||||
|
|
||||||
$.each(data.items, function(i, item) {
|
|
||||||
// Get Output
|
|
||||||
var output = getOutput(item);
|
|
||||||
|
|
||||||
// display results
|
|
||||||
$('#results').append(output);
|
|
||||||
});
|
|
||||||
|
|
||||||
var buttons = getButtons(prevPageToken, nextPageToken);
|
|
||||||
|
|
||||||
// Display buttons
|
|
||||||
$('#buttons').append(buttons);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Next page function
|
// Clear previous data
|
||||||
function nextPage() {
|
|
||||||
var token = $('#next-button').data('token');
|
|
||||||
var q = $('#next-button').data('query');
|
|
||||||
|
|
||||||
|
|
||||||
// clear
|
|
||||||
$('#results').html('');
|
$('#results').html('');
|
||||||
$('#buttons').html('');
|
$('#buttons').html('');
|
||||||
|
|
||||||
// get form input
|
// Process each item
|
||||||
q = $('#query').val(); // this probably shouldn't be created as a global
|
|
||||||
|
|
||||||
// run get request on API
|
|
||||||
$.get(
|
|
||||||
"https://www.googleapis.com/youtube/v3/search", {
|
|
||||||
part: 'snippet, id',
|
|
||||||
q: q,
|
|
||||||
pageToken: token,
|
|
||||||
type: 'video',
|
|
||||||
key: gapikey,
|
|
||||||
maxResults: 50,
|
|
||||||
videoEmbeddable: "true"
|
|
||||||
},
|
|
||||||
function(data) {
|
|
||||||
|
|
||||||
var nextPageToken = data.nextPageToken;
|
|
||||||
var prevPageToken = data.prevPageToken;
|
|
||||||
|
|
||||||
// Log data
|
|
||||||
console.log(data);
|
|
||||||
|
|
||||||
$.each(data.items, function(i, item) {
|
$.each(data.items, function(i, item) {
|
||||||
|
|
||||||
// Get Output
|
|
||||||
var output = getOutput(item);
|
var output = getOutput(item);
|
||||||
|
|
||||||
// display results
|
|
||||||
$('#results').append(output);
|
$('#results').append(output);
|
||||||
});
|
});
|
||||||
|
|
||||||
var buttons = getButtons(prevPageToken, nextPageToken);
|
// Handle pagination buttons
|
||||||
|
var buttons = getButtons(data.prevPageToken, data.nextPageToken);
|
||||||
// Display buttons
|
|
||||||
$('#buttons').append(buttons);
|
$('#buttons').append(buttons);
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Previous page function
|
|
||||||
function prevPage() {
|
|
||||||
var token = $('#prev-button').data('token');
|
|
||||||
var q = $('#prev-button').data('query');
|
|
||||||
|
|
||||||
|
function nextPage(token) {
|
||||||
// clear
|
var query = $('#query').val();
|
||||||
$('#results').html('');
|
search(token);
|
||||||
$('#buttons').html('');
|
}
|
||||||
|
|
||||||
// get form input
|
function prevPage(token) {
|
||||||
q = $('#query').val(); // this probably shouldn't be created as a global
|
var query = $('#query').val();
|
||||||
|
search(token);
|
||||||
// run get request on API
|
|
||||||
$.get(
|
|
||||||
"https://www.googleapis.com/youtube/v3/search", {
|
|
||||||
part: 'snippet, id',
|
|
||||||
q: q,
|
|
||||||
pageToken: token,
|
|
||||||
type: 'video',
|
|
||||||
key: gapikey,
|
|
||||||
maxResults: 50,
|
|
||||||
videoEmbeddable: "true"
|
|
||||||
},
|
|
||||||
function(data) {
|
|
||||||
|
|
||||||
var nextPageToken = data.nextPageToken;
|
|
||||||
var prevPageToken = data.prevPageToken;
|
|
||||||
|
|
||||||
// Log data
|
|
||||||
console.log(data);
|
|
||||||
|
|
||||||
$.each(data.items, function(i, item) {
|
|
||||||
|
|
||||||
// Get Output
|
|
||||||
var output = getOutput(item);
|
|
||||||
|
|
||||||
// display results
|
|
||||||
$('#results').append(output);
|
|
||||||
});
|
|
||||||
|
|
||||||
var buttons = getButtons(prevPageToken, nextPageToken);
|
|
||||||
|
|
||||||
// Display buttons
|
|
||||||
$('#buttons').append(buttons);
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Build output
|
|
||||||
function getOutput(item) {
|
function getOutput(item) {
|
||||||
console.log(item);
|
|
||||||
var videoID;
|
|
||||||
if (typeof item.snippet.thumbnails === 'undefined') {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
if (item.id.videoId) {
|
|
||||||
videoID = item.id.videoId;
|
|
||||||
} else {
|
|
||||||
videoID = item.snippet.resourceId.videoId;
|
|
||||||
}
|
|
||||||
var title = item.snippet.title;
|
|
||||||
var description = item.snippet.description;
|
|
||||||
var thumb = item.snippet.thumbnails.high.url;
|
|
||||||
var channelTitle = item.snippet.channelTitle;
|
|
||||||
var videoDate = item.snippet.publishedAt;
|
|
||||||
|
|
||||||
// Build output string
|
|
||||||
var output = '<li>' +
|
var output = '<li>' +
|
||||||
'<div class="list-left">' +
|
'<div class="list-left">';
|
||||||
'<img src="' + thumb + '">' +
|
|
||||||
'</div>' +
|
if (item.isEmbedded) {
|
||||||
|
// Apply grayscale effect to the image for embedded videos
|
||||||
|
output += '<img src="' + item.thumbs + '" style="filter: grayscale(100%);">';
|
||||||
|
} else {
|
||||||
|
// Regular image for non-embedded videos
|
||||||
|
output += '<img src="' + item.thumbs + '">';
|
||||||
|
}
|
||||||
|
|
||||||
|
output += '</div>' +
|
||||||
'<div class="list-right">' +
|
'<div class="list-right">' +
|
||||||
'<h3><input type="checkbox" value="' + videoID + '" name="videoCheckbox"> <a target="_blank" href="https://youtube.com/embed/' + videoID + '?rel=0">' + title + '</a></h3>' +
|
'<h3>';
|
||||||
'<small>By <span class="cTitle">' + channelTitle + '</span> on ' + videoDate + '</small>' +
|
|
||||||
'<p>' + description + '</p>' +
|
if (item.isEmbedded) {
|
||||||
|
// If the video is embedded, show only the title and indicate it's already embedded
|
||||||
|
output += '<i class="fa-regular fa-square-check"></i> <a target="_blank" href="' + item.link + '" target="_blank">' + item.title + '</a>';
|
||||||
|
output += '<p><a class="btn btn-danger" href="' + webSiteRootURL + 'video/' + item.embeddedVideos_Id + '">'+__('Already embedded')+'</strong></a>';
|
||||||
|
} else {
|
||||||
|
// If the video is not embedded, include a checkbox for embedding
|
||||||
|
output += '<input type="checkbox" value="' + item.link + '" name="videoCheckbox"> ';
|
||||||
|
output += '<a target="_blank" href="' + item.link + '">' + item.title + '</a>';
|
||||||
|
}
|
||||||
|
|
||||||
|
output += '</h3>' +
|
||||||
|
'<small>Published on ' + item.date + '</small>' +
|
||||||
|
'<p>' + item.description + '</p>' +
|
||||||
'</div>' +
|
'</div>' +
|
||||||
'</li>' +
|
|
||||||
'<div class="clearfix"></div>' +
|
'<div class="clearfix"></div>' +
|
||||||
'';
|
'</li>';
|
||||||
|
|
||||||
return output;
|
return output;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
function getButtons(prevPageToken, nextPageToken) {
|
function getButtons(prevPageToken, nextPageToken) {
|
||||||
if (!prevPageToken) {
|
var buttons = '';
|
||||||
var btnoutput = '<div class="button-container">' +
|
|
||||||
'<button id="next-button" class="paging-button" data-token="' + nextPageToken + '" data-query="' + q + '"' +
|
if (prevPageToken) {
|
||||||
'onclick = "nextPage();">Next Page</button>' +
|
buttons += '<div class="button-container">' +
|
||||||
'</div>';
|
'<button id="prev-button" class="paging-button" data-token="' + prevPageToken + '" onclick="prevPage(\'' + prevPageToken + '\')">Prev Page</button>' +
|
||||||
} else {
|
|
||||||
var btnoutput = '<div class="button-container">' +
|
|
||||||
'<button id="prev-button" class="paging-button" data-token="' + prevPageToken + '" data-query="' + q + '"' +
|
|
||||||
'onclick = "prevPage();">Prev Page</button>' +
|
|
||||||
'<button id="next-button" class="paging-button" data-token="' + nextPageToken + '" data-query="' + q + '"' +
|
|
||||||
'onclick = "nextPage();">Next Page</button>' +
|
|
||||||
'</div>';
|
'</div>';
|
||||||
}
|
}
|
||||||
|
|
||||||
return btnoutput;
|
if (nextPageToken) {
|
||||||
|
buttons += '<div class="button-container">' +
|
||||||
|
'<button id="next-button" class="paging-button" data-token="' + nextPageToken + '" onclick="nextPage(\'' + nextPageToken + '\')">Next Page</button>' +
|
||||||
|
'</div>';
|
||||||
|
}
|
||||||
|
|
||||||
|
return buttons;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Save selected videos
|
||||||
|
function saveIt(videoLink) {
|
||||||
|
modal.showPleaseWait();
|
||||||
|
setTimeout(function() {
|
||||||
|
var itemsToSave = [];
|
||||||
|
$.each(videoLink, function(index, link) {
|
||||||
|
itemsToSave.push({
|
||||||
|
link: link
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
$.ajax({
|
||||||
|
url: webSiteRootURL + 'plugin/BulkEmbed/save.json.php',
|
||||||
|
data: {
|
||||||
|
"itemsToSave": itemsToSave,
|
||||||
|
playListName: playListName
|
||||||
|
},
|
||||||
|
type: 'POST',
|
||||||
|
success: function(response) {
|
||||||
|
if (!response.error) {
|
||||||
|
avideoAlertSuccess(__("Your videos have been saved!"));
|
||||||
|
} else {
|
||||||
|
avideoAlertError(response.msg.join("<br>"));
|
||||||
|
}
|
||||||
|
modal.hidePleaseWait();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}, 500);
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue