anime / app.py
Reaperxxxx's picture
Update app.py
cdeaae4 verified
Raw
History Blame Contribute Delete
13.9 kB
from flask import Flask, request, jsonify, send_from_directory, send_file
from PIL import Image, ImageDraw, ImageFont, ImageFilter
from io import BytesIO
import requests
import random
import time
import os
import uuid
import io
import textwrap
import re
app = Flask(__name__)
# Store uptime and request count
start_time = time.time()
request_count = 0
TINYURL_API = "https://tinyurl.com/api-create.php"
WAIFU_API = "https://api.waifu.pics"
BASE_ANIME_API = "https://reikerxx-animedl.hf.space/anime/"
BASE_DOWNLOAD_API = "https://reikerxx-plw.hf.space/download-links?url="
ANIME_IDS = [20, 21, 16498, 118763, 2025, 813, 153, 5114, 11757, 2747364,
12355, 123, 169, 30276, 34565, 6702, 32182, 9253, 157, 30, 1735, 52299, 44511, 34572, 269]
JIKAN_API_BASE = "https://api.jikan.moe/v4/anime"
NODE_API_URL = "https://reikerxx-bani.hf.space/anime"
YT_API_URL = "https://reikerxx-ytm.hf.space/api/q"
BASE_URL = "https://reikerxx-agi.hf.space/getDownload"
IMAGE_FOLDER = "static/images"
os.makedirs(IMAGE_FOLDER, exist_ok=True) # Ensure the folder exists
API_TOKEN = "fe51903c8ea947498dcb16927f840670"
HEADERS = {"X-Auth-Token": API_TOKEN}
# List of 30 popular team IDs
TEAM_IDS = [
66, 65, 64, 61, 57, 73, # Premier League
86, 81, 78, 559, 95, # La Liga
5, 4, 721, 3, 6, # Bundesliga
109, 108, 98, 113, 100, # Serie A
524, 516, 523, 548, # Ligue 1
678, 1903, 503, 211, 1877 # Other Leagues
]
THUMBNAIL_IMAGES = [
"https://i.imgur.com/WfTUHmd.jpeg",
"https://i.imgur.com/WfTUHmd.jpeg",
"https://i.imgur.com/WfTUHmd.jpeg"
]
def fetch_random_character():
while True:
anime_id = random.choice(ANIME_IDS)
url = f"{JIKAN_API_BASE}/{anime_id}/characters"
response = requests.get(url)
if response.status_code != 200:
continue
characters = response.json().get("data", [])
if not characters:
continue
character = random.choice(characters).get("character", {})
if not character or not character.get("images", {}).get("jpg", {}).get("image_url"):
continue
return {
"name": character.get("name"),
"image": character.get("images", {}).get("jpg", {}).get("image_url"),
"url": character.get("url"),
"api_owner": "Reiker"
}
def get_uptime():
seconds = int(time.time() - start_time)
days = seconds // 86400
hours = (seconds % 86400) // 3600
return f"{days} days, {hours} hours"
@app.route('/')
def home():
return send_from_directory(os.getcwd(), 'index.html') # Serves the HTML file from the root directory
@app.route('/api/stats')
def stats():
global request_count
request_count += 1
return jsonify({
"uptime": get_uptime(),
"requests": request_count
})
@app.route('/reiker/random-character', methods=['GET'])
def get_random_character():
return jsonify(fetch_random_character())
@app.route('/api/shorturl', methods=['GET'])
def shorturl():
long_url = request.args.get('longurl')
if not long_url:
return jsonify({"error": "Missing 'longurl' parameter"}), 400
response = requests.get(TINYURL_API, params={"url": long_url})
if response.status_code == 200:
short_url = response.text.strip() # TinyURL returns plain text
return jsonify({
"apiowner": "Reiker",
"short_url": short_url
})
else:
return jsonify({"error": "Failed to shorten URL"}), 500
@app.route('/api/waifu', methods=['GET'])
def get_waifu():
category = request.args.get('category', 'waifu') # Default to 'waifu'
sfw = request.args.get('sfw', 'true').lower() # Default to SFW images
# Validate category
valid_categories = [
"waifu", "neko", "shinobu", "megumin", "bully", "cuddle", "cry", "hug",
"awoo", "kiss", "lick", "pat", "smug", "bonk", "yeet", "blush", "smile",
"wave", "highfive", "handhold", "nom", "bite", "glomp", "slap", "kill",
"kick", "happy", "wink", "poke", "dance", "cringe"
]
if category not in valid_categories:
return jsonify({"error": "Invalid category"}), 400
# Choose SFW or NSFW
type_field = "sfw" if sfw == "true" else "nsfw"
# Call the waifu.pics API
response = requests.get(f"{WAIFU_API}/{type_field}/{category}")
if response.status_code == 200:
waifu_image = response.json().get("url")
return jsonify({
"apiowner": "Reiker",
"category": category,
"image_url": waifu_image
})
else:
return jsonify({"error": "Failed to fetch waifu image"}), 500
FONT_PATH = "gagalin.otf" # Ensure this font is in the same directory
IMAGE_PATH = "image.png" # Background image
@app.route("/api/logo")
def generate_logo():
name = request.args.get("name", "Default Name")
info = request.args.get("info", "Your Motto")
try:
# Load the background image
img = Image.open(IMAGE_PATH).convert("RGBA")
draw = ImageDraw.Draw(img)
# Set font sizes dynamically
max_width = img.width * 0.8 # 80% of image width
name_size = int(img.width * 0.12) # Dynamic name size
info_size = int(img.width * 0.05) # Smaller motto size
font_name = ImageFont.truetype(FONT_PATH, name_size)
font_info = ImageFont.truetype(FONT_PATH, info_size)
# Shrink name text if too long
while draw.textbbox((0, 0), name, font=font_name)[2] > max_width:
name_size -= 5
font_name = ImageFont.truetype(FONT_PATH, name_size)
# **Break long info text into multiple lines**
def wrap_text(text, font, max_width):
lines = []
for line in textwrap.wrap(text, width=30): # Wrap text every 30 characters
while draw.textbbox((0, 0), line, font=font)[2] > max_width:
font = ImageFont.truetype(FONT_PATH, font.size - 2) # Reduce font size
lines.append(line)
return lines, font
info_lines, font_info = wrap_text(info, font_info, max_width)
# Calculate positions
text_x = img.width // 2
text_y_name = int(img.height * 0.42) # Slightly lower
text_y_info = int(img.height * 0.58) # Adjusted further down
# Center name text
name_bbox = draw.textbbox((0, 0), name, font=font_name)
name_x = text_x - (name_bbox[2] - name_bbox[0]) // 2
# Function to draw an **outline glow** instead of blurry glow
def draw_outline(draw, position, text, font, outline_color, thickness=2):
x, y = position
for dx in range(-thickness, thickness + 1):
for dy in range(-thickness, thickness + 1):
if dx != 0 or dy != 0: # Avoid double drawing the center
draw.text((x + dx, y + dy), text, font=font, fill=outline_color)
# **Apply dark blue outline with reduced opacity**
outline_color = (0, 0, 139, 180) # RGBA (Dark Blue with lower opacity)
# **Draw name text**
draw_outline(draw, (name_x, text_y_name), name, font_name, outline_color, thickness=3)
draw.text((name_x, text_y_name), name, font=font_name, fill="white")
# **Draw multi-line info text**
for i, line in enumerate(info_lines):
line_bbox = draw.textbbox((0, 0), line, font=font_info)
line_x = text_x - (line_bbox[2] - line_bbox[0]) // 2
line_y = text_y_info + (i * (font_info.size + 5)) # Adjust for line spacing
draw_outline(draw, (line_x, line_y), line, font_info, outline_color, thickness=2)
draw.text((line_x, line_y), line, font=font_info, fill="white")
# Save and return as API response
img_io = io.BytesIO()
img.save(img_io, "PNG")
img_io.seek(0)
return send_file(img_io, mimetype="image/png")
except Exception as e:
return {"error": str(e)}, 500
@app.route('/api/soccer', methods=['GET'])
def get_random_player():
attempts = 0
while attempts < 2: # Retry twice if needed
team_id = random.choice(TEAM_IDS)
response = requests.get(f"https://api.football-data.org/v4/teams/{team_id}", headers=HEADERS)
if response.status_code == 200:
team_data = response.json()
squad = team_data.get("squad", [])
if squad: # Ensure the squad is not empty
player = random.choice(squad)
return jsonify({
"player_name": player.get("name"),
"position": player.get("position"),
"nationality": player.get("nationality"),
"team": team_data.get("name"),
"apiowner": "Reiker"
})
attempts += 1
return jsonify({"error": "Failed to fetch valid player data"}), 500 # Only return error after 2 failed attempts
@app.route('/api/anime/<string:anime_name>/<int:episode>', methods=['GET'])
def get_anime_download_links(anime_name, episode):
anime_name_formatted = anime_name.replace(" ", "%20") # URL encoding
anime_api_url = f"{BASE_ANIME_API}{anime_name_formatted}/{episode}"
# Fetch the download page URL
anime_response = requests.get(anime_api_url)
if anime_response.status_code != 200:
return jsonify({"error": "Failed to fetch anime info"}), 500
anime_data = anime_response.json()
download_page_url = anime_data.get("downloadPage")
if not download_page_url:
return jsonify({"error": "Download page URL not found"}), 404
# Fetch MP4 links
download_api_url = f"{BASE_DOWNLOAD_API}{download_page_url}"
download_response = requests.get(download_api_url)
if download_response.status_code != 200:
return jsonify({"error": "Failed to fetch download links"}), 500
download_data = download_response.json()
download_links = download_data.get("downloadLinks", {})
# Well-formatted JSON response
response_data = {
"api_owner": "Reiker",
"anime_name": anime_data.get("anime", anime_name),
"episode": episode,
"download_links": {
"360p": download_links.get("3604p", "Not Available"),
"720p": download_links.get("7204p", "Not Available")
}
}
return jsonify(response_data), 200
@app.route('/api/anime2', methods=['GET'])
def get_anime():
anime_name = request.args.get('name', '').strip()
episode_number = request.args.get('episode', '').strip()
if not anime_name or not episode_number:
return jsonify({"error": "Missing required parameters: name and episode"}), 400
node_api_url = f"{NODE_API_URL}/{anime_name}/{episode_number}"
try:
response = requests.get(node_api_url)
data = response.json()
if not data or "error" in data:
return jsonify({"error": "No results found for the given anime and episode"}), 404
formatted_response = {
"Anime": data["anime"],
"Episode": data["episode"],
"Episode URL": data["episodeURL"],
"Downloads": {
"360p": data["360p"] if data["360p"] else "Not available",
"720p": data["720p"] if data["720p"] else "Not available",
"1080p": data["1080p"] if data["1080p"] else "Not available"
}
}
return jsonify(formatted_response), 200
except requests.exceptions.RequestException as e:
return jsonify({"error": "Failed to connect to the Node.js API", "details": str(e)}), 500
@app.route('/api/ytmp3', methods=['GET'])
def youtube_to_mp3():
video_url = request.args.get('url', '').strip()
if not video_url:
return jsonify({"error": "Missing required parameter: url"}), 400
try:
response = requests.get(YT_API_URL, params={"url": video_url})
data = response.json()
if not data.get("success"):
return jsonify({"error": "Failed to convert video"}), 500
return jsonify({
"download_link": data["file"],
"api_owner": "Reikerx"
}), 200
except requests.exceptions.RequestException as e:
return jsonify({"error": "Failed to connect to the conversion API", "details": str(e)}), 500
def clean_movie_name(raw_name):
"""Extracts a clean movie name by removing extra tags like site names."""
# Remove common tags (e.g., NKIRI COM, BluRay, and unnecessary dots)
clean_name = re.sub(r"(\s*NKIRI\s*COM\s*|\s*DOWNLOADED\s*FROM\s*NKIRI\s*COM|\s*\d{4}\s*BluRay)", "", raw_name, flags=re.IGNORECASE)
# Remove excessive dots and underscores
clean_name = re.sub(r"[\.\_]+", " ", clean_name).strip()
return clean_name
@app.route('/fetchDownload', methods=['GET'])
def fetch_download():
moviename = request.args.get('moviename')
episode = request.args.get('episode')
if not moviename:
return jsonify({"error": "Movie name is required"}), 400
# Construct the request URL
url = f"{BASE_URL}?moviename={moviename}"
if episode:
url += f"&episode={episode}"
try:
response = requests.get(url)
data = response.json()
except Exception as e:
return jsonify({"error": "Failed to fetch download info", "details": str(e)}), 500
if "movie" not in data or "finalDownloadUrl" not in data:
return jsonify({"error": "Invalid response format"}), 500
# Extract and clean movie name
movie_name = clean_movie_name(data["movie"])
download_url = data["finalDownloadUrl"]
# Format response
formatted_response = {
"Movie Name": movie_name,
"Download Link": download_url
}
return jsonify(formatted_response)
if __name__ == '__main__':
app.run(debug=True, host='0.0.0.0', port=7860)