- added web front end page
This commit is contained in:
iceyrazor 2025-07-30 15:59:59 -05:00
parent 2356a1b130
commit 08973c0191
8 changed files with 161 additions and 0 deletions

2
.gitignore vendored
View File

@ -5,3 +5,5 @@ thumberr.txt
thumbnails/**
vids/**
title_vids/**
web/ytlist/sql-wasm.js
web/ytlist/sql-wasm.wasm

View File

@ -5,6 +5,8 @@
A simplish set of bash scripts to have a locally stored youtube playlist using fzf and sqlite3 with thumbnails
there is also a web frontend in ``web``
Technically you can modify this to store anything other than just yt videos
![noimg](https://github.com/iceyrazor/youtube-playlist-cli/blob/main/example.png?raw=true)

17
web/README.md Normal file
View File

@ -0,0 +1,17 @@
# the web page
this isnt perfect takes longer to load the more there is.
![noimg](https://github.com/iceyrazor/youtube-playlist-cli/blob/main/web/example-web.png?raw=true)
- download [https://github.com/sql-js/sql.js/releases/tag/v1.13.0](https://github.com/sql-js/sql.js/releases/tag/v1.13.0) sql-wasm.js and sql-wasm.wasm
- put both files in web/ytlist
- get some sort of webserver. (tis free. i reccomend caddy)
- either
- download rsync
- edit upload-web.sh to your server target directory or ssh
- run upload-web.sh
- or
- copy all the files in web/ytlist and ytlist.html to your webserver
- then copy thumbnails directory to your webserver/ytlist
- goto webpage /ytlist.html

BIN
web/example-web.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 377 KiB

6
web/upload-web.sh Executable file
View File

@ -0,0 +1,6 @@
cd "$(dirname "$0")"
rsync -Ra --progress ./ytlist.html ./ytlist/ serv:~/servers/local_html
cd ../
rsync -Ra --progress ./thumbnails serv:~/servers/local_html/ytlist/

20
web/ytlist.html Normal file
View File

@ -0,0 +1,20 @@
<!DOCTYPE html>
<html>
<head>
<link rel="stylesheet" href="/ytlist/ytlist.css" />
</head>
<body>
<script src='/ytlist/sql-wasm.js'></script>
<script src='/ytlist/ytlist.js'></script>
<div id="search_box">
leave blank for seaching all<br>
query: <input id="search_in"></input><br>
category
<div id="category_box">
<input type="radio" name="category_choice" value="ALL" checked> ALL<br>
</div>
<button onclick="search()">search</button><br>
</div>
<div id="the_box"></div>
</body>
</html>

35
web/ytlist/ytlist.css Normal file
View File

@ -0,0 +1,35 @@
a:link {
text-decoration: none;
}
a:visited {
text-decoration: none;
}
a:hover {
text-decoration: none;
}
a:active {
text-decoration: none;
}
#the_box{
display: grid;
grid-template-columns: 1fr 1fr 1fr 1fr;
grid-gap: 5px;
}
#the_box img {
width: 100%;
}
.video-title, .video-channelname{
text-decoration: none;
color: #222222;
}
.video-title{
font-size: 24px
}

79
web/ytlist/ytlist.js Normal file
View File

@ -0,0 +1,79 @@
function insert_item(item,imgurl){
the_box.innerHTML+=`<div>
<a href="https://youtube.com/watch?v=${item[2]}" target="_BLANK">
<span class="video-title">${item[0]}: ${item[1]}</span>
<span class="video-channelname">${item[3]}</span>
<br>
<img src="${imgurl}"></img>
</a>
</div>`
}
function get_item(item){
fetch(`/ytlist/thumbnails/${item[2]}.webp`,
{ method: "HEAD" }
).then((res) => {
if (res.ok) {
insert_item(item,res.url);
} else {
fetch(`/ytlist/thumbnails/${item[2]}.jpg`,
{ method: "HEAD" }
).then((res) => {
if (res.ok) {
insert_item(item,res.url);
} else {
console.log("no");
}
});
}
});
}
async function search(){
const sqlPromise = initSqlJs({
locateFile: file => `/ytlist/${file}`
});
const dataPromise = fetch("/ytlist/youtube_stuffs.db").then(res => res.arrayBuffer());
const [SQL, buf] = await Promise.all([sqlPromise, dataPromise])
const db = new SQL.Database(new Uint8Array(buf));
//search_box.style.display="none";
category=document.querySelector('input[name="category_choice"]:checked').value;
let query="SELECT rowid,* FROM ytlist"
if (category!="ALL"){
query+=` WHERE category='${category}'`
if (search_in.value != ""){
query+=` AND title LIKE '%${search_in.value}%'`
}
} else if (search_in.value != ""){
query+=` WHERE title LIKE '%${search_in.value}%'`
}
let res = db.exec(query);
the_box.innerHTML="";
res[0].values.forEach(item=>{get_item(item)});
}
async function init(){
const sqlPromise = initSqlJs({
locateFile: file => `/ytlist/${file}`
});
const dataPromise = fetch("/ytlist/youtube_stuffs.db").then(res => res.arrayBuffer());
const [SQL, buf] = await Promise.all([sqlPromise, dataPromise])
const db = new SQL.Database(new Uint8Array(buf));
const res = db.exec("SELECT category FROM ytlist");
let categories=[]
res[0].values.forEach(item=>{
if (categories.indexOf(item[0]) < 0) {
categories.push(item[0]);
category_box.innerHTML+=`<input type="radio" name="category_choice" value="${item[0]}"> ${item[0]}<br>`
}
})
}
init()