Compare commits

...

4 Commits

Author SHA1 Message Date
db986bdaed Merge branch 'nez-main' 2023-03-27 18:57:37 +03:00
54e48950c0 Merge branch 'main' of https://git.donut.eu.org/nez/ntv-site into nez-main 2023-03-27 18:53:41 +03:00
9a80889abe filez 2023-03-27 17:46:52 +02:00
d82f26947c add watch page 2023-03-26 11:01:11 +02:00
13 changed files with 387 additions and 1722 deletions

27
NTV_offering/index.css Normal file
View File

@ -0,0 +1,27 @@
.results {
margin-top: 1rem;
text-align: center;
}
table, tr, th, td {
border: 1px solid black;
border-collapse: collapse;
padding-left: 1rem;
padding-right: 1rem;
padding-top: 0.4rem;
padding-bottom: 0.4rem;
}
.name {
text-decoration: none;
}
#queue {
border: none;
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
background-color: white;
}

128
NTV_offering/index.js Normal file
View File

@ -0,0 +1,128 @@
var library = [];
var URLINFO = new URL(window.location.href);
document.addEventListener("DOMContentLoaded", function() {
document.getElementById("query").addEventListener("keydown", function(event) {
if (event.keyCode == 13) {
event.preventDefault();
document.getElementById("submit").click();
}
});
var raw = new XMLHttpRequest();
var libIndic = document.getElementById("libIndic");
libIndic.innerHTML = "loading";
raw.addEventListener("load", function() {
if (this.status != 200) return alert("Cannot fetch library");
var items = this.responseText.split("\n");
for (var i = 0; i < items.length; i++) {
if (items[i] == "") continue;
var info = JSON.parse(items[i]);
info.lName = info.name.toLowerCase().split(" ").join("_");
library.push(info);
}
libIndic.innerHTML = "loaded";
});
raw.open("GET", "https://home.nezbednik.eu.org:2000/NTV_offering/library.txt");
raw.send();
});
window.addEventListener("message", (data) => {
if (data.data == "closeQueue") document.getElementById("queueButton").click();
});
function doSearch() {
document.getElementById("nosearch").style.display = "none";
document.getElementById("noresults").style.display = "none";
var searching = document.getElementById("searching");
var resultsH = document.getElementById("results");
resultsH.style.display = "none";
resultsH.innerHTML = "";
searching.style.display = "block";
var titles = document.createElement("tr");
var titleName = document.createElement("th");
titleName.innerHTML = "name & stream";
titles.appendChild(titleName);
var titleSource = document.createElement("th");
titleSource.innerHTML = "source";
titles.appendChild(titleSource);
var titleAdd = document.createElement("th");
titleAdd.innerHTML = "request";
titles.appendChild(titleAdd);
resultsH.appendChild(titles);
var query = document.getElementById("query").value.toLowerCase().split(" ").join("_");
var results = library.filter((a) => {
return a.lName.includes(query);
});
for (var i = 0; i < results.length; i++) {
var tr = document.createElement("tr");
var _name = document.createElement("td");
var name = document.createElement("a");
name.classList.add("name");
name.href = results[i].stream;
name.setAttribute("target", "_blank");
name.innerHTML = (Object.keys(results[i]).includes("prefix") ? ("<p href=\"about:blank\" style=\"text-decoration: none; display: inline; color: #3399ff;\">(" + results[i].prefix + ")</p> ") : "") + results[i].name;
name.style.color = "blue";
_name.appendChild(name);
tr.appendChild(_name);
var source = document.createElement("td");
source.innerHTML = results[i].source;
tr.appendChild(source);
var _add = document.createElement("td");
var add = document.createElement("button");
add.textContent = "request!";
add.setAttribute("onclick", "event.preventDefault(); doRequest(this)");
add.setAttribute("data-source", results[i].source);
add.setAttribute("data-item", results[i].item);
_add.appendChild(add);
if (URLINFO.searchParams.has("commandMode") && URLINFO.searchParams.get("commandMode").toString() == "1") {
var spacer = document.createElement("a");
spacer.innerHTML = "&nbsp;";
_add.appendChild(spacer);
var copy = document.createElement("button");
copy.textContent = "copy";
copy.setAttribute("onclick", "event.preventDefault(); prompt('your command', './makeJSON.sh \\\"' + this.getAttribute('data-stream') + '\\\" \\\"' + this.getAttribute('data-name').split('\"').join('\\\\\\\"') + '\\\" \\\"' + this.getAttribute('data-source') + '\\\"')");
copy.setAttribute("data-stream", results[i].stream);
copy.setAttribute("data-name", results[i].name);
copy.setAttribute("data-source", results[i].source);
_add.appendChild(copy);
}
tr.appendChild(_add);
resultsH.appendChild(tr);
}
resultsH.style.display = "";
searching.style.display = "none";
}
function doRequest(obj) {
var comment = prompt("Please enter any wishes here. Special title? Dedication? Will show in the queue menu!");
if (comment == null) comment = "";
var source = obj.getAttribute("data-source");
var item = obj.getAttribute("data-item");
obj.textContent = "requesting";
var paramObj = new URL("http://a.a");
paramObj.searchParams.set("source", source);
paramObj.searchParams.set("item", item);
if (comment != "") paramObj.searchParams.set("comment", comment);
var raw = new XMLHttpRequest();
raw.addEventListener("load", function() {
if (this.status != 200) return obj.textContent = "failed :\\";
obj.textContent = "requested!";
});
raw.open("POST", "https://home.nezbednik.eu.org:2000/NTV_offering/request.php");
raw.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
raw.send(paramObj.search.slice(1));
}

