revivetube update

This commit is contained in:
TheErrorExe 2025-02-25 16:08:44 +01:00
parent e9c12a7ef6
commit 9bef2e5f6f
6 changed files with 349 additions and 26 deletions

3
.gitignore vendored
View file

@ -3,4 +3,5 @@ token.txt
.idea
__pycache__
sigma
nohup.out
nohup.out
cookies.txt

View file

@ -1,3 +1,4 @@
Flask
Requests
yt_dlp
yt_dlp
bs4

View file

@ -22,6 +22,8 @@ import threading
import time
from threading import Thread
from bs4 import BeautifulSoup
import requests
import yt_dlp
from flask import Flask, request, render_template_string, send_file, Response, abort, jsonify
@ -53,6 +55,8 @@ video_status = {}
FILE_SEPARATOR = os.sep
LOADING_TEMPLATE = helper.read_file(f"site_storage{FILE_SEPARATOR}loading_template.html")
CHANNEL_TEMPLATE = helper.read_file(f"site_storage{FILE_SEPARATOR}channel_template.html")
SEARCH_TEMPLATE = helper.read_file(f"site_storage{FILE_SEPARATOR}search_template.html")
os.makedirs(VIDEO_FOLDER, exist_ok=True)
@ -139,29 +143,59 @@ def index():
if query:
response = requests.get(f"https://invidious.materialio.us/api/v1/search?q={query}", timeout=3)
try:
data = response.json()
except ValueError:
return "Can't parse Data. If this Issue persist, report it in the Discord Server.", 500
else:
response = requests.get("https://invidious.materialio.us/api/v1/trending", timeout=3)
if response.status_code == 200 and isinstance(data, list):
try:
data = response.json()
except ValueError:
return "Can't parse Data. If this Issue persists, report it in the Discord Server.", 500
if response.status_code == 200 and isinstance(data, list):
if query:
results = []
for entry in data:
if entry.get("type") == "video":
results.append({
"type": "video",
"id": entry.get("videoId"),
"title": entry.get("title"),
"uploader": entry.get("author", "Unknown"),
"thumbnail": f"/thumbnail/{entry['videoId']}",
"viewCount": entry.get("viewCountText", "Unknown"),
"published": entry.get("publishedText", "Unknown"),
"duration": helper.format_duration(entry.get("lengthSeconds", 0))
})
elif entry.get("type") == "channel":
results.append({
"type": "channel",
"id": entry.get("authorId"),
"title": entry.get("author"),
"thumbnail": entry.get("authorThumbnails")[-1]["url"] if entry.get("authorThumbnails") else "/static/default_channel_thumbnail.jpg",
"subCount": entry.get("subCount", "Unknown"),
"videoCount": entry.get("videoCount", "Unknown")
})
return render_template_string(SEARCH_TEMPLATE, results=results)
else:
results = [
{
"id": entry.get("videoId"),
"title": entry.get("title"),
"uploader": entry.get("author", "Unbekannt"),
"uploader": entry.get("author", "Unknown"),
"thumbnail": f"/thumbnail/{entry['videoId']}",
"viewCount": entry.get("viewCountText", "Unbekannt"),
"published": entry.get("publishedText", "Unbekannt"),
"viewCount": entry.get("viewCountText", "Unknown"),
"published": entry.get("publishedText", "Unknown"),
"duration": helper.format_duration(entry.get("lengthSeconds", 0))
}
for entry in data
if entry.get("videoId")
]
else:
return "No Results or Error in the API.", 404
return render_template_string(INDEX_TEMPLATE, results=results)
else:
return "No Results or Error in the API.", 404
return render_template_string(INDEX_TEMPLATE, results=results)
@app.route("/watch", methods=["GET"])
def watch():
@ -397,6 +431,7 @@ def serve_video(filename):
return send_file(file_path)
@app.route('/channel', methods=['GET'])
def channel_m():
channel_id = request.args.get('channel_id', None)
@ -418,22 +453,48 @@ def channel_m():
if 'entries' not in info:
return "No videos found.", 404
results = [
{
'id': video['id'],
'duration': 'Duration not available on Channel View',
'title': video['title'],
'uploader': info.get('uploader', 'Unknown'),
'thumbnail': f"http://yt.old.errexe.xyz/thumbnail/{video['id']}"
}
for video in info['entries']
]
channel_name = info.get('uploader', 'Unknown')
return render_template_string(INDEX_TEMPLATE, results=results)
invidious_url = f"https://invidious.materialio.us/channel/{channel_id}"
response = requests.get(invidious_url, timeout=10)
if response.status_code != 200:
return "Failed to fetch channel page.", 500
soup = BeautifulSoup(response.text, "html.parser")
profile_div = soup.find(class_="channel-profile")
if profile_div:
img_tag = profile_div.find("img")
if img_tag and "src" in img_tag.attrs:
channel_picture = "http://api.allorigins.win/raw?url=http://invidious.materialio.us" + img_tag["src"]
else:
channel_picture = ""
else:
channel_picture = ""
results = [
{
'id': video['id'],
'duration': 'Duration not available on Channel View',
'title': video['title'],
'uploader': channel_name,
'thumbnail': f"http://yt.old.errexe.xyz/thumbnail/{video['id']}"
}
for video in info['entries']
]
return render_template_string(
CHANNEL_TEMPLATE,
results=results,
channel_name=channel_name,
channel_picture=channel_picture
)
except Exception as e:
return f"An error occurred: {str(e)}", 500
if __name__ == "__main__":
app.run(host="0.0.0.0", debug=True, port=5000)

