from flask import Flask, render_template, request, redirect, url_for, Response import os from dotenv import load_dotenv from bs4 import BeautifulSoup # Load environment variables from .env file load_dotenv() app = Flask(__name__, template_folder='templates') def get_config(): """Retrieve configuration from environment variables.""" return { "excluded_countries": os.getenv('EXCLUDED_COUNTRIES', '[]'), "preferred_protocols": os.getenv('PREFERRED_PROTOCOLS', '["https", "http"]'), "preferred_types": os.getenv('PREFERRED_TYPES', '["https", "http"]'), "min_preference": os.getenv('MIN_PREFERENCE', '0') } @app.route('/dash/config', methods=['GET', 'POST']) def config(): if request.method == 'POST': # Update environment variables with form data os.environ['EXCLUDED_COUNTRIES'] = request.form.get('excluded_countries', '') os.environ['PREFERRED_PROTOCOLS'] = request.form.get('preferred_protocols', '') os.environ['PREFERRED_TYPES'] = request.form.get('preferred_types', '') os.environ['MIN_PREFERENCE'] = request.form.get('min_preference', '') return redirect(url_for('config')) # Retrieve the current configuration config = get_config() return render_template('config.html', **config) @app.route('/metalink') def get_metalink(): # Get query parameters from the request repo = request.args.get('repo') arch = request.args.get('arch') # Check if required parameters are provided if not repo or not arch: return "Error: Missing 'repo' or 'arch' parameter", 400 # Construct the metalink URL using the provided parameters metalink_url = f'https://mirrors.fedoraproject.org/metalink?repo={repo}&arch={arch}' # Fetch the metalink file from the constructed URL response = requests.get(metalink_url) metalink_content = response.content # Get the filtering criteria from environment variables config = get_config() excluded_countries = eval(config['excluded_countries']) preferred_protocols = eval(config['preferred_protocols']) preferred_types = eval(config['preferred_types']) min_preference = int(config['min_preference']) # Filter out the URLs based on the criteria filtered_content = filter_urls(metalink_content, excluded_countries, preferred_protocols, preferred_types, min_preference) # Return the filtered content as a response return Response(filtered_content, mimetype='application/xml') def filter_urls(content, excluded_countries, preferred_protocols, preferred_types, min_preference): # Parse the XML content soup = BeautifulSoup(content, 'xml') # Find all URL elements urls = soup.find_all('url') # Iterate over URLs and remove those that do not meet the criteria for url in urls: location = url.get('location') protocol = url.get('protocol') type_ = url.get('type') preference = int(url.get('preference', 0)) if (location in excluded_countries or protocol not in preferred_protocols or type_ not in preferred_types or preference < min_preference): url.decompose() # Convert the BeautifulSoup object back to a string and clean up filtered_content = str(soup) filtered_content = '\n'.join(line for line in filtered_content.splitlines() if line.strip()) return filtered_content @app.route('/dash/stats') def stats(): return render_template('stats.html') @app.route('/dash/logs') def logs(): return render_template('logs.html') if __name__ == '__main__': app.run(host='0.0.0.0', port=8182)