pub / yt2html

Fetches Youtube content via RSS and provides a chronological timeline
git clone https://src.jayvii.de/pub/yt2html.git
Home | Log | Files | Exports | Refs | README | RSS

commit d6a68a32f07f3a2bdc31281613a045b985b7b060
parent db796ed554ac770d42e9e99a2e7a5aa0d2730deb
Author: JayVii <jayvii[AT]posteo[DOT]de>
Date:   Tue, 22 Oct 2024 11:44:32 +0200

feat: process for editing channel list is now more intuitive

Diffstat:
Massets/css/custom.css | 6++++--
Massets/js/yt.js | 45+++++++++++++++++++++++++++++++++++++++++++++
Mindex.php | 141++++++++++++++++++++++++++++++++++++++++++++++++++++++++++---------------------
3 files changed, 153 insertions(+), 39 deletions(-)

diff --git a/assets/css/custom.css b/assets/css/custom.css @@ -27,9 +27,8 @@ a.button:hover display: none; } -textarea[name=channels] { +input { width: 100%; - min-height: 400px; } @media only screen and (width<=720px) { @@ -44,3 +43,6 @@ a[href^="https"]:where([href*="www.youtube.com"])::after { content: " \2197"; } +.error { + background-color: red; +} diff --git a/assets/js/yt.js b/assets/js/yt.js @@ -53,3 +53,48 @@ function yt2html_toggle_player(index, video) { } } + +function yt2html_update_channels_list() { + + // Initilise channels array + var channels = []; + + // Fetch channel input fields + var channels_obj = document.querySelectorAll(".channels_input"); + channels_obj.forEach(function(x) { + if (x.value != "") { + channels.push(x.value); + } + }); + + // If last input field has a value, add a new (empty) one to the list, so the + // user can continue with input + if (channels_obj[channels_obj.length - 1].value != "") { + yt2html_add_channels_input(channels_obj.length); + } + + // join channels array + channels = channels.join(","); + + // insert array into hidden "channels" field + document.querySelector("input[name=channels]").value = channels; +} + +function yt2html_add_channels_input(index) { + + // Create label object + var label = document.createElement("label"); + label.for = "channel_" + index; + label.innerHTML = "<mark>Add a new channel here</mark>"; + + // Create input object + var input = document.createElement("input"); + input.name = "channel_" + index; + input.classList.add("channels_input"); + input.type = "text"; + input.oninput = "yt2html_update_channels_list();"; + + // Append label and input objects + document.getElementById("channels_list").append(label); + document.getElementById("channels_list").append(input); +} diff --git a/index.php b/index.php @@ -39,7 +39,11 @@ ); /* Initilise channels array */ - $channels = array(); + $channels = array( + "aid" => array(), + "author" => array(), + "error" => array() + ); /* Initilise videos array */ $videos = array(); @@ -48,32 +52,36 @@ // Cookie should have lowest priority (fallback), POST first (intend) // GET arguments are used for one-time usage (will not set cookie) if (!is_null($_COOKIE["channels"])) { - $channels = explode(",", $_COOKIE["channels"]); + $channels["aid"] = explode(",", $_COOKIE["channels"]); } if (!is_null($_POST["channels"])) { - $channels = urldecode($_POST["channels"]); - $channels = preg_replace('/[^A-Za-z0-9\-\_\,]+/', '', $channels); - $channels = explode(",", $channels); + $channels["aid"] = urldecode($_POST["channels"]); + $channels["aid"] = preg_replace( + '/[^A-Za-z0-9\-\_\,]+/', + '', + $channels["aid"] + ); + $channels["aid"] = explode(",", $channels["aid"]); } if (!is_null($_GET["channels"])) { - $channels = explode(",", $_GET["channels"]); + $channels["aid"] = explode(",", $_GET["channels"]); } // Sort channels by alphabet and ensure each stream is unique - $channels = array_unique($channels); + $channels["aid"] = array_unique($channels["aid"]); /* refresh cookie */ if (is_null($_GET["channels"])) { header( "Set-Cookie: " . - "channels=" . implode(",", $channels) . ";" . + "channels=" . implode(",", $channels["aid"]) . ";" . "Max-Age=" . 31536000 . "; " . /* 60 x 60 x 24 x 365 = 1 year */ "Domain=" . $_SERVER["SERVER_NAME"] . "; " . "SameSite=Strict;" ); } - foreach ($channels as $channel) { + foreach ($channels["aid"] as $channel) { // Fetch Youtube XML Feed $channel_xml = file( @@ -82,6 +90,10 @@ /* Skip to next entry, if channel could not be found */ if ($channel_xml === false) { + /* Add dummy values to channels array and mark as error */ + array_push($channels["author"], ""); + array_push($channels["error"], true); + /* Skip item within loop */ continue; } @@ -100,6 +112,14 @@ $channel_xml = json_encode($channel_xml); $channel_xml = json_decode($channel_xml, true); + // Get Channel name + $author = str_replace( + array("&"), + "&amp;", + $channel_xml["entry"][0]["author"]["name"] + ); + array_push($channels["author"], $author); + // Process Entries foreach ($channel_xml["entry"] as $entry) { @@ -126,22 +146,16 @@ $video["aid"] = $channel; // Get Channel Name - $author = str_replace( - array("&"), - "&amp;", - $entry["author"]["name"] - ); - $video["author"] = str_replace( - array("&"), - "&amp;", - $entry["author"]["name"] - ); + $video["author"] = $author; /* Add video to videos array */ array_push($videos, $video); } + /* Mark as successful in channels array */ + array_push($channels["error"], false); + } /* Sort videos array */ @@ -149,12 +163,24 @@ ?> - <body onload="setThumbnails();"> + <body> <header> <nav> <a href="/">All Videos</a> - <a href="#" onclick="window.location.reload();">Refresh</a> + <?php + /* For GET-requests, draw simple reload button, + * otherwise re-submit channels form + */ + if (is_null($_GET["channels"])) { + $jsfun = "document.getElementById('channel_form').submit();"; + } else { + $jsfun = "window.location.reload();"; + } + ?> + <a href="#" onclick="<?php echo $jsfun; ?>"> + Refresh + </a> <a href="https://src.jayvii.de/pub/yt2html" target="_blank"> Development </a> @@ -163,27 +189,68 @@ </header> <form action="https://www.youtube.com/results" method="GET"> - <input - id="searchbar" - type="text" - id="searchInput" - name="search_query" - placeholder="Search on YouTube..." - > + <input + id="searchbar" + type="text" + id="searchInput" + name="search_query" + placeholder="Search on YouTube..." + > </form> <!-- Channels List Form --> <details id="channels"> <summary>List of Channels</summary> - <p> - Please enter the YouTube channel-IDs you want to check here, each - separated with a <code>,</code>: - </p> - <form action="/" method="POST"> - <textarea - name="channels" - placeholder="channelid1, channelid1, ..." - ><?php echo implode("," . PHP_EOL, $channels); ?></textarea> + <form action="/" method="POST" id="channel_form"> + <details> + <summary>Import / Export</summary> + <p> + Please enter the YouTube channel-IDs you want to check here, each + separated with a <code>,</code>: + </p> + <input + name="channels" + type="text" + value="<?php echo implode("," . PHP_EOL, $channels["aid"]); ?>" + > + </details> + <div id="channels_list"> + <?php + /* Draw Input fields for each channel ID */ + for ($i = 0; $i < count($channels["aid"]); $i++) { + ?> + <label for="channel_<?php echo $i; ?>"> + <?php + if ($channels["author"][$i] != "") { + echo "<a href=\"/?channels=" . $channels["aid"][$i] . + "\" target=\"_blank\">" . $channels["author"][$i] . "</a>"; + } else { + echo "<mark class=\"error\">Error</mark>"; + } + ?> + </label> + <input + name="channel_<?php echo $i; ?>" + class="channels_input" + type="text" + value="<?php echo $channels["aid"][$i]; ?>" + oninput="yt2html_update_channels_list();" + > + <?php + } + ?> + <!-- Draw one empty input field for new entry by the user --> + <label for="channel_<?php echo ($i); ?>"> + <mark>Add a new channel here</mark> + </label> + <input + name="channel<?php echo ($i); ?>" + class="channels_input" + type="text" + oninput="yt2html_update_channels_list();" + > + </div> + <!-- Submit Button --> <input type="submit" value="Submit &amp; Reload"> </form> </details>