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

2
.gitignore vendored
View file

@ -2,3 +2,5 @@ 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> </div>
<div class="content">
{% if results %}
<h2>Search Results</h2>
<div class="video-grid">
{% for video in results %} {% for video in results %}
<div class="video-item"> <div class="video-item">
<a href="/watch?video_id={{ video['id'] }}"> <a href="/watch?video_id={{ video['id'] }}">
<img alt="{{ video['title'] }}" src="{{ video['thumbnail'] }}"> <img alt="{{ video['title'] }}" src="{{ video['thumbnail'] }}">
</a>
<div class="video-item-title">{{ video['title'] }}</div> <div class="video-item-title">{{ video['title'] }}</div>
<div class="video-item-uploader">By: {{ video['uploader'] }}</div> <div class="video-item-uploader">By: {{ video['uploader'] }}</div>
<div class="video-item-duration">Duration: {{ video['duration'] }}</div> <div class="video-item-duration">Duration: {{ video['duration'] }}</div>
</a>
</div> </div>
{% endfor %} {% endfor %}
</div> </div>
{% endif %} {% endif %}
<p><a href="http://revivemii.errexe.xyz" target="_blank">Visit ReviveMii</a></p> </div>
<p style="color: red;">\/ Scroll down \/</p> <p style="color: red; text-align: center;">\/ Scroll down \/</p>
<p style="font-size: 12px;">We are NOT affiliated with Nintendo or YouTube. This app uses code from Wiinet.xyz. For more <p style="text-align: center;"><a href="http://revivemii.errexe.xyz" target="_blank">Visit the ReviveMii Project</a></p>
information, scroll down to Open Source Software.</p> <p style="font-size: 12px; text-align: center;">We are NOT affiliated with Nintendo or YouTube.</p>
<p style="color: blue">It's recommended to bookmark this page. Some sites may take longer to load.</p> <p style="text-align: center;">
<a href="http://revivetube.errexe.xyz/revivetube/t-and-p.html">Terms of Service and Privacy Policy (Last Updated: 7. Dec <a href="https://github.com/ReviveMii/revivetube/" target="_blank">Source Code</a> |
2024 12:41 CET)</a><br><br> <a href="https://revivetube.errexe.xyz/discord-redirect.html">Discord Server</a> |
<a href="https://github.com/ReviveMii/revivetube/" target="_blank">Source Code</a><br><br> <a href="mailto:theerrorexe@gmail.com">Contact</a>
<a href="http://revivetube.errexe.xyz/discord-redirect.html">Discord Server [Use a Compatible Device]</a> </p>
<p>Version: v2 Beta (Sometimes I forget to update the Version Number)</p>
<a href="/licenses.html">Open Source Software Used in This App</a>
<br>
<a href="mailto:theerrorexe@gmail.com">Contact</a>
<br>
<a href="https://revivemii.errexe.xyz/feedback.html">Report Bugs & Feedback</a>
</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;
@ -28,17 +66,33 @@
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>
</div>
<div class="loading-section">
<h1>Loading...</h1>
<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 goButton = document.getElementById('goButton');
var loadingGif = document.getElementById('loadingGif'); var loadingGif = document.getElementById('loadingGif');
var progressText = document.getElementById('progressText'); var progressText = document.getElementById('progressText');
@ -55,7 +109,7 @@
if (xhr.readyState === 4 && xhr.status === 200) { if (xhr.readyState === 4 && xhr.status === 200) {
var response; var response;
try { try {
response = eval('(' + xhr.responseText + ')'); response = JSON.parse(xhr.responseText);
} catch (e) { } catch (e) {
response = { status: 'error' }; response = { status: 'error' };
} }
@ -77,7 +131,7 @@
} else if (status.status === 'converting for Wii') { } else if (status.status === 'converting for Wii') {
progressText.innerHTML = 'The Server is Converting for Wii...'; progressText.innerHTML = 'The Server is Converting for Wii...';
} else { } 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'; 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';
} }
} }
@ -88,6 +142,6 @@
window.onload = function () { window.onload = function () {
simulateLoading(); simulateLoading();
}; };
</script> </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">
<div class="logo">ReviveTube</div>
<div class="search-container">
<form action="/" method="get">
<input class="search-bar" name="query" type="text">
<input type="submit" class="search-button" value="Search">
</form>
</div>
</div>
<div class="content">
<div class="video-container">
<object data="/player.swf" height="256" type="application/x-shockwave-flash" width="384"> <object data="/player.swf" height="256" type="application/x-shockwave-flash" width="384">
<param name="wmode" value="transparent"> <param name="wmode" value="transparent">
<param name="allowFullScreen" value="false"> <param name="allowFullScreen" value="false">
<param name="flashvars" value="filename={{ video_flv }}"> <param name="flashvars" value="filename={{ video_flv }}">
</object> </object>
</div> </div>
<h1 style="color: red">{{ title }}</h1> <h1 style="color: red">{{ title }}</h1>
<h3>Uploaded by: <a href="/channel?channel_id={{ channelId }}">{{ uploader }}</a></h3> <h3>Uploaded by: <a href="/channel?channel_id={{ channelId }}">{{ uploader }}</a></h3>
<p><strong>Views:</strong> {{ viewCount }}</p> <p><strong>Views:</strong> {{ viewCount }}</p>
<p><strong>Likes:</strong> {{ likeCount }}</p> <p><strong>Likes:</strong> {{ likeCount }}</p>
<p><strong>Upload Date:</strong> {{ publishedAt }}</p> <p><strong>Upload Date:</strong> {{ publishedAt }}</p>
<a href="#comments">Skip Description</a> <a href="#comments">Skip Description</a>
<h3 style="color: red">Description:</h3> <h3 style="color: red">Description:</h3>
<p>{{ description | safe }}</p> <p>{{ description | safe }}</p>
<h3 class="comments" id="comments" style="color: red">Comments:</h3> <h3 class="comments" id="comments" style="color: red">Comments:</h3>
<div class="comments"> <div class="comments">
{% if comments %} {% if comments %}
{% for comment in comments %} {% for comment in comments %}
<div class="comment"> <div class="comment">
<p><strong>{{ comment.author }}</strong> posted:</p> <p><strong>{{ comment.author }}</strong> posted:</p>
<p>{{ comment.text|safe }}</p> <p>{{ comment.text|safe }}</p>
<p style="color: gray; font-size: 12px;">Likes: {{ comment.likeCount }} | Post date: {{ comment.publishedAt <p style="color: gray; font-size: 12px;">Likes: {{ comment.likeCount }} | Post date: {{ comment.publishedAt }}</p>
}}</p>
</div> </div>
{% endfor %} {% endfor %}
{% else %} {% else %}
<p>No Comments.</p> <p>No Comments.</p>
{% endif %} {% endif %}
</div> </div>
</div>
</body> </body>
</html> </html>