From 6eff8b22c2ce0a48d431ccf791c06e87cace67d6 Mon Sep 17 00:00:00 2001 From: kobayashi90 Date: Mon, 10 Mar 2025 01:10:17 +0000 Subject: [PATCH] Upload files to "/" --- app.py | 199 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 199 insertions(+) create mode 100644 app.py diff --git a/app.py b/app.py new file mode 100644 index 0000000..3f80bd7 --- /dev/null +++ b/app.py @@ -0,0 +1,199 @@ +from flask import Flask, render_template, request, jsonify, send_file +from io import BytesIO +import requests +from bs4 import BeautifulSoup +import urllib.parse +import time +import random +import os + +app = Flask(__name__) + +# Request settings +REQUEST_DELAY = 3.0 # seconds +last_request_time = 0 + +# Extended list of user agents +USER_AGENTS = [ + 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36', + 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36', + 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/14.1.1 Safari/605.1.15', + 'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.114 Safari/537.36', + 'Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:89.0) Gecko/20100101 Firefox/89.0', + 'Mozilla/5.0 (iPhone; CPU iPhone OS 14_6 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/14.1.1 Mobile/15E148 Safari/604.1', + 'Mozilla/5.0 (iPad; CPU OS 14_6 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/14.1.1 Mobile/15E148 Safari/604.1', + 'Mozilla/5.0 (Linux; Android 11; SM-G975F) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.114 Mobile Safari/537.36', + 'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:89.0) Gecko/20100101 Firefox/89.0', + 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.114 Safari/537.36' +] + +def polite_request(url): + global last_request_time + now = time.time() + elapsed = now - last_request_time + if elapsed < REQUEST_DELAY: + time.sleep(REQUEST_DELAY - elapsed) + + headers = { + 'User-Agent': random.choice(USER_AGENTS), + 'Referer': 'https://downloads.khinsider.com/', + 'Accept-Language': 'en-US,en;q=0.5', + 'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8', + 'Accept-Encoding': 'gzip, deflate, br' + } + + proxies = {} + if os.getenv('HTTP_PROXY'): + proxies['http'] = os.getenv('HTTP_PROXY') + if os.getenv('HTTPS_PROXY'): + proxies['https'] = os.getenv('HTTPS_PROXY') + + try: + with requests.Session() as session: + response = session.get( + url, + headers=headers, + proxies=proxies if proxies else None, + timeout=10 + ) + response.raise_for_status() + return response + finally: + last_request_time = time.time() + +@app.route('/') +def index(): + return render_template('index.html') + +@app.route("/search") +def search(): + query = request.args.get("q", "").strip() + if not query or len(query) < 3: + return jsonify({"error": "Query must be at least 3 characters"}), 400 + + results = search_for_album(query) + return jsonify({ + "results": results, + "count": len(results) + }) + +@app.route('/album') +def album(): + album_url = request.args.get('url') + if not album_url: + return jsonify({'error': 'Missing album URL'}), 400 + + tracks = get_album_tracks(album_url) + return jsonify(tracks) + +@app.route('/download') +def download(): + track_url = request.args.get('url') + if not track_url: + return jsonify({'error': 'Missing track URL'}), 400 + + direct_url = get_download_url(track_url) + if not direct_url: + return jsonify({'error': 'Could not find download link'}), 404 + + try: + response = polite_request(direct_url) + response.raise_for_status() + + buffer = BytesIO() + for chunk in response.iter_content(chunk_size=8192): + if chunk: + buffer.write(chunk) + buffer.seek(0) + + filename = urllib.parse.unquote(direct_url.split('/')[-1]) + return send_file( + buffer, + as_attachment=True, + download_name=filename, + mimetype='audio/mpeg' if filename.endswith('.mp3') else 'audio/flac', + conditional=False + ) + + except Exception as e: + return jsonify({'error': str(e)}), 500 + +def search_for_album(query): + try: + search_url = f"https://downloads.khinsider.com/search?search={urllib.parse.quote(query)}" + response = polite_request(search_url) + soup = BeautifulSoup(response.text, 'html.parser') + albums = [] + + for row in soup.select('table.albumList tr:not(:first-child)'): + album_link = row.select_one('td:nth-of-type(2) a') + if not album_link: + continue + + album_name = album_link.text.strip() + album_url = f"https://downloads.khinsider.com{album_link['href']}" + + albums.append({ + "name": album_name, + "url": album_url + }) + + seen = set() + return [x for x in albums if not (x['url'] in seen or seen.add(x['url']))] + + except Exception as e: + print(f"Search error: {str(e)}") + return [] + +def get_album_tracks(album_url): + try: + response = polite_request(album_url) + soup = BeautifulSoup(response.text, 'html.parser') + tracks = [] + + for row in soup.select('table#songlist tr:has(a[href$=".mp3"]), table#songlist tr:has(a[href$=".flac"])'): + link = row.find('a', href=True) + if link and (link['href'].endswith('.mp3') or link['href'].endswith('.flac')): + track_url = link['href'] if link['href'].startswith('http') else f"https://downloads.khinsider.com{link['href']}" + tracks.append({ + 'name': link.text.strip(), + 'url': track_url, + 'format': 'flac' if link['href'].lower().endswith('.flac') else 'mp3' + }) + + return tracks + + except Exception as e: + print(f"Album error: {str(e)}") + return [] + +def get_download_url(track_page_url): + try: + response = polite_request(track_page_url) + soup = BeautifulSoup(response.text, 'html.parser') + + audio_links = [] + for link in soup.find_all('a', href=True): + href = link['href'] + if href.endswith(('.mp3', '.flac')): + decoded_url = urllib.parse.unquote(href) + if not decoded_url.startswith('http'): + decoded_url = f"https://downloads.khinsider.com{decoded_url}" + audio_links.append(decoded_url) + + flac_links = [link for link in audio_links if link.endswith('.flac')] + if flac_links: + return flac_links[0] + + mp3_links = [link for link in audio_links if link.endswith('.mp3')] + if mp3_links: + return mp3_links[0] + + return None + + except Exception as e: + print(f"Download URL error: {str(e)}") + return None + +if __name__ == '__main__': + app.run(host='127.0.0.1', port=5000, debug=true) \ No newline at end of file