This commit is contained in:
TheErrorExe 2025-02-01 23:13:44 +01:00
parent 3318327b36
commit b8b1944964
10 changed files with 324 additions and 299 deletions

4
.gitignore vendored
View file

@ -1,4 +1,6 @@
token.txt token.txt
.venv .venv
.idea .idea
__pycache__ __pycache__
sigma
nohup.out

View file

@ -1,17 +1,26 @@
# ReviveTube # ReviveTube
# WARNING: before starting the server, remove the -proxy command in revivetube.py
Watch YouTube on your Wii! Watch YouTube on your Wii!
ReviveTube by ReviveMii ReviveTube: http://yt.old.errexe.xyz/
ReviveMii Homepage: https://revivemii.errexe.xyz ReviveMii Homepage: https://revivemii.errexe.xyz
Use it without self hosting: http://yt.old.errexe.xyz/ # Self Hosting
Open Source Software used: http://yt.old.errexe.xyz/licenses.html WARNING: before starting the server, remove the --proxy command in revivetube.py
# Use it yourself Go to https://console.cloud.google.com/ and create a new application with the YouTube Data v3 API.
Go to console.cloud.google.com and create a new application with the youtube data v3 api. paste the api key in token.txt. Install the Requirements in the beginning of revivetube.py. Start revivetube.py
Click on Credentials and click on new, and create a new API Key. Paste the API Key in token.txt
Install the Requirements:
```bash
pip install -r requirements.txt
```
Search for "--proxy" in revivetube.py and remove the command
Start the Server:
```bash
python3 revivetube.py
```

Binary file not shown.

Before

Width:  |  Height:  |  Size: 32 B

After

Width:  |  Height:  |  Size: 61 KiB

BIN
loading.gif Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.4 KiB

View file

@ -1,3 +1,3 @@
Flask==3.1.0 Flask
Requests==2.32.3 Requests
yt_dlp==2024.12.23 yt_dlp

View file

@ -144,59 +144,13 @@ def get_video_comments(video_id, max_results=20):
return comments return comments
except requests.exceptions.RequestException as e: except requests.exceptions.RequestException as e:
print(f"Fehler beim Abrufen der Kommentare: {str(e)}") print(f"Can't fetch Comments: {str(e)}")
return [] return []
@app.route("/switch_wii", methods=["GET"])
def switch_wii():
video_id = request.args.get("video_id")
if not video_id:
return "Missing Video-ID.", 400
headers = {
"User-Agent": "Mozilla/5.0 (Nintendo Wii; U; ; en) Opera/9.30 (Nintendo Wii)"
}
response = requests.get(f"http://localhost:5000/watch?video_id={video_id}", headers=headers, timeout=2)
if response.status_code == 200:
return response.text
else:
return "Can't start DEBUG Mode.", 500
@app.route('/test.swf')
def download_file():
return send_file(
'./test.swf',
mimetype='application/x-shockwave-flash',
as_attachment=True,
download_name='test.swf'
)
@app.route("/switch_n", methods=["GET"])
def switch_n():
video_id = request.args.get("video_id")
if not video_id:
return "Missing Video-ID.", 400
headers = {
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36"
}
response = requests.get(f"http://localhost:5000/watch?video_id={video_id}", headers=headers, timeout=2)
if response.status_code == 200:
return response.text
else:
return "Can't start DEBUG Mode.", 500
@app.route("/", methods=["GET"]) @app.route("/", methods=["GET"])
def index_wiitv(): def index():
query = request.args.get("query") query = request.args.get("query")
results = None results = None
@ -307,14 +261,17 @@ def process_video(video_id):
video_status[video_id] = {"status": "downloading"} video_status[video_id] = {"status": "downloading"}
with tempfile.TemporaryDirectory() as temp_dir: with tempfile.TemporaryDirectory() as temp_dir:
temp_video_path = os.path.join(temp_dir, f"{video_id}.%(ext)s") temp_video_path = os.path.join(temp_dir, f"{video_id}.%(ext)s")
command = [ command = [
"yt-dlp", "yt-dlp",
"-f", "worstvideo+worstaudio",
"--proxy", "http://localhost:4000",
"-o", temp_video_path, "-o", temp_video_path,
f"https://m.youtube.com/watch?v={video_id}" "--proxy", "http://localhost:4000",
"-f", "worstvideo+worstaudio",
f"https://youtube.com/watch?v={video_id}"
] ]
subprocess.run(command, check=True) subprocess.run(command, check=True)

View file