View file

@ -0,0 +1,132 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>ReviveTube - A YouTube App for the Wii</title>
<style>
a {
color: #3ea6ff;
text-decoration: none;
}
a:hover {
color: #46bbff;
text-decoration: underline;
}
body {
font-family: Arial, sans-serif;
color: #fff;
background-color: #181818;
margin: 0;
padding: 0;
}
.header {
background-color: #202020;
border-bottom:2px solid #2c2c2c;
padding: 10px 20px;
display: flex;
align-items: center;
}
.logo {
font-size: 24px;
color: #fe0000;
font-weight: bold;
}
.search-container {
flex: 1;
text-align: center;
}
.search-bar {
width: 400px;
padding: 8px;
font-size: 16px;
border: 1px solid #313131;
background-color: #121212;
color: #fff;
}
.search-bar:hover {
border: 1px solid #268ee9;
}
.search-button {
padding: 8px 15px;
font-size: 16px;
background-color: #222222;
border:1px solid #3d3d3d;
color: white;
cursor: pointer;
}
.search-button:hover {
border: 1px solid #268ee9;
}
.content {
padding: 20px;
}
.video-grid {
display: flex;
flex-wrap: wrap;
justify-content: center;
}
.video-item {
width: 320px;
margin: 10px;
background-color: #222;
padding: 10px;
}
.video-item img {
width: 100%;
}
.video-item-title {
font-weight: bold;
font-size: 14px;
margin-top: 5px;
}
.video-item-uploader, .video-item-duration {
color: #aaa;
font-size: 12px;
}
</style>
</head>
<body>
<div class="header">
<div class="logo"><img src="../favicon.ico" style="width:32px; height:32px; display:inline; position:relative; top:3px; right:3px; padding-right:2px;"><span style="position:relative; top:-4px; padding-left:5px; border-left:1px solid #323232;">
ReviveTube</span></div>
<div class="search-container">
<form action="/" method="get">
<input class="search-bar" placeholder="Search YouTube" name="query" type="text">
<input type="submit" class="search-button" value="Search">
</form>
</div>
</div>
<div class="content">
{% if results %}
<div>
<img src="{{ channel_picture if channel_picture else 'default_profile.png' }}"
alt="Channel Profile Picture"
style="width: 48px; height: 48px; border-radius: 50%; object-fit: cover; display: inline-block; vertical-align: middle; margin-right: 10px;">
<h2 style="display: inline-block; vertical-align: middle; margin: 0; color: white;">{{ channel_name }}</h2>
</div>
<div class="video-grid">
{% for video in results %}
<div class="video-item">
<a href="/watch?video_id={{ video['id'] }}">
<img alt="{{ video['title'] }}" src="{{ video['thumbnail'] }}">
</a>
<div class="video-item-title">{{ video['title'] }}</div>
<div class="video-item-uploader">By: {{ video['uploader'] }}</div>
</div>
{% endfor %}
</div>
{% endif %}
</div>
<p style="color: red; text-align: center;">ReviveTube - A YouTube App for the Wii</p>
<p style="text-align: center;"><a href="http://revivemii.xyz" target="_blank">Visit the ReviveMii Project</a></p>
<p style="font-size: 12px; text-align: center;">We are NOT affiliated with Nintendo or YouTube.</p>
<p style="text-align: center;">
<a href="https://github.com/ReviveMii/revivetube/" target="_blank">Source Code</a> |
<a href="https://revivemii.errexe.xyz/discord-redirect.html">Discord Server</a> |
<a href="mailto:theerrorexe@gmail.com">Contact</a> |
<a href="/site_storage/credits.html">Credits</a>
</p>
</body>
</html>

