mirror of
https://github.com/hnhx/gnutube.git
synced 2025-01-09 11:07:18 -03:00
first commit
This commit is contained in:
parent
d8a638d9ef
commit
5c7c221d3e
16 changed files with 705 additions and 0 deletions
32
api.php
Normal file
32
api.php
Normal file
|
@ -0,0 +1,32 @@
|
|||
<?php
|
||||
$config = require "config.php";
|
||||
require "misc/tools.php";
|
||||
|
||||
$query = $_REQUEST["q"];
|
||||
$type = isset($_REQUEST["type"]) ? (int) $_REQUEST["type"] : 0;
|
||||
|
||||
$results = array();
|
||||
|
||||
switch ($type)
|
||||
{
|
||||
case 0:
|
||||
require "results/search_results.php";
|
||||
get_search_results($query);
|
||||
break;
|
||||
case 1:
|
||||
require "results/channel_results.php";
|
||||
get_channel_results($query);
|
||||
break;
|
||||
case 2:
|
||||
require "results/watch_results.php";
|
||||
get_watch_results($query);
|
||||
break;
|
||||
default:
|
||||
require "results/search_results.php";
|
||||
get_search_results($query);
|
||||
break;
|
||||
}
|
||||
|
||||
header("Content-Type: application/json");
|
||||
echo json_encode($results, JSON_PRETTY_PRINT);
|
||||
?>
|
35
channel.php
Normal file
35
channel.php
Normal file
|
@ -0,0 +1,35 @@
|
|||
|
||||
<?php
|
||||
require "static/header.xhtml";
|
||||
|
||||
$config = require "config.php";
|
||||
require "misc/tools.php";
|
||||
require "results/channel_results.php";
|
||||
|
||||
$channel_id = $_REQUEST["id"];
|
||||
$results = array();
|
||||
get_channel_results($channel_id);
|
||||
|
||||
$channel_info = $results[0];
|
||||
|
||||
echo "<img class=\"banner\" src=\"/image_proxy.php?url=" . $channel_info["channel_banner"] . "\" alt=\"banner\"/ >";
|
||||
echo "<p class=\"small-channel\"><img src=\"/image_proxy.php?url=" . $channel_info["thumbnail"] . "\" width=\"50\" height=\"40\"><a href=\"channel.php?id=" . $channel_info["channel_id"] . "\">" . $channel_info["channel_name"] . "</a> (" . $channel_info["subscribers"] . ")</p>";
|
||||
|
||||
echo "<div class=\"video-results\">";
|
||||
foreach ($results as $result)
|
||||
{
|
||||
if (!$result["is_video"])
|
||||
continue;
|
||||
|
||||
echo "<div>";
|
||||
echo "<a href=\"watch.php?v=" . $result["video_id"] . "\">";
|
||||
echo "<img src=\"/image_proxy.php?url=" . $result["thumbnail"] . "\" />";
|
||||
echo "<p>" . $result["title"] . "</p>";
|
||||
echo "</a>";
|
||||
echo "<small class=\"channel-name\">" . $result["date"] . " - " . $result["views"] . "</a></small>";
|
||||
echo "</div>";
|
||||
}
|
||||
echo "</div>";
|
||||
|
||||
require "static/footer.xhtml";
|
||||
?>
|
41
config.php
Normal file
41
config.php
Normal file
|
@ -0,0 +1,41 @@
|
|||
<?php
|
||||
return (object) array(
|
||||
|
||||
/*
|
||||
This will proxy all videos trough your server so clients won't make connections to Google.
|
||||
!!! THIS WILL USE LOTS OF BANDWIDTH !!!
|
||||
*/
|
||||
"proxy_videos" => true,
|
||||
|
||||
"default_quality" => "hd720",
|
||||
|
||||
/*
|
||||
To send requests trough a proxy uncomment CURLOPT_PROXY and CURLOPT_PROXYTYPE:
|
||||
|
||||
CURLOPT_PROXYTYPE options:
|
||||
|
||||
CURLPROXY_HTTP
|
||||
CURLPROXY_SOCKS4
|
||||
CURLPROXY_SOCKS4A
|
||||
CURLPROXY_SOCKS5
|
||||
CURLPROXY_SOCKS5_HOSTNAME
|
||||
|
||||
!!! ONLY CHANGE THE OTHER OPTIONS IF YOU KNOW WHAT YOU ARE DOING !!!
|
||||
*/
|
||||
|
||||
"curl_settings" => array(
|
||||
// CURLOPT_PROXY => "ip:port",
|
||||
// CURLOPT_PROXYTYPE => CURLPROXY_HTTP,
|
||||
CURLOPT_RETURNTRANSFER => true,
|
||||
CURLOPT_ENCODING => "",
|
||||
CURLOPT_USERAGENT => "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/103.0.0.0 Safari/537.36",
|
||||
CURLOPT_IPRESOLVE => CURL_IPRESOLVE_V4,
|
||||
CURLOPT_PROTOCOLS => CURLPROTO_HTTPS | CURLPROTO_HTTP,
|
||||
CURLOPT_REDIR_PROTOCOLS => CURLPROTO_HTTPS | CURLPROTO_HTTP,
|
||||
CURLOPT_MAXREDIRS => 5,
|
||||
CURLOPT_TIMEOUT => 8,
|
||||
CURLOPT_VERBOSE => false
|
||||
)
|
||||
|
||||
);
|
||||
?>
|
BIN
favicon.ico
Normal file
BIN
favicon.ico
Normal file
Binary file not shown.
After Width: | Height: | Size: 34 KiB |
12
image_proxy.php
Normal file
12
image_proxy.php
Normal file
|
@ -0,0 +1,12 @@
|
|||
<?php
|
||||
|
||||
$config = require "config.php";
|
||||
require "misc/tools.php";
|
||||
|
||||
$image = $_REQUEST["url"];
|
||||
|
||||
$image_src = request($image);
|
||||
|
||||
header("Content-Type: image/jpeg");
|
||||
echo $image_src;
|
||||
?>
|
42
index.php
Normal file
42
index.php
Normal file
|
@ -0,0 +1,42 @@
|
|||
<?php
|
||||
require "static/header.xhtml";
|
||||
|
||||
$config = require "config.php";
|
||||
require "misc/tools.php";
|
||||
require "results/search_results.php";
|
||||
|
||||
$query = $_REQUEST["q"];
|
||||
$results = array();
|
||||
get_search_results($query);
|
||||
|
||||
if (empty($query))
|
||||
{
|
||||
echo "<p>No popular video feed here, don't be a consoomer.</p>";
|
||||
}
|
||||
else
|
||||
{
|
||||
echo "<div class=\"video-results\">";
|
||||
foreach ($results as $result)
|
||||
{
|
||||
echo "<div>";
|
||||
if ($result["is_video"])
|
||||
{
|
||||
echo "<a href=\"watch.php?v=" . $result["video_id"] . "\">";
|
||||
echo "<img src=\"/image_proxy.php?url=" . $result["thumbnail"] . "\" />";
|
||||
echo "<p>" . $result["title"] . "</p>";
|
||||
echo "</a>";
|
||||
echo "<small class=\"channel-name\"><a href=\"channel.php?id=" . $result["channel_id"] . "\">" . $result["channel_name"] . "</a> - " . $result["date"] . " - " . $result["views"] . "</small>";
|
||||
}
|
||||
else
|
||||
{
|
||||
echo "<a href=\"channel.php?id=" . $result["channel_id"] . "\">";
|
||||
echo "<img src=\"/image_proxy.php?url=" . $result["thumbnail"] . "\" />";
|
||||
echo "<p>" . $result["channel_name"] . "</p></a>";
|
||||
}
|
||||
echo "</div>";
|
||||
}
|
||||
echo "</div>";
|
||||
}
|
||||
|
||||
require "static/footer.xhtml";
|
||||
?>
|
13
misc/tools.php
Normal file
13
misc/tools.php
Normal file
|
@ -0,0 +1,13 @@
|
|||
<?php
|
||||
function request($url)
|
||||
{
|
||||
global $config;
|
||||
|
||||
$ch = curl_init($url);
|
||||
curl_setopt_array($ch, $config->curl_settings);
|
||||
|
||||
$response = curl_exec($ch);
|
||||
|
||||
return $response;
|
||||
}
|
||||
?>
|
77
results/channel_results.php
Normal file
77
results/channel_results.php
Normal file
|
@ -0,0 +1,77 @@
|
|||
|
||||
<?php
|
||||
function get_channel_results($channel_id)
|
||||
{
|
||||
global $config;
|
||||
|
||||
$url = "https://www.youtube.com/channel/$channel_id/videos?hl=en";
|
||||
|
||||
$response = file_get_contents($url);
|
||||
$data_part1 = explode("var ytInitialData = ", $response);
|
||||
$data_part2 = explode(";</script>", $data_part1[1]);
|
||||
$data = json_decode($data_part2[0], true);
|
||||
$raw_results = $data["contents"]["twoColumnBrowseResultsRenderer"]["tabs"][1]["tabRenderer"]["content"]["sectionListRenderer"]["contents"];
|
||||
|
||||
parse_channel_header($data);
|
||||
parse_channel_results($raw_results);
|
||||
|
||||
|
||||
}
|
||||
|
||||
function parse_channel_header($data)
|
||||
{
|
||||
global $results;
|
||||
|
||||
$header = $data["header"]["c4TabbedHeaderRenderer"];
|
||||
$channel_name = $header["title"];
|
||||
$channel_id = $header["channelId"];
|
||||
$channel_thumbnail = $header["avatar"]["thumbnails"][0]["url"];
|
||||
$channel_banner = $header["banner"]["thumbnails"][0]["url"];
|
||||
$subscribers = $header["subscriberCountText"]["simpleText"];
|
||||
|
||||
$result = array(
|
||||
"is_video" => false,
|
||||
"channel_name" => $channel_name,
|
||||
"channel_id" => $channel_id,
|
||||
"thumbnail" => $channel_thumbnail,
|
||||
"channel_banner" => $channel_banner,
|
||||
"subscribers" => $subscribers
|
||||
);
|
||||
|
||||
array_push($results, $result);
|
||||
}
|
||||
|
||||
function parse_channel_results($raw_results)
|
||||
{
|
||||
global $results;
|
||||
|
||||
foreach ($raw_results as $raw_result)
|
||||
{
|
||||
$shelf_raw_results = $raw_result["itemSectionRenderer"]["contents"][0]["gridRenderer"]["items"];
|
||||
foreach ($shelf_raw_results as $shelf_raw_result)
|
||||
{
|
||||
if (array_key_exists("gridVideoRenderer", $shelf_raw_result))
|
||||
{
|
||||
|
||||
$video = $shelf_raw_result["gridVideoRenderer"];
|
||||
$video_id = $video["videoId"];
|
||||
$thumbnail = $video["thumbnail"]["thumbnails"][0]["url"];
|
||||
$title = $video["title"]["runs"][0]["text"];
|
||||
$views = $video["viewCountText"]["simpleText"];
|
||||
$date = $video["publishedTimeText"]["simpleText"];
|
||||
|
||||
$result = array(
|
||||
"is_video" => true,
|
||||
"video_id" => $video_id,
|
||||
"title" => $title,
|
||||
"thumbnail" => $thumbnail,
|
||||
"views" => $views,
|
||||
"date" => $date
|
||||
);
|
||||
|
||||
array_push($results, $result);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
?>
|
75
results/search_results.php
Normal file
75
results/search_results.php
Normal file
|
@ -0,0 +1,75 @@
|
|||
|
||||
<?php
|
||||
function get_search_results($query)
|
||||
{
|
||||
global $config;
|
||||
|
||||
$query = urlencode($query);
|
||||
$url = "https://www.youtube.com/results?search_query=$query&hl=en";
|
||||
|
||||
$response = request($url);
|
||||
$data_part1 = explode("var ytInitialData = ", $response);
|
||||
$data_part2 = explode(";</script>", $data_part1[1]);
|
||||
$data = json_decode($data_part2[0], true);
|
||||
$raw_results = $data["contents"]["twoColumnSearchResultsRenderer"]["primaryContents"]["sectionListRenderer"]["contents"][0]["itemSectionRenderer"]["contents"];
|
||||
|
||||
parse_search_results($raw_results);
|
||||
}
|
||||
|
||||
function parse_search_results($raw_results)
|
||||
{
|
||||
global $results;
|
||||
|
||||
foreach ($raw_results as $raw_result)
|
||||
{
|
||||
if (array_key_exists("videoRenderer", $raw_result))
|
||||
{
|
||||
$video = $raw_result["videoRenderer"];
|
||||
$video_id = $video["videoId"];
|
||||
$thumbnail = $video["thumbnail"]["thumbnails"][0]["url"];
|
||||
$title = $video["title"]["runs"][0]["text"];
|
||||
$views = $video["shortViewCountText"]["simpleText"];
|
||||
$date = $video["publishedTimeText"]["simpleText"];
|
||||
|
||||
$channel = $video["longBylineText"]["runs"][0];
|
||||
$channel_name = $channel["text"];
|
||||
$channel_id = $channel["navigationEndpoint"]["browseEndpoint"]["browseId"];
|
||||
|
||||
$result = array(
|
||||
"is_video" => true,
|
||||
"video_id" => $video_id,
|
||||
"title" => $title,
|
||||
"thumbnail" => $thumbnail,
|
||||
"channel_id" => $channel_id,
|
||||
"channel_name" => $channel_name,
|
||||
"views" => $views,
|
||||
"date" => $date
|
||||
);
|
||||
|
||||
array_push($results, $result);
|
||||
}
|
||||
else if (array_key_exists("shelfRenderer", $raw_result))
|
||||
{
|
||||
$shelf_raw_results = $raw_result["shelfRenderer"]["content"]["verticalListRenderer"]["items"];
|
||||
parse_search_results($shelf_raw_results);
|
||||
}
|
||||
else if (array_key_exists("channelRenderer", $raw_result))
|
||||
{
|
||||
$channel = $raw_result["channelRenderer"];
|
||||
$channel_id = $channel["channelId"];
|
||||
$channel_name = $channel["title"]["simpleText"];
|
||||
$channel_thumbnail = $channel["thumbnail"]["thumbnails"][1]["url"];
|
||||
$fixed_channel_thumbnail = "https://" . substr($channel_thumbnail, 2);
|
||||
|
||||
$result = array(
|
||||
"is_video" => false,
|
||||
"channel_id" => $channel_id,
|
||||
"channel_name" => $channel_name,
|
||||
"thumbnail" => $fixed_channel_thumbnail
|
||||
);
|
||||
|
||||
array_push($results, $result);
|
||||
}
|
||||
}
|
||||
}
|
||||
?>
|
173
results/watch_results.php
Normal file
173
results/watch_results.php
Normal file
|
@ -0,0 +1,173 @@
|
|||
|
||||
<?php
|
||||
function get_watch_results($video_id)
|
||||
{
|
||||
global $config;
|
||||
|
||||
$mh = curl_multi_init();
|
||||
|
||||
// Get directl URL to the video
|
||||
$direct_ch = curl_init("https://youtubei.googleapis.com/youtubei/v1/player?key=AIzaSyAO_FJ2SlqU8Q4STEHLGCilw_Y9_11qcW8");
|
||||
curl_setopt_array($direct_ch, $config->curl_settings);
|
||||
curl_setopt($direct_ch, CURLOPT_HTTPHEADER, array("Content-Type: application/json"));
|
||||
curl_setopt($direct_ch, CURLOPT_POST, 1);
|
||||
curl_setopt($direct_ch, CURLOPT_POSTFIELDS, "{
|
||||
'context': {
|
||||
'client': {
|
||||
'hl': 'en',
|
||||
'clientName': 'WEB',
|
||||
'clientVersion': '2.20210721.00.00',
|
||||
'mainAppWebInfo': {
|
||||
'graftUrl': '/watch?v=$video_id'
|
||||
}
|
||||
}
|
||||
},
|
||||
'videoId': '$video_id'
|
||||
}");
|
||||
curl_multi_add_handle($mh, $direct_ch);
|
||||
|
||||
// Get additional info (description, recommended videos etc.)
|
||||
$video_ch = curl_init("https://www.youtube.com/watch?v=$video_id&hl=en");
|
||||
curl_setopt_array($video_ch, $config->curl_settings);
|
||||
curl_multi_add_handle($mh, $video_ch);
|
||||
|
||||
$running = null;
|
||||
do {
|
||||
curl_multi_exec($mh, $running);
|
||||
} while ($running);
|
||||
|
||||
// Parse the response
|
||||
$video_response = curl_multi_getcontent($video_ch);
|
||||
get_video_results($video_response);
|
||||
|
||||
$direct_response = curl_multi_getcontent($direct_ch);
|
||||
get_direct_url($direct_response);
|
||||
}
|
||||
|
||||
|
||||
function get_direct_url($json_response, $audio_only=false)
|
||||
{
|
||||
global $config , $results;
|
||||
|
||||
$response = json_decode($json_response, true);
|
||||
$videos = array_merge($response["streamingData"]["formats"], $response["streamingData"]["adaptiveFormats"]);
|
||||
|
||||
$video_url = null;
|
||||
|
||||
do
|
||||
{
|
||||
foreach ($videos as $video)
|
||||
{
|
||||
$type = $video["mimeType"];
|
||||
$quality = $video["quality"];
|
||||
|
||||
if ($audio_only)
|
||||
{
|
||||
if (strpos($type, "audio") !== false)
|
||||
$video_url = $video["url"];
|
||||
}
|
||||
else if (strpos($type, "video") !== false && strpos($quality, $config->default_quality) !== false)
|
||||
$video_url = $video["url"];
|
||||
|
||||
if ($video_url)
|
||||
break;
|
||||
}
|
||||
|
||||
$config->default_quality = "";
|
||||
} while ($video_url == null);
|
||||
|
||||
$results[0]["direct_url"] = urlencode($video_url);
|
||||
}
|
||||
|
||||
function get_video_results($response)
|
||||
{
|
||||
$data_part1 = explode("var ytInitialData = ", $response);
|
||||
$data_part2 = explode(";</script>", $data_part1[1]);
|
||||
$data = json_decode($data_part2[0], true);
|
||||
$raw_results = $data["contents"]["twoColumnWatchNextResults"]["secondaryResults"]["secondaryResults"]["results"];
|
||||
|
||||
parse_main_video_info($data);
|
||||
parse_recommended_results($raw_results);
|
||||
}
|
||||
|
||||
function parse_main_video_info($data)
|
||||
{
|
||||
global $results;
|
||||
|
||||
$main_info = $data["contents"]["twoColumnWatchNextResults"]["results"]["results"]["contents"];
|
||||
$video_info = $main_info[0]["videoPrimaryInfoRenderer"];
|
||||
$title = $video_info["title"]["runs"][0]["text"];
|
||||
$views = $video_info["viewCount"]["videoViewCountRenderer"]["viewCount"]["simpleText"];
|
||||
$date = $video_info["dateText"]["simpleText"];
|
||||
$likes = $video_info["videoActions"]["menuRenderer"]["topLevelButtons"][0]["toggleButtonRenderer"]["defaultText"]["accessibility"]["accessibilityData"]["label"];
|
||||
$channel_info = $main_info[1]["videoSecondaryInfoRenderer"]["owner"]["videoOwnerRenderer"];
|
||||
$channel_name = $channel_info["title"]["runs"][0]["text"];
|
||||
$subscribers = $channel_info["subscriberCountText"]["simpleText"];
|
||||
$channel_thumbnail = urlencode($channel_info["thumbnail"]["thumbnails"][0]["url"]);
|
||||
$channel_id = $channel_info["navigationEndpoint"]["browseEndpoint"]["browseId"];
|
||||
$raw_description = $main_info[1]["videoSecondaryInfoRenderer"]["description"]["runs"];
|
||||
$description = "";
|
||||
foreach ($raw_description as $part)
|
||||
{
|
||||
$text = $part["text"];
|
||||
|
||||
if (array_key_exists("navigationEndpoint", $part))
|
||||
$description .= "$text <br><br>";
|
||||
else
|
||||
$description .= $text . "<br><br>";
|
||||
}
|
||||
|
||||
$result = array(
|
||||
"is_main_video" => true,
|
||||
"is_video" => true,
|
||||
"direct_url" => null,
|
||||
"title" => $title,
|
||||
"thumbnail" => $channel_thumbnail,
|
||||
"channel_id" => $channel_id,
|
||||
"channel_name" => $channel_name,
|
||||
"description" => $description,
|
||||
"views" => $views,
|
||||
"date" => $date,
|
||||
"likes" => $likes,
|
||||
"subscribers" => $subscribers
|
||||
);
|
||||
|
||||
array_push($results, $result);
|
||||
}
|
||||
|
||||
function parse_recommended_results($raw_results)
|
||||
{
|
||||
global $results;
|
||||
|
||||
foreach ($raw_results as $raw_result)
|
||||
{
|
||||
if (array_key_exists("compactVideoRenderer", $raw_result))
|
||||
{
|
||||
|
||||
$video = $raw_result["compactVideoRenderer"];
|
||||
$video_id = $video["videoId"];
|
||||
$thumbnail = $video["thumbnail"]["thumbnails"][1]["url"];
|
||||
$title = $video["title"]["simpleText"];
|
||||
$views = $video["shortViewCountText"]["simpleText"];
|
||||
$date = $video["publishedTimeText"]["simpleText"];
|
||||
|
||||
$channel = $video["longBylineText"]["runs"][0];
|
||||
$channel_name = $channel["text"];
|
||||
$channel_id = $channel["navigationEndpoint"]["browseEndpoint"]["browseId"];
|
||||
|
||||
$result = array(
|
||||
"is_video" => true,
|
||||
"video_id" => $video_id,
|
||||
"title" => $title,
|
||||
"thumbnail" => $thumbnail,
|
||||
"channel_id" => $channel_id,
|
||||
"channel_name" => $channel_name,
|
||||
"views" => $views,
|
||||
"date" => $date
|
||||
);
|
||||
|
||||
array_push($results, $result);
|
||||
}
|
||||
}
|
||||
}
|
||||
?>
|
2
static/footer.xhtml
Normal file
2
static/footer.xhtml
Normal file
|
@ -0,0 +1,2 @@
|
|||
</body>
|
||||
</html>
|
BIN
static/gnutube.png
Normal file
BIN
static/gnutube.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 34 KiB |
15
static/header.xhtml
Normal file
15
static/header.xhtml
Normal file
|
@ -0,0 +1,15 @@
|
|||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
|
||||
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
|
||||
<head>
|
||||
<title>GNUTube (BETA)</title>
|
||||
<meta content="text/html; charset=utf-8" http-equiv="content-type" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<meta name="referrer" content="no-referrer" />
|
||||
<link rel="stylesheet" type="text/css" href="static/styles.css" />
|
||||
</head>
|
||||
<body>
|
||||
<form class="search" action="index.php">
|
||||
<a href="/"><img src="static/gnutube.png" alt="gnutube"></a>
|
||||
<input name="q" placeholder="Search" />
|
||||
<input type="submit" style="display: none;"/>
|
||||
</form>
|
113
static/styles.css
Normal file
113
static/styles.css
Normal file
|
@ -0,0 +1,113 @@
|
|||
body {
|
||||
background-color: #181818;
|
||||
font-family: Arial, Helvetica, sans-serif;
|
||||
color: #e8eaed;
|
||||
word-break: break-all;
|
||||
margin-left: 9%;
|
||||
margin-right: 9%;
|
||||
}
|
||||
|
||||
video {
|
||||
width: 100%;
|
||||
height: 700px;
|
||||
}
|
||||
|
||||
.search {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.search img {
|
||||
float: left;
|
||||
margin-left: 35px;
|
||||
margin-top: 20px;
|
||||
width: 55px;
|
||||
height: 40px;
|
||||
}
|
||||
|
||||
.search h3 {
|
||||
margin-left: 10px;
|
||||
}
|
||||
|
||||
.banner {
|
||||
width: 100%;
|
||||
height: 230px;
|
||||
}
|
||||
|
||||
.search input {
|
||||
width: 500px;
|
||||
margin-bottom: 30px;
|
||||
margin-top: 20px;
|
||||
padding: 10px;
|
||||
border: 1px solid #202020;
|
||||
background-color: #121212;
|
||||
color: inherit;
|
||||
font-family: inherit;
|
||||
font-size: 17px;
|
||||
outline: none;
|
||||
}
|
||||
|
||||
.video-results {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(auto-fit, minmax(420px, 1fr));
|
||||
grid-gap: 1.5rem;
|
||||
justify-items: center;
|
||||
padding: 0;
|
||||
margin-bottom:50px;
|
||||
}
|
||||
|
||||
.video-results a {
|
||||
text-decoration: none;
|
||||
color: inherit;
|
||||
}
|
||||
|
||||
.video-results img {
|
||||
width: 420px;
|
||||
height: 220px;
|
||||
border: 1px solid #bd93f9;
|
||||
}
|
||||
|
||||
.channel-name a ,
|
||||
.small-channel a {
|
||||
color: #bd93f9;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
.small-channel img {
|
||||
width: 50 !important;
|
||||
height: 50 !important;
|
||||
border-radius: 50%;
|
||||
vertical-align: middle;
|
||||
margin-right: 20px;
|
||||
}
|
||||
|
||||
.description {
|
||||
width: 50%;
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
/* mobile view */
|
||||
@media only screen and (max-width: 900px) {
|
||||
body {
|
||||
margin-left: 0%;
|
||||
margin-right: 0%;
|
||||
}
|
||||
|
||||
video {
|
||||
height: auto;
|
||||
}
|
||||
|
||||
.search input {
|
||||
width: 90%;
|
||||
}
|
||||
|
||||
.banner {
|
||||
height: 100px;
|
||||
}
|
||||
|
||||
.search img {
|
||||
float: unset;
|
||||
width: 80px;
|
||||
height: 60px;
|
||||
margin-left: 0%;
|
||||
}
|
||||
}
|
31
video_proxy.php
Normal file
31
video_proxy.php
Normal file
|
@ -0,0 +1,31 @@
|
|||
<?php
|
||||
$config = require "config.php";
|
||||
if (!$config->proxy_videos)
|
||||
{
|
||||
echo "Sorry but the host disabled this feature!";
|
||||
die();
|
||||
}
|
||||
|
||||
|
||||
header("Content-Type: video/mp4");
|
||||
ini_set("memory_limit", "1024M");
|
||||
set_time_limit(3600);
|
||||
|
||||
$url = urldecode($_GET["url"]);
|
||||
|
||||
ob_start();
|
||||
|
||||
$opts["http"]["header"] = "Range: " . $_SERVER["HTTP_RANGE"];
|
||||
$opts["http"]["method"] = "HEAD";
|
||||
$conh=stream_context_create($opts);
|
||||
$opts["http"]["method"] = "GET";
|
||||
$cong = stream_context_create($opts);
|
||||
$out[ ]= file_get_contents($url, false, $conh);
|
||||
$out[] = $http_response_header;
|
||||
|
||||
ob_end_clean();
|
||||
|
||||
array_map("header", $http_response_header);
|
||||
|
||||
readfile($url, false, $cong);
|
||||
?>
|
44
watch.php
Normal file
44
watch.php
Normal file
|
@ -0,0 +1,44 @@
|
|||
|
||||
<?php
|
||||
require "static/header.xhtml";
|
||||
|
||||
$config = require "config.php";
|
||||
require "misc/tools.php";
|
||||
require "results/watch_results.php";
|
||||
|
||||
$video_id = $_REQUEST["v"];
|
||||
|
||||
$results = array();
|
||||
get_watch_results($video_id);
|
||||
|
||||
$main_vid = $results[0];
|
||||
|
||||
echo "<video controls autoplay>";
|
||||
if ($config->proxy_videos)
|
||||
echo "<source src=\"/video_proxy.php?url=" . $main_vid["direct_url"] . "\" type=\"video/mp4\">";
|
||||
else
|
||||
echo "<source src=\"" . urldecode($main_vid["direct_url"]) . "\" type=\"video/mp4\">";
|
||||
echo "</video>";
|
||||
echo "<h3>" . $main_vid["title"] . "</h3>";
|
||||
echo "<p>" . $main_vid["date"] . " - " . $main_vid["views"] . " - " . $main_vid["likes"] . "</p>";
|
||||
echo "<p class=\"small-channel\"><img src=\"/image_proxy.php?url=" . $main_vid["thumbnail"] . "\" width=\"50\" height=\"40\"><a href=\"channel.php?id=" . $main_vid["channel_id"] . "\">" . $main_vid["channel_name"] . "</a> (" . $main_vid["subscribers"] . ")</p>";
|
||||
//echo "<p class=\"description\">" . $main_vid["description"] . "</p>";
|
||||
|
||||
echo "<div class=\"video-results\">";
|
||||
foreach ($results as $result)
|
||||
{
|
||||
if (array_key_exists("is_main_video", $result))
|
||||
continue;
|
||||
|
||||
echo "<div>";
|
||||
echo "<a href=\"watch.php?v=" . $result["video_id"] . "\">";
|
||||
echo "<img src=\"/image_proxy.php?url=" . $result["thumbnail"] . "\" />";
|
||||
echo "<p>" . $result["title"] . "</p>";
|
||||
echo "</a>";
|
||||
echo "<span class=\"channel-name\"><a href=\"channel.php?id=" . $result["channel_id"] . "\">" . $result["channel_name"] . "</a> - " . $result["date"] . " - " . $result["views"] . "</span>";
|
||||
echo "</div>";
|
||||
}
|
||||
echo "</div>";
|
||||
|
||||
require "static/footer.xhtml";
|
||||
?>
|
Loading…
Reference in a new issue