92
css/styles.css Normal file
View File

@ -0,0 +1,92 @@
a.button {
height: 17px;
background: rgb(255,255,255);
background: -moz-linear-gradient(180deg, rgba(255,255,255,1) 0%, rgba(168,176,194,1) 13%, rgba(73,80,93,1) 49%, rgba(39,46,55,1) 51%, rgba(13,27,35,1) 87%, rgba(0,6,10,1) 100%);
background: -webkit-linear-gradient(180deg, rgba(255,255,255,1) 0%, rgba(168,176,194,1) 13%, rgba(73,80,93,1) 49%, rgba(39,46,55,1) 51%, rgba(13,27,35,1) 87%, rgba(0,6,10,1) 100%);
background: linear-gradient(180deg, rgba(255,255,255,1) 0%, rgba(168,176,194,1) 13%, rgba(73,80,93,1) 49%, rgba(39,46,55,1) 51%, rgba(13,27,35,1) 87%, rgba(0,6,10,1) 100%);
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr="#ffffff",endColorstr="#00060a",GradientType=1);
border: 1px solid #1e2229;
border-top: 1px solid #848998;
border-bottom: 1px solid #02070c;
color: #ffffff;
text-decoration: none;
font-family: sans-serif;
font-size: 11pt;
padding: 3px;
min-width: 70px;
display: inline-block;
text-align: center;
vertical-align: middle;
}
a.button:hover {
font-weight: bold;
}
a.button:active {
padding: 2px;
margin: 1px;
font-size: 10pt;
}
body, html {
margin: 0;
padding: 0;
}
body {
max-width: 800px;
margin: auto;
background-color: #ffffff;
/*
border-left: 1px solid #c0c0c0;
border-right: 1px solid #c0c0c0;
*/
font-family: sans-serif;
font-size: 11pt;
}
nav {
display: block;
width: fit-content;
margin: auto;
}
header {
background: rgb(17,62,76);
background: -moz-linear-gradient(180deg, rgba(17,62,76,1) 0%, rgba(17,61,74,1) 74%, rgba(9,32,40,1) 100%);
background: -webkit-linear-gradient(180deg, rgba(17,62,76,1) 0%, rgba(17,61,74,1) 74%, rgba(9,32,40,1) 100%);
background: linear-gradient(180deg, rgba(17,62,76,1) 0%, rgba(17,61,74,1) 74%, rgba(9,32,40,1) 100%);
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr="#113e4c",endColorstr="#092028",GradientType=1);
padding-bottom: 4px;
border-bottom: 1px solid #082026;
}
img.banner {
border-bottom: 1px solid #082026;
}
footer {
background: rgb(17,62,76);
background: -moz-linear-gradient(180deg, rgba(17,62,76,1) 0%, rgba(9,32,40,1) 100%);
background: -webkit-linear-gradient(180deg, rgba(17,62,76,1) 0%, rgba(9,32,40,1) 100%);
background: linear-gradient(180deg, rgba(17,62,76,1) 0%, rgba(9,32,40,1) 100%);
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr="#113e4c",endColorstr="#092028",GradientType=1);
color: #ffffff;
padding: 15px;
text-align: center;
border-top: 1px solid #082026;
}
main {
padding: 15px;
margin: 0;
}
.song-display {
display: inline-block;
background-color: #000000;
width: 285px;
font-size: 11pt;
border: 1px solid #c0c0c0;
color: #ed8e1d;
padding: 3px 5px 2px 5px;
vertical-align: middle;
font-family: monospace;
}
#js {
background-color: black;
width: 770px;
height: 433px;
}

