diff --git a/betaserver.py b/betaserver.py deleted file mode 100644 index 3e12ba2..0000000 --- a/betaserver.py +++ /dev/null @@ -1,352 +0,0 @@ -from flask import Flask, request, render_template_string, send_file, Response, abort -import requests -import subprocess -import os -import threading -import time - -# Flask-Setup -app = Flask(__name__) - -# Konstanten -RIITUBE_BASE_URL = "https://riitube.rc24.xyz/" -VIDEO_FOLDER = "sigma/videos" -API_BASE_URL = "https://y.com.sb/api/v1/" -YOUTUBE_API_URL = "https://www.googleapis.com/youtube/v3/videos" - -# Diese Funktion dient dazu, die Dateigröße zu ermitteln -def get_file_size(file_path): - return os.path.getsize(file_path) - -# Diese Funktion dient dazu, einen bestimmten Abschnitt einer Datei zurückzugeben -def get_range(file_path, byte_range): - with open(file_path, 'rb') as f: - f.seek(byte_range[0]) - return f.read(byte_range[1] - byte_range[0] + 1) - -def get_api_key(): - try: - with open("token.txt", "r") as f: - return f.read().strip() # Den API Key zurückgeben - except FileNotFoundError: - raise FileNotFoundError("Die Datei token.txt wurde nicht gefunden. Bitte stelle sicher, dass sie vorhanden ist.") - -# 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) # 24 hours - 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

- - -""" - -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("/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 - -@app.route("/", methods=["GET"]) -def index(): - query = request.args.get("query") - results = None - - if query: - # API-Anfrage an y.com.sb für die Suchergebnisse - response = requests.get(f"{API_BASE_URL}search?q={query}", timeout=3) - try: - data = response.json() # Parst die JSON-Antwort der API - except ValueError: - return "Fehler beim Parsen der API-Antwort.", 500 - - # Ergebnisse verarbeiten, falls die API-Antwort erfolgreich und im erwarteten Format ist - if response.status_code == 200 and isinstance(data, list): - results = [ - { - "id": entry.get("videoId"), # Die Video-ID - "title": entry.get("title"), # Der Titel des Videos - "uploader": entry.get("author", "Unbekannt"), # Der Name des Uploaders - "thumbnail": f"/thumbnail/{entry['videoId']}", - "viewCount": entry.get("viewCountText", "Unbekannt"), # Anzahl der Aufrufe - "published": entry.get("publishedText", "Unbekannt") # Veröffentlichungsdatum - } - for entry in data # Iteriere durch jedes Video - if entry.get("videoId") # Sicherstellen, dass ein VideoID vorhanden ist - ] - else: - return "Keine Ergebnisse gefunden oder Fehler in der API-Antwort.", 404 - - return render_template_string(INDEX_TEMPLATE, results=results) - -@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 to FLV for Wii: {str(e)}", 500 - - # HTML basierend auf User-Agent rendern - if is_wii: - return render_template_string(WATCH_WII_TEMPLATE, **metadata, video_flv=f"/sigma/videos/{video_id}.flv") - else: - return render_template_string(WATCH_STANDARD_TEMPLATE, **metadata, video_mp4=f"/sigma/videos/{video_id}.mp4") - -# Video-Metadaten zurückgeben (Simulation für Metadaten) -@app.route("/video_metadata/") -def video_metadata(video_id): - api_key = get_api_key() - - # API-Anfrage an YouTube Data API v3 - params = { - "part": "snippet,statistics", - "id": video_id, - "key": api_key - } - - try: - response = requests.get(YOUTUBE_API_URL, params=params, timeout=2) - response.raise_for_status() # Raise HTTPError für schlechte Antworten - - data = response.json() - - # Überprüfen, ob Video-Daten vorhanden sind - if "items" not in data or len(data["items"]) == 0: - return f"Video mit ID {video_id} wurde nicht gefunden.", 404 - - # Metadaten extrahieren - video_data = data["items"][0] - title = video_data["snippet"]["title"] - description = video_data["snippet"]["description"] - uploader = video_data["snippet"]["channelTitle"] - view_count = video_data["statistics"].get("viewCount", "Unknown") - like_count = video_data["statistics"].get("likeCount", "Unknown") - dislike_count = video_data["statistics"].get("dislikeCount", "Unknown") - - # Metadaten als JSON zurückgeben - return { - "title": title, - "uploader": uploader, - "description": description, - "viewCount": view_count, - "likeCount": like_count, - "dislikeCount": dislike_count - } - - except requests.exceptions.RequestException as e: - return f"Fehler bei der API-Anfrage: {str(e)}", 500 - -@app.route("/") -def serve_video(filename): - file_path = os.path.join(filename) - - # Überprüfen, ob die Datei existiert - if not os.path.exists(file_path): - return "File not found.", 404 - - file_size = get_file_size(file_path) - - # Überprüfen, ob ein Range-Header vorhanden ist - range_header = request.headers.get('Range', None) - if range_header: - # Range-Header parsen (Beispiel: 'bytes=0-499') - byte_range = range_header.strip().split('=')[1] - start_byte, end_byte = byte_range.split('-') - start_byte = int(start_byte) - end_byte = int(end_byte) if end_byte else file_size - 1 - - # Wenn der angeforderte Bereich ungültig ist - if start_byte >= file_size or end_byte >= file_size: - abort(416) # 416 Range Not Satisfiable - - # Abschnitt der Datei zurückgeben - data = get_range(file_path, (start_byte, end_byte)) - content_range = f"bytes {start_byte}-{end_byte}/{file_size}" - - # Antwort mit Status 206 (Partial Content) - response = Response( - data, - status=206, - mimetype="video/mp4", - content_type="video/mp4", - direct_passthrough=True - ) - response.headers["Content-Range"] = content_range - response.headers["Content-Length"] = str(len(data)) - return response - - # Wenn kein Range-Header vorhanden ist, wird die ganze Datei gesendet - return send_file(file_path) - -if __name__ == "__main__": - app.run(debug=True)