@ -1,116 +1,109 @@
<!DOCTYPE html> <!DOCTYPE html>
<html lang="en"> <html lang="en">
<head> <head>
<meta charset="UTF-8"> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<meta content="width=device-width, initial-scale=1.0" name="viewport">
<title>ReviveTube by ReviveMii</title> <title>ReviveTube by ReviveMii</title>
<style> <style>
body { body {
font-family: 'Arial', sans-serif; font-family: Arial, sans-serif;
color: #fff; color: #fff;
background-color: #181818; background-color: #181818;
margin: 0;
padding: 0;
}
.header {
background-color: #202020;
padding: 10px 20px;
display: flex;
align-items: center;
}
.logo {
font-size: 24px;
color: #ff0000;
font-weight: bold;
}
.search-container {
flex: 1;
text-align: center; text-align: center;
} }
h1 {
color: #ff0000;
font-size: 28px;
margin-bottom: 20px;
}
p, h2 {
font-size: 16px;
margin-bottom: 10px;
}
.search-bar { .search-bar {
width: 300px; width: 400px;
padding: 10px; padding: 8px;
font-size: 16px; font-size: 16px;
border: 1px solid #ccc; border: 1px solid #ccc;
border-radius: 4px; background-color: #121212;
display: block; color: #fff;
margin: 0 auto;
} }
button { .search-button {
padding: 10px 20px; padding: 8px 15px;
font-size: 16px; font-size: 16px;
background-color: #333333; background-color: #303030;
color: white; color: white;
border: none; border: none;
cursor: pointer; cursor: pointer;
border-radius: 4px; }
display: block; .content {
margin: 10px auto; padding: 20px;
}
.video-grid {
display: flex;
flex-wrap: wrap;
justify-content: center;
} }
.video-item { .video-item {
margin-bottom: 20px; width: 320px;
text-align: center; margin: 10px;
background-color: #222;
padding: 10px;
} }
.video-item img { .video-item img {
width: 320px; width: 100%;
height: 180px;
border-radius: 8px;
} }
.video-item-title { .video-item-title {
color: #fff;
font-weight: bold; font-weight: bold;
font-size: 16px;
text-align: center;
}
.video-item-uploader {
color: #ccc;
font-size: 14px; font-size: 14px;
text-align: center;
}
.video-item-duration {
color: #ccc;
font-size: 14px;
text-align: center;
margin-top: 5px; margin-top: 5px;
} }
.dark-mode { .video-item-uploader, .video-item-duration {
background-color: #181818; color: #aaa;
color: #fff; font-size: 12px;
}
.dark-mode a {
color: #1e90ff;
} }
</style> </style>
</head> </head>
<body class="dark-mode" id="page-body"> <body>
<h1>ReviveTube by ReviveMii</h1> <div class="header">
<p>A YouTube App for the Wii</p> <div class="logo">ReviveTube</div>
<form action="/" method="get"> <div class="search-container">
<input class="search-bar" name="query" placeholder="Search YouTube" type="text"> <form action="/" method="get">
<button type="submit">Go</button> <input class="search-bar" name="query" type="text">
</form> <input type="submit" class="search-button" value="Search">
{% if results %} </form>
<h2>Search Results</h2> </div>
<div>
{% for video in results %}
<div class="video-item">
<a href="/watch?video_id={{ video['id'] }}">
<img alt="{{ video['title'] }}" src="{{ video['thumbnail'] }}">
<div class="video-item-title">{{ video['title'] }}</div>
<div class="video-item-uploader">By: {{ video['uploader'] }}</div>
<div class="video-item-duration">Duration: {{ video['duration'] }}</div>
</a>
</div> </div>
{% endfor %} <div class="content">
</div> {% if results %}
{% endif %} <h2>Search Results</h2>
<p><a href="http://revivemii.errexe.xyz" target="_blank">Visit ReviveMii</a></p> <div class="video-grid">
<p style="color: red;">\/ Scroll down \/</p> {% for video in results %}
<p style="font-size: 12px;">We are NOT affiliated with Nintendo or YouTube. This app uses code from Wiinet.xyz. For more <div class="video-item">
information, scroll down to Open Source Software.</p> <a href="/watch?video_id={{ video['id'] }}">
<p style="color: blue">It's recommended to bookmark this page. Some sites may take longer to load.</p> <img alt="{{ video['title'] }}" src="{{ video['thumbnail'] }}">
<a href="http://revivetube.errexe.xyz/revivetube/t-and-p.html">Terms of Service and Privacy Policy (Last Updated: 7. Dec </a>
2024 12:41 CET)</a><br><br> <div class="video-item-title">{{ video['title'] }}</div>
<a href="https://github.com/ReviveMii/revivetube/" target="_blank">Source Code</a><br><br> <div class="video-item-uploader">By: {{ video['uploader'] }}</div>
<a href="http://revivetube.errexe.xyz/discord-redirect.html">Discord Server [Use a Compatible Device]</a> <div class="video-item-duration">Duration: {{ video['duration'] }}</div>
<p>Version: v2 Beta (Sometimes I forget to update the Version Number)</p> </div>
<a href="/licenses.html">Open Source Software Used in This App</a> {% endfor %}
<br> </div>
<a href="mailto:theerrorexe@gmail.com">Contact</a> {% endif %}
<br> </div>
<a href="https://revivemii.errexe.xyz/feedback.html">Report Bugs & Feedback</a> <p style="color: red; text-align: center;">\/ Scroll down \/</p>
<p style="text-align: center;"><a href="http://revivemii.errexe.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://revivetube.errexe.xyz/discord-redirect.html">Discord Server</a> |
<a href="mailto:theerrorexe@gmail.com">Contact</a>
</p>
</body> </body>
</html> </html>