1
css/video-js.min.css vendored Normal file

File diff suppressed because one or more lines are too long

View File

@ -1,20 +1,23 @@
<!DOCTYPE html>
<?php
$cache = bin2hex(random_bytes(16));
?><!DOCTYPE html>
<html>
<head>
<title>NTV</title>
<link rel="stylesheet" href="styles.css?cache=<?php echo bin2hex(random_bytes(16)); ?>">
<link rel="stylesheet" href="/css/styles.css?cache=<?php echo $cache; ?>">
<script src="/js/song-display.js?cache=<?php echo $cache; ?>"></script>
</head>
<body>
<header>
<a href="/"><img src="/img/banner.png" class="banner" alt='NTV banner with the tagline "You decide."'></a>
<nav>
<a href="/" class="button">home</a>
<a href="#" class="button">watch</a>
<a href="#" class="button">queue</a>
<a href="#" class="button">request</a>
<a href="#" class="button">about</a>
<a href="#" class="button">contact</a>
<div class="song-display">Today is <?php echo date("d/m/Y h:i"); ?></div>
<a href="/watch.php" class="button">watch</a>
<a href="javascript:alert('queue not implemented')" class="button">queue</a>
<a href="/request.php" class="button">request</a>
<a href="javascript:alert('about not implemented')" class="button">about</a>
<a href="javascript:alert('contact not implemented')" class="button">contact</a>
<div class="song-display" id="song-display">&nbsp;</div>
</nav>
</header>
<main>

View File

@ -2,8 +2,8 @@
mkdir npmtemp
cd npmtemp
npm init -y
npm i video.js videojs-contrib-quality-levels tingtingan-videojs-hls-quality-selector
cp node_modules/video.js/dist/video-js.css ..
npm i video.js@7.21.4 videojs-contrib-quality-levels tingtingan-videojs-hls-quality-selector
cp node_modules/video.js/dist/video-js.min.css ../../css/
cp node_modules/video.js/dist/video.min.js ..
cp node_modules/videojs-contrib-quality-levels/dist/videojs-contrib-quality-levels.min.js ..
cp node_modules/tingtingan-videojs-hls-quality-selector/dist/videojs-hls-quality-selector.min.js ..

54
js/song-display.js Normal file
View File

@ -0,0 +1,54 @@
var songEndpoint = "https://stream.services.nez-cf.net.eu.org:1965/ntv_nowplaying.php";
function fetchSong() {
return new Promise((resolve, reject) => {
var xhr = new XMLHttpRequest();
xhr.addEventListener("load", function() {
if (this.status == 200) resolve(this.responseText);
else reject(this);
});
xhr.open("GET", songEndpoint);
xhr.send();
});
}
function spacePad(i, c = "&nbsp;", a = 32) {
var l = 32 - i.length;
if (l < 0) l = 0;
return i + c.repeat(l);
}
var scrollIndex = -1;
var scrollText = "";
var scrollElement = "null";
var skipTurns = 0;
var skipTurnsBegin = 5;
function scroller() {
if (scrollElement == "null") return;
if (skipTurns > 0) return skipTurns--;
if (skipTurnsBegin > 0) skipTurnsBegin--;
scrollIndex++;
if (scrollIndex > scrollText.length) {
scrollIndex = -1;
skipTurnsBegin = 5;
return skipTurns = 5;
}
if (scrollText.length > 32) scrollElement.innerHTML = spacePad(scrollText.substr(skipTurnsBegin > 0 ? 0 : scrollIndex, 32).replace(/ /g, "&nbsp;"));
else scrollElement.innerHTML = spacePad(scrollText.replace(/ /g, "&nbsp;"));
}
async function updateSongs() {
var song = await fetchSong();
song = "now playing: " + song;
if (scrollText != song) {
scrollText = song;
scrollIndex = -1;
}
}
document.addEventListener("DOMContentLoaded", function() {
scrollElement = document.getElementById("song-display");
setInterval(scroller, 200);
updateSongs();
setInterval(updateSongs, 20 * 1000);
});

