import os import hashlib import json import requests import subprocess from datetime import datetime, timedelta from flask import Flask, jsonify, Response, request BASE_API = "https://ws1.smn.gob.ar" CACHE_DIR = "json.api.cache" CACHE_TTL = timedelta(minutes=60) SMN_TOKEN_FILE = "token.txt" ACCESS_TOKEN = "i.hate.smn" TIMEOUT = 10 app = Flask(__name__) app.config["JSONIFY_PRETTYPRINT_REGULAR"] = False @app.after_request def remove_server_header(response): response.headers["Server"] = "" response.headers["X-Powered-By"] = "" return response def get_cache_filename(url: str) -> str: h = hashlib.sha256(url.encode()).hexdigest() return os.path.join(CACHE_DIR, f"{h}.json") def load_cache(url: str): try: path = get_cache_filename(url) if not os.path.exists(path): return None mtime = datetime.fromtimestamp(os.path.getmtime(path)) if datetime.now() - mtime > CACHE_TTL: return None with open(path, "r", encoding="utf-8") as f: return json.load(f) except Exception: return None def save_cache(url: str, data: dict): try: os.makedirs(CACHE_DIR, exist_ok=True) path = get_cache_filename(url) with open(path, "w", encoding="utf-8") as f: json.dump(data, f, ensure_ascii=False) except Exception as e: print(f"[CACHE] Failed to save cache: {e}") def load_smn_token(): try: with open(SMN_TOKEN_FILE, "r", encoding="utf-8") as f: token = f.read().strip() if not token: raise ValueError("Empty token file.") return token except Exception as e: print(f"[TOKEN] Error loading token: {e}") return "" def refresh_smn_token(): print("[TOKEN] Refreshing SMN token...") try: result = subprocess.run( ["python3", "tokenext.py"], capture_output=True, text=True, timeout=60 ) if result.returncode == 0: print("[TOKEN] Token refreshed successfully.") else: print(f"[TOKEN] Refresh failed: {result.stderr.strip()}") except Exception as e: print(f"[TOKEN] Error running tokenext.py: {e}") def check_access_token(): header_token = request.headers.get("Authorization", "").strip() if header_token != ACCESS_TOKEN: # Drop unauthorized message (empty response) return Response("", status=401) return None def fetch_from_smn(url: str, retry: bool = True): token = load_smn_token() headers = { "Authorization": f"JWT {token}", "Accept": "application/json", "User-Agent": "Mozilla/5.0" } try: resp = requests.get(url, headers=headers, timeout=TIMEOUT) except requests.RequestException as e: print(f"[ERROR] Request failed: {e}") return None if resp.status_code == 401 and retry: print("[AUTH] SMN token expired, refreshing...") refresh_smn_token() return fetch_from_smn(url, retry=False) return resp @app.route("/") def smn_proxy(subpath): unauthorized = check_access_token() if unauthorized: return unauthorized url = f"{BASE_API}/{subpath}" # Cache check cached = load_cache(url) if cached: print(f"[CACHE] Loaded {subpath}") return jsonify(cached) print(f"[FETCH] {url}") resp = fetch_from_smn(url) if not resp: return Response("", status=502) if resp.status_code >= 400: print(f"[WARN] {resp.status_code} for {url}") return Response("", status=resp.status_code) try: data = resp.json() except Exception: print("[ERROR] Invalid JSON response.") return Response("", status=502) save_cache(url, data) return jsonify(data) if __name__ == "__main__": os.makedirs(CACHE_DIR, exist_ok=True) app.run(host="0.0.0.0", port=6942, debug=False, use_reloader=False)