View file

@ -6,8 +6,46 @@
<title>Loading...</title> <title>Loading...</title>
<style> <style>
body { body {
text-align: center;
font-family: Arial, sans-serif; font-family: Arial, sans-serif;
background-color: #181818;
color: white;
margin: 0;
padding: 0;
}
.header {
background-color: #202020;
padding: 10px 20px;
display: flex;
align-items: center;
}
.logo {
font-size: 24px;
color: #ff0000;
font-weight: bold;
}
.search-container {
flex: 1;
text-align: center;
}
.search-bar {
width: 400px;
padding: 8px;
font-size: 16px;
border: 1px solid #ccc;
background-color: #121212;
color: #fff;
}
.search-button {
padding: 8px 15px;
font-size: 16px;
background-color: #303030;
color: white;
border: none;
cursor: pointer;
}
.loading-section {
text-align: center;
margin-top: 20px;
} }
#loadingGif { #loadingGif {
width: 50px; width: 50px;
@ -24,70 +62,86 @@
border: none; border: none;
cursor: pointer; cursor: pointer;
} }
#goButton:disabled { #goButton:disabled {
background-color: gray; background-color: gray;
cursor: not-allowed; cursor: not-allowed;
} }
small {
color: grey;
display: block;
margin-top: 20px;
text-align: center;
}
</style> </style>
</head> </head>
<body> <body>
<h1>Loading</h1> <div class="header">
<img alt="Loading..." id="loadingGif" src="loading.gif"/> <div class="logo">ReviveTube</div>
<p id="progressText">Fetching Info...</p> <div class="search-container">
<button id="goButton" onclick="startVideo()">Go</button> <form action="/" method="get">
<br> <input class="search-bar" name="query" placeholder="Search YouTube" type="text">
<small style="color: grey">Loading Screen will NOT work in Dolphin Emulator.<br><br>Long Video = Longer Download and <input type="submit" class="search-button" value="Search">
Converting.<br><br>For videos longer than 7 minutes, there is a chance that they wont play.</small> </form>
<script type="text/javascript"> </div>
var goButton = document.getElementById('goButton'); </div>
var loadingGif = document.getElementById('loadingGif'); <div class="loading-section">
var progressText = document.getElementById('progressText'); <h1>Loading...</h1>
var videoId = "{{ video_id }}"; <img alt="Loading..." id="loadingGif" src="loading.gif"/>
<p id="progressText">Fetching Info...</p>
<button id="goButton" onclick="startVideo()">Go</button>
<br>
<small>Loading Screen will NOT work in Dolphin Emulator.<br><br>Long Video = Longer Download and Converting.<br><br>For videos longer than 7 minutes, there is a chance that they wont play.</small>
</div>
<script type="text/javascript">
var goButton = document.getElementById('goButton');
var loadingGif = document.getElementById('loadingGif');
var progressText = document.getElementById('progressText');
var videoId = "{{ video_id }}";
function simulateLoading() { function simulateLoading() {
setInterval(checkStatus, 1000); setInterval(checkStatus, 1000);
}
function checkStatus() {
var xhr = new XMLHttpRequest();
xhr.open('GET', '/status/' + videoId, true);
xhr.onreadystatechange = function () {
if (xhr.readyState === 4 && xhr.status === 200) {
var response;
try {
response = eval('(' + xhr.responseText + ')');
} catch (e) {
response = { status: 'error' };
}
updateProgress(response);
}
};
xhr.send();
}
function updateProgress(status) {
if (status.status === 'complete') {
loadingGif.style.display = 'none';
progressText.innerHTML = 'Done!';
goButton.style.display = 'inline';
} else if (status.status === 'downloading') {
progressText.innerHTML = 'The Server is Downloading...';
} else if (status.status === 'converting') {
progressText.innerHTML = 'The Server is Converting video...';
} else if (status.status === 'converting for Wii') {
progressText.innerHTML = 'The Server is Converting for Wii...';
} else {
progressText.innerHTML = 'The Server was unable to process the video! Report the Bug in the Discord Server. <br> Error Details for Developers: {{ video_id }}_unable_1.<br>Discord Server on ReviveMii Homepage Footer';
} }
}
function startVideo() { function checkStatus() {
window.location.href = '/watch?video_id=' + videoId; var xhr = new XMLHttpRequest();
} xhr.open('GET', '/status/' + videoId, true);
xhr.onreadystatechange = function () {
if (xhr.readyState === 4 && xhr.status === 200) {
var response;
try {
response = JSON.parse(xhr.responseText);
} catch (e) {
response = { status: 'error' };
}
updateProgress(response);
}
};
xhr.send();
}
window.onload = function () { function updateProgress(status) {
simulateLoading(); if (status.status === 'complete') {
}; loadingGif.style.display = 'none';
</script> progressText.innerHTML = 'Done!';
goButton.style.display = 'inline';
} else if (status.status === 'downloading') {
progressText.innerHTML = 'The Server is Downloading...';
} else if (status.status === 'converting') {
progressText.innerHTML = 'The Server is Converting video...';
} else if (status.status === 'converting for Wii') {
progressText.innerHTML = 'The Server is Converting for Wii...';
} else {
progressText.innerHTML = 'The Server was unable to process the video! Report the Bug in the Discord Server. <br> Error Details: Error on Video with ID: {{ video_id }}<br>Discord Server on ReviveMii Homepage Footer';
}
}
function startVideo() {
window.location.href = '/watch?video_id=' + videoId;
}
window.onload = function () {
simulateLoading();
};
</script>
</body> </body>
</html> </html>