File diff suppressed because one or more lines are too long

1
js/video-js.min.css vendored Normal file

File diff suppressed because one or more lines are too long

46
js/video.min.js vendored

File diff suppressed because one or more lines are too long

26
request.php Normal file
View File

@ -0,0 +1,26 @@
<!DOCTYPE html>
<html>
<head>
<title>NTV song select!!!</title>
<script src="NTV_offering/index.js?cache=<?php echo bin2hex(random_bytes(16)); ?>"></script>
<link rel="stylesheet" href="NTV_offering/index.css">
</head>
<body>
<iframe src="https://home.nezbednik.eu.org:2000/NTV_offering/queue_embed.php" id="queue" style="display: none;"></iframe>
<a href="about:blank" id="queueButton" onclick="event.preventDefault(); var q = document.getElementById('queue'); if (q.hasAttribute('style')) { q.removeAttribute('style'); } else { q.setAttribute('style', 'display: none;'); }">open queue</a>
<h1 style="margin-bottom: 0; margin-top: 0;">NTV song select</h1>
<a>library:&nbsp;</a><a id="libIndic">initializing</a><br><br>
<input type="text" id="query" placeholder="Axel_F">
<input type="submit" id="submit" onclick="doSearch()">
<table id="results" class="results"></table>
<div id="nosearch">
<p>Please input a query!</p>
</div>
<div id="searching" style="display: none;">
<p>Searching...</p>
</div>
<div id="noresults" style="display: none;">
<p>No result</p>
</div>
</body>
</html>

View File

@ -1,4 +1,4 @@
button, a.button {
a.button {
height: 17px;
background: rgb(255,255,255);
background: -moz-linear-gradient(180deg, rgba(255,255,255,1) 0%, rgba(168,176,194,1) 13%, rgba(73,80,93,1) 49%, rgba(39,46,55,1) 51%, rgba(13,27,35,1) 87%, rgba(0,6,10,1) 100%);
@ -18,10 +18,10 @@ button, a.button {
text-align: center;
vertical-align: middle;
}
button:hover, a.button:hover {
a.button:hover {
font-weight: bold;
}
button:active, a.button:active {
a.button:active {
padding: 2px;
margin: 1px;
font-size: 10pt;
@ -89,3 +89,8 @@ main {
vertical-align: middle;
font-family: monospace;
}
#js {
width: 800px;
height: 450px;
}

21
watch.php Normal file
View File

@ -0,0 +1,21 @@
<?php include("includes/header.php") ?>
<link rel="stylesheet" href="/css/video-js.min.css?cache=<?php echo $cache; ?>">
<script src="/js/video.min.js?cache=<?php echo $cache; ?>"></script>
<script src="/js/videojs-contrib-quality-levels.min.js"></script>
<script src="/js/videojs-hls-quality-selector.min.js"></script>
<h1>NTV on your Mind</h1>
<script>
document.addEventListener("DOMContentLoaded", function() {
var vjs = videojs("js");
vjs.controls("true");
vjs.src({
type: "application/vnd.apple.mpegurl",
src: "https://stream.services.nez-cf.net.eu.org:1965/playlist.m3u8"
});
vjs.hlsQualitySelector({
vjsIconClass: "vjs-icon-cog"
});
});
</script>
<video id="js" class="video-js"></video>
<?php include("includes/footer.php") ?>