import threading
from flows import create_animations
import logging
import os
import re
import time
from datetime import datetime
import requests
from flask import Flask , Response , render_template , request , send_from_directory
from prefect . deployments import run_deployment
PORT = 9021
PROTO = " https "
BARE = True
app = Flask ( __name__ )
logging . basicConfig ( level = logging . DEBUG )
def deploy_name ( ) :
return datetime . utcnow ( ) . strftime ( " % Y- % m- %d T % H: % M: % S " ) + " Z "
def get_host ( ) :
host = os . environ . get ( " LIGHTNING_CLOUDSPACE_HOST " )
if host is None :
default_host = os . environ . get ( " HOST_NAME " , " 0.0.0.0 " )
return f " { default_host } : { PORT } " if not BARE else f " { default_host } "
else :
return f " { PORT } - { host } " if not BARE else f " { host } "
@app . route ( " /iframe " )
@app . route ( " /iframe/ " )
@app . route ( " /iframe/<path:subpath> " )
def home ( subpath = " images/animations/ " , proto = PROTO ) :
host = get_host ( )
initial_url = f " { proto } :// { host } / { subpath } "
api_url = f " { proto } :// { host } /api "
return render_template (
" index.html " , initial_url = initial_url , host = f " { proto } :// { host } " , api_url = api_url
)
@app . route ( " /api " , methods = [ " POST " ] )
def handle_api ( ) :
data = request . json # This assumes you're sending JSON data.
url = data . get ( " url " )
if not url . endswith ( " / " ) :
url + = " / "
logging . debug ( f " Received URL: { url } " )
params = { " url " : url , " limit " : 24 * 60 , " ext " : None }
response = run_deployment (
name = " create-animations/noaa-animate " ,
parameters = params ,
flow_run_name = f " { deploy_name ( ) } .webapp. { url } " ,
)
# response is a FlowRun - need to get what we want from it.
# Process the data as needed.
return {
" status " : " success " ,
" message " : f " { url } processed successfully " ,
# "response": response,
} , 200
@app . route ( " /videos/<path:filename> " )
def custom_static ( filename ) :
return send_from_directory ( " ./out " , filename )
@app . route ( " / " , methods = [ " GET " ] )
@app . route ( " /<path:url> " , methods = [ " GET " ] )
def proxy ( url = " " , proto = PROTO ) :
original_base_url = " https://services.swpc.noaa.gov "
host = get_host ( )
proxy_base_url = f " { proto } :// { host } / "
target_url = f " { original_base_url } / { url } "
logging . debug ( f " Fetching URL: { target_url } " )
try :
headers = {
" User-Agent " : " Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537.36 "
}
response = requests . get ( target_url , headers = headers , stream = True )
excluded_headers = [
" content-encoding " ,
" content-length " ,
" transfer-encoding " ,
" connection " ,
]
headers = [
( name , value )
for ( name , value ) in response . raw . headers . items ( )
if name . lower ( ) not in excluded_headers
]
if " text/html " in response . headers . get ( " Content-Type " , " " ) :
content = response . content . decode ( " utf-8 " )
content = re . sub ( r " ' http:// " , " ' https:// " , content )
content = re . sub (
r " https?://services.swpc.noaa.gov " , proxy_base_url , content
)
content = content . replace (
" </body> " ,
f """
< script >
window . addEventListener ( ' load ' , function ( ) { {
var hasSufficientImages = false ;
var observer = new MutationObserver ( function ( mutations ) { {
mutations . forEach ( function ( mutation ) { {
if ( mutation . type == = ' childList ' ) { {
console . log ( ' observer ' ) ;
checkImages ( ) ;
} }
} } ) ;
} } ) ;
observer . observe ( document . body , { { childList : true , subtree : true } } ) ;
function checkImages ( ) { {
var links = document . querySelectorAll ( ' a ' ) ;
var imageLinkRegex = / \. ( jpg | jpeg | png ) ( \\? . * ) ? ( #.*)?$/i;
var numImages = Array . from ( links ) . filter ( link = > imageLinkRegex . test ( link . href ) ) . length ;
console . log ( ' Number of eligible links: ' , numImages ) ;
hasSufficientImages = numImages > = 60 ;
window . parent . postMessage ( { { type : ' urlUpdate ' , url : ' {original_base_url} / {url} ' , eligible : hasSufficientImages } } , ' * ' ) ;
} }
/ / Run initial check in case content is already loaded
console . log ( ' initial ' ) ;
checkImages ( ) ;
} } ) ;
< / script >
< / body > """ ,
)
content = content . encode ( " utf-8 " )
return Response ( content , status = response . status_code , headers = headers )
else :
return Response (
response . content , status = response . status_code , headers = headers
)
except Exception as e :
logging . error ( f " Error fetching URL: { e } " )
return Response ( f " Error fetching URL: { e } " , status = 500 )
if __name__ == " __main__ " :
threading . Thread ( target = create_animations . serve , daemon = True , kwargs = { " name " : " noaa-animate " , " limit " : 8 } ) . start ( )
app . run ( host = " 0.0.0.0 " , port = 9021 , debug = True )