import hashlib import re import requests import xml.etree.ElementTree as ET from flask import Flask, render_template, jsonify, request from urllib.parse import quote import urllib3 # Disable SSL warnings when using verify=False urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning) app = Flask(__name__) # Configuration METAFILE_BASE_URL = "https://metafile.oliver.solutions/getFile" METAFILE_KEY = "$14W0TF~8FL" class MetafileClient: def __init__(self, base_url, api_key): self.base_url = base_url self.api_key = api_key def _generate_checksum(self, root, path, sub=None): """Generate MD5 checksum for metafile API authentication""" if sub: checksum_string = f"{self.api_key}{root}/{sub}/{path}" else: checksum_string = f"{self.api_key}{root}/{path}" return hashlib.md5(checksum_string.encode('utf-8')).hexdigest() def get_file(self, root, path, keyid=1, sub=None): """Make request to metafile server""" checksum = self._generate_checksum(root, path, sub) params = { 'root': root, 'path': path, 'keyid': keyid, 'cs': checksum } if sub: params['sub'] = sub try: response = requests.get(self.base_url, params=params, timeout=30, verify=False) response.raise_for_status() return { 'success': True, 'data': response.text, 'status_code': response.status_code } except requests.exceptions.RequestException as e: return { 'success': False, 'error': str(e), 'status_code': getattr(e.response, 'status_code', None) if hasattr(e, 'response') else None } def get_client_from_xml(self, deliverable_number): """Get client information from XML file""" xml_filename = f"{deliverable_number}.xml" result = self.get_file(root="XML", path=xml_filename) if not result['success']: return result try: # Parse XML root_elem = ET.fromstring(result['data']) # Look for Set-Property elements with Property="jobpath" jobpath_elements = root_elem.findall(".//Set-Property[@Property='jobpath']") for prop in jobpath_elements: jobpath_value = prop.get('Value', '') if jobpath_value and '/CAMPAIGNS/' in jobpath_value: # Extract client name from jobpath like "/ADIDAS_CAM_OLIVER_KUALA_LUMPUR/ADIDAS/CAMPAIGNS/..." # Use regex to extract client name before /CAMPAIGNS client_pattern = r'([A-Z][A-Z0-9_]*?)(?=/CAMPAIGNS/)' match = re.search(client_pattern, jobpath_value) if match: return { 'success': True, 'client': match.group(1) } # Fallback: look for any Value containing /CAMPAIGNS/ set_properties = root_elem.findall(".//Set-Property[@Value]") for prop in set_properties: value = prop.get('Value', '') if '/CAMPAIGNS/' in value: client_pattern = r'([A-Z][A-Z0-9_]*?)(?=/CAMPAIGNS/)' match = re.search(client_pattern, value) if match: return { 'success': True, 'client': match.group(1) } return { 'success': False, 'error': 'Could not extract client information from XML' } except ET.ParseError as e: return { 'success': False, 'error': f'XML parsing error: {str(e)}' } except Exception as e: return { 'success': False, 'error': f'Error processing XML: {str(e)}' } def get_job_data(self, deliverable_number): """Get complete job data (XML + JSON workflow)""" # Step 1: Get client from XML client_result = self.get_client_from_xml(deliverable_number) if not client_result['success']: return client_result client = client_result['client'] # Step 2: Get JSON data using client info json_filename = f"{deliverable_number}.json" json_result = self.get_file(root="JSON_STORE", path=json_filename, sub=client) if not json_result['success']: return json_result # Check if response is 200 OK if json_result['status_code'] != 200: return { 'success': False, 'error': f'JSON file not found or inaccessible (HTTP {json_result["status_code"]})' } try: import json json_data = json.loads(json_result['data']) return { 'success': True, 'client': client, 'data': json_data } except json.JSONDecodeError as e: return { 'success': False, 'error': f'JSON parsing error: {str(e)}' } # Initialize metafile client metafile_client = MetafileClient(METAFILE_BASE_URL, METAFILE_KEY) @app.route('/') def index(): """Serve the main HTML page""" return render_template('index.html') @app.route('/api/job/') def get_job_info(job_number): """API endpoint to get job information""" if not job_number: return jsonify({'error': 'Job number is required'}), 400 # Sanitize job number (remove any non-alphanumeric characters except hyphens and underscores) job_number = re.sub(r'[^a-zA-Z0-9\-_]', '', job_number) if not job_number: return jsonify({'error': 'Invalid job number format'}), 400 result = metafile_client.get_job_data(job_number) if result['success']: return jsonify({ 'success': True, 'job_number': job_number, 'client': result['client'], 'data': result['data'] }) else: return jsonify({ 'success': False, 'job_number': job_number, 'error': result['error'] }), 400 @app.route('/api/health') def health_check(): """Health check endpoint""" return jsonify({'status': 'healthy', 'service': 'Meta File Server Query'}) if __name__ == '__main__': app.run(debug=True, host='0.0.0.0', port=5000)