View file

@ -1,49 +0,0 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta content="width=device-width, initial-scale=1.0" name="viewport">
<title>{{ title }}</title>
<style>
body { font-family: 'Arial', sans-serif; text-align: center; color: #fff; background-color: #181818; }
video { margin-top: 20px; }
h1 { color: #ff0000; font-size: 24px; }
h3, p { font-size: 16px; }
.comments { text-align: left; margin: 0 auto; width: 80%; font-size: 14px; }
.comment { margin-bottom: 15px; padding: 10px; border-bottom: 1px solid #ddd; }
.comment p { font-size: 14px; }
.dark-mode { background-color: #181818; color: #fff; }
.dark-mode a { color: #1e90ff; }
</style>
</head>
<!-- <body class="dark-mode" id="page-body">
<video width="640" height="360" controls>
<source src="{{ video_mp4 }}" type="video/mp4">
Your browser does not support the video tag.
</video>
<h1>{{ title }}</h1>
<h3>Uploaded by: <a href="/channel?channel_id={{ channelId }}">{{ uploader }}</a></h3>
<p><strong>Views:</strong> {{ viewCount }}</p>
<p><strong>Likes:</strong> {{ likeCount }}</p>
<p><strong>Upload Date:</strong> {{ publishedAt }}</p>
<a href="#comments">Skip Description</a>
<h3>Description:</h3>
<p>{{ description | safe }}</p>
<h3 id="comments" class="comments">Comments:</h3>
<div class="comments">
{% if comments %}
{% for comment in comments %}
<div class="comment">
<p><strong>{{ comment.author }}</strong> posted:</p>
<p>{{ comment.text|safe }}</p>
<p style="color: gray; font-size: 12px;">Likes: {{ comment.likeCount }} | Post date: {{ comment.publishedAt }}</p>
</div>
{% endfor %}
{% else %}
<p>No Comments.</p>
{% endif %}
</div> -->
Please access this Site on a Wii
</body>
</html>

View file

@ -1,68 +1,127 @@
<!DOCTYPE html> <!DOCTYPE html>
<html lang="en"> <html lang="en">
<head> <head>
<meta charset="UTF-8"> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<meta content="width=device-width, initial-scale=1.0" name="viewport">
<title>{{ title }}</title> <title>{{ title }}</title>
<style> <style>
body { body {
font-family: 'Arial', sans-serif; font-family: Arial, sans-serif;
text-align: center; /* Zentriert den Text */
color: #fff; color: #fff;
background-color: #181818; background-color: #181818;
margin: 0;
padding: 0;
} }
.dark-mode { .header {
background-color: #181818; background-color: #202020;
padding: 10px 20px;
display: flex;
align-items: center;
}
.logo {
font-size: 24px;
color: #ff0000;
font-weight: bold;
}
.search-container {
flex: 1;
text-align: center;
}
.search-bar {
width: 400px;
padding: 8px;
font-size: 16px;
border: 1px solid #ccc;
background-color: #121212;
color: #fff; color: #fff;
} }
.dark-mode a { .search-button {
color: #1e90ff; padding: 8px 15px;
font-size: 16px;
background-color: #303030;
color: white;
border: none;
cursor: pointer;
}
.content {
padding: 20px;
text-align: center;
}
.video-container {
background-color: #000;
text-align: center;
padding: 10px;
}
.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;
} }
.comments { .comments {
margin: 0 auto; margin: 0 auto;
width: 80%; width: 80%;
} text-align: left;
h1 {
color: red;
text-align: center;
}
h3 {
color: white;
text-align: center;
} }
</style> </style>
<script src="https://unpkg.com/@ruffle-rs/ruffle"></script> <script src="https://unpkg.com/@ruffle-rs/ruffle"></script>
</head> </head>
<body class="dark-mode" id="page-body"> <body>
<div style="width: 100%; background-color: #000; text-align: center;"> <div class="header">
<object data="/player.swf" height="256" type="application/x-shockwave-flash" width="384"> <div class="logo">ReviveTube</div>
<param name="wmode" value="transparent"> <div class="search-container">
<param name="allowFullScreen" value="false"> <form action="/" method="get">
<param name="flashvars" value="filename={{ video_flv }}"> <input class="search-bar" name="query" type="text">
</object> <input type="submit" class="search-button" value="Search">
</div> </form>
<h1 style="color: red">{{ title }}</h1> </div>
<h3>Uploaded by: <a href="/channel?channel_id={{ channelId }}">{{ uploader }}</a></h3> </div>
<p><strong>Views:</strong> {{ viewCount }}</p> <div class="content">
<p><strong>Likes:</strong> {{ likeCount }}</p> <div class="video-container">
<p><strong>Upload Date:</strong> {{ publishedAt }}</p> <object data="/player.swf" height="256" type="application/x-shockwave-flash" width="384">
<a href="#comments">Skip Description</a> <param name="wmode" value="transparent">
<h3 style="color: red">Description:</h3> <param name="allowFullScreen" value="false">
<p>{{ description | safe }}</p> <param name="flashvars" value="filename={{ video_flv }}">
<h3 class="comments" id="comments" style="color: red">Comments:</h3> </object>
<div class="comments"> </div>
{% if comments %} <h1 style="color: red">{{ title }}</h1>
{% for comment in comments %} <h3>Uploaded by: <a href="/channel?channel_id={{ channelId }}">{{ uploader }}</a></h3>
<div class="comment"> <p><strong>Views:</strong> {{ viewCount }}</p>
<p><strong>{{ comment.author }}</strong> posted:</p> <p><strong>Likes:</strong> {{ likeCount }}</p>
<p>{{ comment.text|safe }}</p> <p><strong>Upload Date:</strong> {{ publishedAt }}</p>
<p style="color: gray; font-size: 12px;">Likes: {{ comment.likeCount }} | Post date: {{ comment.publishedAt <a href="#comments">Skip Description</a>
}}</p> <h3 style="color: red">Description:</h3>
<p>{{ description | safe }}</p>
<h3 class="comments" id="comments" style="color: red">Comments:</h3>
<div class="comments">
{% if comments %}
{% for comment in comments %}
<div class="comment">
<p><strong>{{ comment.author }}</strong> posted:</p>
<p>{{ comment.text|safe }}</p>
<p style="color: gray; font-size: 12px;">Likes: {{ comment.likeCount }} | Post date: {{ comment.publishedAt }}</p>
</div>
{% endfor %}
{% else %}
<p>No Comments.</p>
{% endif %}
</div>
</div> </div>
{% endfor %}
{% else %}
<p>No Comments.</p>
{% endif %}
</div>
</body> </body>
</html> </html>