from flask import Flask, request, render_template_string, send_file import requests import subprocess import os import threading import time import shutil # Flask-Setup app = Flask(__name__) # API-Schlüssel aus token.txt laden with open("token.txt", "r") as f: YOUTUBE_API_KEY = f.read().strip() # Konstanten YOUTUBE_SEARCH_URL = "https://www.googleapis.com/youtube/v3/search" RIITUBE_BASE_URL = "https://riitube.rc24.xyz/" VIDEO_FOLDER = "videos" # Videos-Ordner erstellen, falls nicht vorhanden os.makedirs(VIDEO_FOLDER, exist_ok=True) # Maximum size limits (1 GB and 5 GB) MAX_VIDEO_SIZE = 1 * 1024 * 1024 * 1024 # 1 GB MAX_FOLDER_SIZE = 5 * 1024 * 1024 * 1024 # 5 GB # Helper function to calculate the total size of the folder def get_folder_size(path): total_size = 0 for dirpath, dirnames, filenames in os.walk(path): for f in filenames: file_path = os.path.join(dirpath, f) total_size += os.path.getsize(file_path) return total_size # Function to periodically delete videos every 5 minutes def delete_videos_periodically(): while True: time.sleep(86400) # 5 minutes for filename in os.listdir(VIDEO_FOLDER): file_path = os.path.join(VIDEO_FOLDER, filename) if os.path.isfile(file_path): os.remove(file_path) print(f"Deleted: {file_path}") # Start the periodic deletion in a separate thread threading.Thread(target=delete_videos_periodically, daemon=True).start() # HTML-Templates als Strings INDEX_TEMPLATE = """ ReviveTube by ReviveMii

ReviveTube by ReviveMii

{% if results %}

Search Results

{% endif %}
Visit ReviveMii

This app uses the RiiConnect24 WiiMC API. We are NOT afiliated with RiiConnect24, Nintendo or YouTube. This app is using Code from Wiinet.xyz.

It's recommend to bookmark this Page

It's normal that Sites take long to load

Version: v0.0.7 Beta

""" WATCH_STANDARD_TEMPLATE = """ {{ title }}

{{ title }}

Uploaded by: {{ uploader }}

Description:

{{ description }}

""" WATCH_WII_TEMPLATE = """ {{ title }}

If the video does not play smoothly, restart the Internet Channel by pressing the Home button and then Reset. It's a bug. It happens if you visit too many Sites

{{ title }}

Uploaded by: {{ uploader }}

Description:

{{ description }}

""" @app.route("/", methods=["GET"]) def index(): query = request.args.get("query") results = None if query: # YouTube API aufrufen params = { "part": "snippet", "q": query, "type": "video", "maxResults": 10, "key": YOUTUBE_API_KEY, } response = requests.get(YOUTUBE_SEARCH_URL, params=params, timeout=3) data = response.json() # Ergebnisse verarbeiten if response.status_code == 200 and "items" in data: results = [ { "id": item["id"]["videoId"], "title": item["snippet"]["title"], "uploader": item["snippet"]["channelTitle"], "thumbnail": f"/thumbnail/{item['id']['videoId']}", } for item in data.get("items", []) ] return render_template_string(INDEX_TEMPLATE, results=results) @app.route("/video_metadata/") def video_metadata(video_id): # Metadaten aus der YouTube-API abrufen params = { "part": "snippet", "id": video_id, "key": YOUTUBE_API_KEY, } response = requests.get(YOUTUBE_SEARCH_URL.replace("search", "videos"), params=params, timeout=3) if response.status_code != 200: return {"error": "Failed to fetch metadata"}, 500 data = response.json() if "items" not in data or not data["items"]: return {"error": "No metadata found"}, 404 video_data = data["items"][0]["snippet"] return { "title": video_data["title"], "uploader": video_data["channelTitle"], "description": video_data["description"], } @app.route("/watch", methods=["GET"]) def watch(): video_id = request.args.get("video_id") if not video_id: return "Missing video ID.", 400 # Metadaten abrufen metadata_response = requests.get(f"http://127.0.0.1:5000/video_metadata/{video_id}") if metadata_response.status_code != 200: return f"Failed to fetch video metadata: {metadata_response.text}", 500 metadata = metadata_response.json() # User-Agent prüfen user_agent = request.headers.get("User-Agent", "").lower() is_wii = "wii" in user_agent and "wiiu" not in user_agent # Video-Pfade video_mp4_path = os.path.join(VIDEO_FOLDER, f"{video_id}.mp4") video_flv_path = os.path.join(VIDEO_FOLDER, f"{video_id}.flv") # Video herunterladen, falls nicht vorhanden if not os.path.exists(video_mp4_path): video_url = f"{RIITUBE_BASE_URL}video/wii/?q={video_id}" try: response = requests.get(video_url, stream=True, timeout=10) if response.status_code != 200: return f"Failed to download video. HTTP Status: {response.status_code}, Reason: {response.reason}", 500 # Check file size during download total_size = 0 with open(video_mp4_path, "wb") as f: for chunk in response.iter_content(chunk_size=8192): f.write(chunk) total_size += len(chunk) if total_size > MAX_VIDEO_SIZE: os.remove(video_mp4_path) return "Video exceeds 1 GB in size.", 400 except requests.exceptions.RequestException as e: return f"An error occurred while downloading the video: {str(e)}", 500 # Für Wii in FLV umwandeln if is_wii and not os.path.exists(video_flv_path): try: subprocess.run( [ "ffmpeg", "-i", video_mp4_path, "-ar", "22050", "-f", "flv", "-s", "320x240", "-ab", "32k", "-filter:v", "fps=fps=15", video_flv_path ], check=True ) except subprocess.CalledProcessError as e: return f"Failed to convert video. Try reloading the Page. Error: {str(e)}", 500 # Passendes Template rendern if is_wii: return render_template_string(WATCH_WII_TEMPLATE, video_flv=f"/videos/{video_id}.flv", **metadata) else: return render_template_string(WATCH_STANDARD_TEMPLATE, video_mp4=f"/videos/{video_id}.mp4", **metadata) @app.route("/") def serve_static(filename): return send_file(os.path.join(filename)) @app.route("/thumbnail/") def get_thumbnail(video_id): thumbnail_url = f"https://img.youtube.com/vi/{video_id}/hqdefault.jpg" try: # Thumbnail von YouTube abrufen response = requests.get(thumbnail_url, stream=True, timeout=5) if response.status_code == 200: # Content-Type weiterleiten return send_file( response.raw, mimetype=response.headers.get("Content-Type", "image/jpeg"), as_attachment=False, ) else: return f"Failed to fetch thumbnail. Status: {response.status_code}", 500 except requests.exceptions.RequestException as e: return f"Error fetching thumbnail: {str(e)}", 500 if __name__ == "__main__": app.run(debug=True)