View file

@ -98,7 +98,6 @@
</div>
<div class="content">
{% if results %}
<h2>Search Results:</h2>
<div class="video-grid">
{% for video in results %}
<div class="video-item">
@ -123,4 +122,4 @@
<a href="/site_storage/credits.html">Credits</a>
</p>
</body>
</html>
</html>

View file

@ -0,0 +1,129 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>ReviveTube - A YouTube App for the Wii</title>
<style>
a {
color: #3ea6ff;
text-decoration: none;
}
a:hover {
color: #46bbff;
text-decoration: underline;
}
body {
font-family: Arial, sans-serif;
color: #fff;
background-color: #181818;
margin: 0;
padding: 0;
}
.header {
background-color: #202020;
border-bottom:2px solid #2c2c2c;
padding: 10px 20px;
display: flex;
align-items: center;
}
.logo {
font-size: 24px;
color: #fe0000;
font-weight: bold;
}
.search-container {
flex: 1;
text-align: center;
}
.search-bar {
width: 400px;
padding: 8px;
font-size: 16px;
border: 1px solid #313131;
background-color: #121212;
color: #fff;
}
.search-bar:hover {
border: 1px solid #268ee9;
}
.search-button {
padding: 8px 15px;
font-size: 16px;
background-color: #222222;
border:1px solid #3d3d3d;
color: white;
cursor: pointer;
}
.search-button:hover {
border: 1px solid #268ee9;
}
.content {
padding: 20px;
}
.video-grid {
display: flex;
flex-wrap: wrap;
justify-content: center;
}
.video-item {
width: 320px;
margin: 10px;
background-color: #222;
padding: 10px;
}
.video-item img {
width: 100%;
}
.video-item-title {
font-weight: bold;
font-size: 14px;
margin-top: 5px;
}
.video-item-uploader, .video-item-duration {
color: #aaa;
font-size: 12px;
}
</style>
</head>
<body>
<div class="header">
<div class="logo"><img src="../favicon.ico" style="width:32px; height:32px; display:inline; position:relative; top:3px; right:3px; padding-right:2px;"><span style="position:relative; top:-4px; padding-left:5px; border-left:1px solid #323232;">
ReviveTube</span></div>
<div class="search-container">
<form action="/" method="get">
<input class="search-bar" placeholder="Search YouTube" name="query" type="text">
<input type="submit" class="search-button" value="Search">
</form>
</div>
</div>
<div class="content">
{% if results %}
<div class="video-grid">
{% for result in results %}
<div class="video-item">
<a href="{% if result.type == 'video' %}/watch?video_id={{ result.id }}{% else %}/channel?channel_id={{ result.id }}{% endif %}">
<img alt="{{ result.title }}" src="{{ result.thumbnail }}">
</a>
<div class="video-item-title">{{ result.title }}</div>
{% if result.type == 'video' %}
<div class="video-item-uploader">By: {{ result.uploader }}</div>
<div class="video-item-duration">Duration: {{ result.duration }}</div>
{% else %}
<div class="video-item-uploader">Subscribers: {{ result.subCount }}</div>
{% endif %}
</div>
{% endfor %}
</div>
{% endif %}
</div>
<p style="color: red; text-align: center;">ReviveTube - A YouTube App for the Wii</p>
<p style="text-align: center;"><a href="http://revivemii.xyz" target="_blank">Visit the ReviveMii Project</a></p>
<p style="font-size: 12px; text-align: center;">We are NOT affiliated with Nintendo or YouTube.</p>
<p style="text-align: center;">
<a href="https://github.com/ReviveMii/revivetube/" target="_blank">Source Code</a> |
<a href="https://revivemii.errexe.xyz/discord-redirect.html">Discord Server</a> |
<a href="mailto:theerrorexe@gmail.com">Contact</a> |
<a href="/site_storage/credits.html">Credits</a>
</p>
</body>
</html>