mirror of
https://github.com/ReviveMii/revivetube
synced 2025-04-29 04:29:25 -04:00
revivetube update
This commit is contained in:
parent
e9c12a7ef6
commit
9bef2e5f6f
6 changed files with 349 additions and 26 deletions
1
.gitignore
vendored
1
.gitignore
vendored
|
@ -4,3 +4,4 @@ token.txt
|
|||
__pycache__
|
||||
sigma
|
||||
nohup.out
|
||||
cookies.txt
|
|
@ -1,3 +1,4 @@
|
|||
Flask
|
||||
Requests
|
||||
yt_dlp
|
||||
bs4
|
|
@ -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)
|
||||
else:
|
||||
response = requests.get("https://invidious.materialio.us/api/v1/trending", timeout=3)
|
||||
|
||||
try:
|
||||
data = response.json()
|
||||
except ValueError:
|
||||
return "Can't parse Data. If this Issue persist, report it in the Discord Server.", 500
|
||||
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")
|
||||
]
|
||||
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
|
||||
|
||||
channel_name = info.get('uploader', 'Unknown')
|
||||
|
||||
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': info.get('uploader', 'Unknown'),
|
||||
'uploader': channel_name,
|
||||
'thumbnail': f"http://yt.old.errexe.xyz/thumbnail/{video['id']}"
|
||||
}
|
||||
for video in info['entries']
|
||||
]
|
||||
|
||||
return render_template_string(INDEX_TEMPLATE, results=results)
|
||||
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)
|
||||
|
|
132
site_storage/channel_template.html
Normal file
132
site_storage/channel_template.html
Normal 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>
|
|
@ -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">
|
||||
|
|
129
site_storage/search_template.html
Normal file
129
site_storage/search_template.html
Normal 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>
|
Loading…
Add table
Reference in a new issue