@ -4,13 +4,14 @@ Environment variables: 
			
		
	
		
			
				
					-  ADMIN_PASSWORD :  password  for  admin  user  for  sensitive  endpoints ,  defaults  to  ' admin '  
			
		
	
		
			
				
					"""  
			
		
	
		
			
				
					
 
			
		
	
		
			
				
					from  typing  import  Dict ,  Tuple ,  Union ,  Optional  
			
		
	
		
			
				
					from  flask  import  Flask ,  request ,  jsonify ,  Response  
			
		
	
		
			
				
					from  models  import  db ,  VAPIDKey ,  Subscription  
			
		
	
		
			
				
					from  cryptography . hazmat . backends  import  default_backend  
			
		
	
		
			
				
					from  cryptography . hazmat . primitives  import  serialization  
			
		
	
		
			
				
					from  cryptography . hazmat . primitives . asymmetric  import  ec  
			
		
	
		
			
				
					from  flask  import  Flask ,  request ,  jsonify ,  Response  
			
		
	
		
			
				
					from  models  import  db ,  VAPIDKey ,  Settings ,  Subscription  
			
		
	
		
			
				
					from  pywebpush  import  webpush ,  WebPushException  
			
		
	
		
			
				
					from  sqlalchemy  import  and_  
			
		
	
		
			
				
					from  typing  import  Dict ,  Tuple  
			
		
	
		
			
				
					
 
			
		
	
		
			
				
					import  base64  
			
		
	
		
			
				
					import  datetime  
			
		
	
	
		
			
				
					
						
						
						
							
								 
						
					 
				
				@ -21,9 +22,14 @@ import time 
			
		
	
		
			
				
					
 
			
		
	
		
			
				
					CONTACT_EMAIL  =  " mailto:info@timesafari.app "  
			
		
	
		
			
				
					
 
			
		
	
		
			
				
					PUSH_SERVER_VERSION  =  os . getenv ( ' PUSH_SERVER_VERSION ' )  
			
		
	
		
			
				
					
 
			
		
	
		
			
				
					app  =  Flask ( __name__ )  
			
		
	
		
			
				
					
 
			
		
	
		
			
				
					class  WebPushService ( ) :  
			
		
	
		
			
				
					
 
			
		
	
		
			
				
					    latest_subscription_run  =  None  
			
		
	
		
			
				
					
 
			
		
	
		
			
				
					    """  
			
		
	
		
			
				
					    This  class  provides  services  for  sending  web  push  notifications .  
			
		
	
		
			
				
					    """  
			
		
	
	
		
			
				
					
						
						
						
							
								 
						
					 
				
				@ -44,10 +50,12 @@ class WebPushService(): 
			
		
	
		
			
				
					        # Setting the application instance  
			
		
	
		
			
				
					        self . app  =  app  
			
		
	
		
			
				
					        self . app . add_url_rule ( ' /web-push/regenerate-vapid ' ,  view_func = self . regenerate_vapid ,  methods = [ ' POST ' ] )  
			
		
	
		
			
				
					        self . app . add_url_rule ( ' /web-push/ping ' ,  view_func = self . ping ,  methods = [ ' GET ' ] )  
			
		
	
		
			
				
					
 
			
		
	
		
			
				
					        # Setting the database URI for the application  
			
		
	
		
			
				
					        db_uri  =  os . getenv ( ' SQLALCHEMY_DATABASE_URI ' ,  ' sqlite:////app/instance/data/webpush.db ' )  
			
		
	
		
			
				
					        # This relative path works in docker-compose  
			
		
	
		
			
				
					        # This relative path works on a local run if you link to this dir from "var/app-instance"  
			
		
	
		
			
				
					        #db_uri = os.getenv('SQLALCHEMY_DATABASE_URI', 'sqlite:///data/webpush.db')  
			
		
	
		
			
				
					        self . app . config [ ' SQLALCHEMY_DATABASE_URI ' ]  =  db_uri  
			
		
	
		
			
				
					
 
			
		
	
	
		
			
				
					
						
							
								 
						
						
							
								 
						
						
					 
				
				@ -126,7 +134,7 @@ class WebPushService(): 
			
		
	
		
			
				
					
 
			
		
	
		
			
				
					
 
			
		
	
		
			
				
					    @staticmethod  
			
		
	
		
			
				
					    def  _send_push_notification ( subscription_info :  Dict ,  message :  Dict ,  vapid_key :  VAPIDKey )  - >  bool :  
			
		
	
		
			
				
					    def  _send_push_notification ( subscription_info :  Dict ,  message :  Dict ,  vapid_key :  VAPIDKey )  - >  Dict [ str ,  any ] :  
			
		
	
		
			
				
					        """  
			
		
	
		
			
				
					        Sends  a  push  notification  using  the  provided  subscription  information ,  message ,  and  VAPID  key .  
			
		
	
		
			
				
					
 
			
		
	
	
		
			
				
					
						
						
						
							
								 
						
					 
				
				@ -135,8 +143,10 @@ class WebPushService(): 
			
		
	
		
			
				
					        -  message  ( Dict ) :  The  actual  message  content  to  be  sent  as  the  push  notification .  
			
		
	
		
			
				
					        -  vapid_key  ( VAPIDKey ) :  The  VAPID  key  model  instance  containing  the  private  key  used  for  sending  the  notification .  
			
		
	
		
			
				
					
 
			
		
	
		
			
				
					        Returns :  
			
		
	
		
			
				
					        -  request . Response  https : / / requests . readthedocs . io / en / latest / api . html #requests.Response if the push notification was sent successfully  
			
		
	
		
			
				
					        Returns  Dict  with  the  following  keys  
			
		
	
		
			
				
					        -  success :  True  if  the  push  notification  was  sent  successfully ,  False  otherwise  
			
		
	
		
			
				
					        -  message :  a  string  message  with  the  resulting  text ,  usually  nothing  on  success  
			
		
	
		
			
				
					        -  result :  request . Response  https : / / requests . readthedocs . io / en / latest / api . html #requests.Response if the push notification was sent successfully  
			
		
	
		
			
				
					          or  False  if  there  was  an  exception  
			
		
	
		
			
				
					
 
			
		
	
		
			
				
					        Notes :  
			
		
	
	
		
			
				
					
						
							
								 
						
						
							
								 
						
						
					 
				
				@ -199,25 +209,80 @@ class WebPushService(): 
			
		
	
		
			
				
					
 
			
		
	
		
			
				
					        while  True :  
			
		
	
		
			
				
					
 
			
		
	
		
			
				
					            now  =  datetime . datetime . now ( ) . isoformat ( )  
			
		
	
		
			
				
					            now  =  datetime . datetime . now ( )  
			
		
	
		
			
				
					            print ( f " { now }  - Starting to send subscriptions... " ,  flush = True )  
			
		
	
		
			
				
					
 
			
		
	
		
			
				
					            # Creating a context for the application to enable database operations  
			
		
	
		
			
				
					            with  self . app . app_context ( ) :  
			
		
	
		
			
				
					
 
			
		
	
		
			
				
					                # Retrieving all subscription data from the database  
			
		
	
		
			
				
					                all_subscriptions  =  Subscription . query . all ( )  
			
		
	
		
			
				
					
 
			
		
	
		
			
				
					                # Retrieving the VAPID key from the database  
			
		
	
		
			
				
					                # Retrieve the VAPID key from the database  
			
		
	
		
			
				
					                vapid_key  =  VAPIDKey . query . first ( )  
			
		
	
		
			
				
					
 
			
		
	
		
			
				
					                # Constructing  the push notification message  
			
		
	
		
			
				
					                # Construct the push notification message  
			
		
	
		
			
				
					                # The title value is a key, triggering the device to apply logic and customize both title and message.  
			
		
	
		
			
				
					                # See https://gitea.anomalistdesign.com/trent_larson/crowd-funder-for-time-pwa/src/commit/1e6159869fc28ca6e6b5b3d186617d75705100b4/sw_scripts/additional-scripts.js#L65  
			
		
	
		
			
				
					                UPDATE_TITLE  =  " DAILY_CHECK "  
			
		
	
		
			
				
					                message  =  { " title " :  UPDATE_TITLE ,  " message " :  f " Update for  { now } " }  
			
		
	
		
			
				
					
 
			
		
	
		
			
				
					                # Sending a push notification to each subscribed client  
			
		
	
		
			
				
					                # Determine the beginning and end time to check for subscriptions  
			
		
	
		
			
				
					                settings  =  Settings . query . first ( )  
			
		
	
		
			
				
					                if  settings . running_notify_end_time  is  None :  
			
		
	
		
			
				
					
 
			
		
	
		
			
				
					                    # set all subscriptions without a time to the current time  
			
		
	
		
			
				
					                    # (these won't be picked-up in the current run, since thie current minute is the end minute)  
			
		
	
		
			
				
					                    Subscription . query . filter_by ( notify_time = None ) . update ( { Subscription . notify_time :  now . strftime ( ' % H: % M ' ) } )  
			
		
	
		
			
				
					
 
			
		
	
		
			
				
					                    """  
			
		
	
		
			
				
					                    Storing  the  HH : MM  for  the  desired  notification  time  isn ' t a bad idea.  
			
		
	
		
			
				
					
 
			
		
	
		
			
				
					                    However ,  the  logic  that  compares  directly  to  it  is  a  bit  complicated .  
			
		
	
		
			
				
					                    It  would  be  more  straightforward  to  save  the  next  notification  time  in  each  record  
			
		
	
		
			
				
					                    and  then  update  that  every  time  this  process  runs .  It  would  require  raw  SQL  with  
			
		
	
		
			
				
					                    some  calculations  and  many  DB  updates  each  day ,  but  the  logic  would  be  more  clear .  
			
		
	
		
			
				
					                    """  
			
		
	
		
			
				
					
 
			
		
	
		
			
				
					                    # get the previous notify end time from the DB as a datetime  
			
		
	
		
			
				
					                    prev_notify_end_time  =  datetime . datetime . fromisoformat ( settings . prev_notify_end_time )  
			
		
	
		
			
				
					                    # if it's before midnight this morning, catch us up to the beginning of today:  
			
		
	
		
			
				
					                    if  prev_notify_end_time  <  now . replace ( hour = 0 ,  minute = 0 ,  second = 0 ,  microsecond = 0 ) :  
			
		
	
		
			
				
					                        # make the start time the later of: prevNotifyEndTime or yesterday at this time  
			
		
	
		
			
				
					                        start_time  =  max (  
			
		
	
		
			
				
					                            prev_notify_end_time ,  
			
		
	
		
			
				
					                            # if the current time is later in the day, use that  
			
		
	
		
			
				
					                            # because the next run will pick up everything from midnight until now today  
			
		
	
		
			
				
					                            now . replace ( second = 0 ,  microsecond = 0 )  -  datetime . timedelta ( days = 1 )  
			
		
	
		
			
				
					                        )  
			
		
	
		
			
				
					                        # make the end time right at midnight at the beginning of today  
			
		
	
		
			
				
					                        end_time  =  now . replace ( hour = 0 ,  minute = 0 ,  second = 0 ,  microsecond = 0 )  
			
		
	
		
			
				
					
 
			
		
	
		
			
				
					                        start_minute  =  start_time . strftime ( ' % H: % M ' )  
			
		
	
		
			
				
					                        # (we'd never catch anything if we used a non-zero start_minute and "00:00" as the end_minute)  
			
		
	
		
			
				
					                        end_minute  =  ' 23:60 '  # gotta catch "23:59", too  
			
		
	
		
			
				
					
 
			
		
	
		
			
				
					                    else :  
			
		
	
		
			
				
					                        # the start time is OK  
			
		
	
		
			
				
					                        start_time  =  prev_notify_end_time  
			
		
	
		
			
				
					                        # the end time is now  
			
		
	
		
			
				
					                        end_time  =  now . replace ( second = 0 ,  microsecond = 0 )  
			
		
	
		
			
				
					
 
			
		
	
		
			
				
					                        start_minute  =  start_time . strftime ( ' % H: % M ' )  
			
		
	
		
			
				
					                        end_minute  =  end_time . strftime ( ' % H: % M ' )  
			
		
	
		
			
				
					
 
			
		
	
		
			
				
					                    # This really should update & continue only if the running_notify_end_time is still None,  
			
		
	
		
			
				
					                    # just in case another thread started.  
			
		
	
		
			
				
					                    settings . running_notify_end_time  =  end_time . isoformat ( )  
			
		
	
		
			
				
					                    db . session . commit ( )  
			
		
	
		
			
				
					                    # this check was generated by Copilot; it's probably unnecessary  
			
		
	
		
			
				
					                    if  settings . running_notify_end_time  ==  end_time . isoformat ( ) :  
			
		
	
		
			
				
					                        # Now get the 'HH:MM' value for start & end so we can compare to the notify_time field  
			
		
	
		
			
				
					
 
			
		
	
		
			
				
					                        # get all the subscriptions that have a notify_time between start_minute inclusive and end_minute exclusive  
			
		
	
		
			
				
					                        all_subscriptions  =  Subscription . query . filter (  
			
		
	
		
			
				
					                            and_ ( Subscription . notify_time  > =  start_minute ,  Subscription . notify_time  <  end_minute )  
			
		
	
		
			
				
					                        )  
			
		
	
		
			
				
					
 
			
		
	
		
			
				
					                        # Send a push notification to each subscribed client  
			
		
	
		
			
				
					                        num_subscriptions  =  all_subscriptions . count ( )  
			
		
	
		
			
				
					                        for  subscription  in  all_subscriptions :  
			
		
	
		
			
				
					                            subscription_info  =  {  
			
		
	
		
			
				
					                                " endpoint " :  subscription . endpoint ,  
			
		
	
	
		
			
				
					
						
						
						
							
								 
						
					 
				
				@ -227,15 +292,39 @@ class WebPushService(): 
			
		
	
		
			
				
					                                }  
			
		
	
		
			
				
					                            }  
			
		
	
		
			
				
					                            result  =  WebPushService . _send_push_notification ( subscription_info ,  message ,  vapid_key )  
			
		
	
		
			
				
					                    print ( f " Result from sub  { subscription . id } : success= { result [ ' success ' ] }  text= { result [ ' message ' ] } " ,  flush = True )  
			
		
	
		
			
				
					                print ( f " { now }  - Finished sending  { len ( all_subscriptions ) }  subscriptions. " ,  flush = True )  
			
		
	
		
			
				
					                            print (  
			
		
	
		
			
				
					                                f " Result from sub  { subscription . id } : success= { result [ ' success ' ] }  text= { result [ ' message ' ] } " ,  
			
		
	
		
			
				
					                                flush = True  
			
		
	
		
			
				
					                            )  
			
		
	
		
			
				
					
 
			
		
	
		
			
				
					                        settings . prev_notify_end_time  =  end_time . isoformat ( )  
			
		
	
		
			
				
					                        settings . running_notify_end_time  =  None  
			
		
	
		
			
				
					                        db . session . commit ( )  
			
		
	
		
			
				
					                        print ( f " { now }  - Finished sending  { num_subscriptions }  subscriptions. " ,  flush = True )  
			
		
	
		
			
				
					                    else :  
			
		
	
		
			
				
					                        print ( f " { now }  - Failed to update running_notify_end_time " ,  flush = True )  
			
		
	
		
			
				
					                else :  
			
		
	
		
			
				
					                    print ( f " { now }  - Stopped because we ' re already running a notification check. " ,  flush = True )  
			
		
	
		
			
				
					
 
			
		
	
		
			
				
					            # Sleeping for 24 hours before sending the next set of notifications  
			
		
	
		
			
				
					            time . sleep ( 24  *  60  *  60 )  
			
		
	
		
			
				
					
 
			
		
	
		
			
				
					            self . latest_subscription_run  =  now . isoformat ( )  
			
		
	
		
			
				
					
 
			
		
	
		
			
				
					            # Sleep before repeating  
			
		
	
		
			
				
					            time . sleep ( 5  *  60 )  
			
		
	
		
			
				
					
 
			
		
	
		
			
				
					    # This is an endpoint, routed in __init__  
			
		
	
		
			
				
					    def  ping ( self )  - >  str :  
			
		
	
		
			
				
					        """  
			
		
	
		
			
				
					        Endpoint  to  show  liveness  info  
			
		
	
		
			
				
					
 
			
		
	
		
			
				
					        Returns :  
			
		
	
		
			
				
					        -  Response :  Text  with  some  subscription - run  info  
			
		
	
		
			
				
					        """  
			
		
	
		
			
				
					
 
			
		
	
		
			
				
					        return  f " pong ... version  { PUSH_SERVER_VERSION }  ... with latest subscription run at  { self . latest_subscription_run } "  
			
		
	
		
			
				
					
 
			
		
	
		
			
				
					    # This is an endpoint, routed in __init__  
			
		
	
		
			
				
					    def  regenerate_vapid ( self )  - >  Tuple [ str ,  int ] :  
			
		
	
		
			
				
					    def  regenerate_vapid ( self )  - >  Tuple [ Response ,  int ,  dict [ str ,  str ] ]  |  Tuple [ Response ,  int ] :  
			
		
	
		
			
				
					        """  
			
		
	
		
			
				
					        Endpoint  to  regenerate  VAPID  keys .  
			
		
	
		
			
				
					
 
			
		
	
	
		
			
				
					
						
						
						
							
								 
						
					 
				
				@ -248,7 +337,7 @@ class WebPushService(): 
			
		
	
		
			
				
					        Header :  Authentication :  Basic  . . .  
			
		
	
		
			
				
					
 
			
		
	
		
			
				
					        Returns :  
			
		
	
		
			
				
					        -  t uplewith  " success "  as  True  or  False ,  and  " message "  message  string  
			
		
	
		
			
				
					        -  T uplewith  " success "  as  True  or  False ,  and  " message "  message  string  
			
		
	
		
			
				
					
 
			
		
	
		
			
				
					        Notes :  
			
		
	
		
			
				
					        -  If  the  operation  is  successful ,  a  JSON  response  with  a  success  message  is  returned  with  a  200  status  code .  
			
		
	
	
		
			
				
					
						
							
								 
						
						
							
								 
						
						
					 
				
				@ -312,7 +401,7 @@ class WebPushService(): 
			
		
	
		
			
				
					
 
			
		
	
		
			
				
					    @staticmethod  
			
		
	
		
			
				
					    @app . route ( ' /web-push/subscribe ' ,  methods = [ ' POST ' ] )  
			
		
	
		
			
				
					    def  subscribe ( )  - >  Tuple [ str ,  int ] :  
			
		
	
		
			
				
					    def  subscribe ( )  - >  Tuple [ Response ,  int ] :  
			
		
	
		
			
				
					        """  
			
		
	
		
			
				
					        Endpoint  to  handle  new  web  push  subscription  requests .  
			
		
	
		
			
				
					
 
			
		
	
	
		
			
				
					
						
							
								 
						
						
							
								 
						
						
					 
				
				@ -344,10 +433,21 @@ class WebPushService(): 
			
		
	
		
			
				
					        if  not  vapid_key :  
			
		
	
		
			
				
					            return  jsonify ( success = False ,  message = " No VAPID keys available " ) ,  500  
			
		
	
		
			
				
					
 
			
		
	
		
			
				
					        # Constructing the notify_time string  
			
		
	
		
			
				
					        notify_time  =  " 13:13 "   # random time that is in most people's waking hours (server time, typically UTC)  
			
		
	
		
			
				
					        if  ( ' notifyTime '  in  content )  and  ( ' utcHour '  in  content [ ' notifyTime ' ] ) :  
			
		
	
		
			
				
					            notify_hour  =  content [ ' notifyTime ' ] [ ' utcHour ' ]  
			
		
	
		
			
				
					            if  ' minute '  in  content [ ' notifyTime ' ] :  
			
		
	
		
			
				
					                notify_minute  =  content [ ' notifyTime ' ] [ ' minute ' ]  
			
		
	
		
			
				
					            else :  
			
		
	
		
			
				
					                notify_minute  =  0  
			
		
	
		
			
				
					            notify_time  =  ' {:02d} ' . format ( notify_hour )  +  " : "  +  ' {:02d} ' . format ( notify_minute )  
			
		
	
		
			
				
					
 
			
		
	
		
			
				
					        # Creating a new Subscription instance with the provided data  
			
		
	
		
			
				
					        subscription  =  Subscription ( endpoint = content [ ' endpoint ' ] ,  
			
		
	
		
			
				
					        subscription  =  Subscription ( auth = content [ ' keys ' ] [ ' auth ' ] ,  
			
		
	
		
			
				
					                                    endpoint = content [ ' endpoint ' ] ,  
			
		
	
		
			
				
					                                    notify_time = notify_time ,  
			
		
	
		
			
				
					                                    p256dh = content [ ' keys ' ] [ ' p256dh ' ] ,  
			
		
	
		
			
				
					                                    auth = content [ ' keys ' ] [ ' auth ' ] ,  
			
		
	
		
			
				
					                                    vapid_key_id = vapid_key . id )  
			
		
	
		
			
				
					
 
			
		
	
		
			
				
					        # Saving the subscription data to the database  
			
		
	
	
		
			
				
					
						
						
						
							
								 
						
					 
				
				@ -355,7 +455,8 @@ class WebPushService(): 
			
		
	
		
			
				
					        db . session . commit ( )  
			
		
	
		
			
				
					
 
			
		
	
		
			
				
					        # Introducing a delay (ensure that gateway endpoint is available)  
			
		
	
		
			
				
					        time . sleep ( 10 )  
			
		
	
		
			
				
					        # ... which I'm now commenting out because there's no pending request so it doesn't make sense... we'll see if things still work  
			
		
	
		
			
				
					        #time.sleep(10)  
			
		
	
		
			
				
					
 
			
		
	
		
			
				
					        # Constructing the subscription information for the push notification  
			
		
	
		
			
				
					        subscription_info  =  {  
			
		
	
	
		
			
				
					
						
						
						
							
								 
						
					 
				
				@ -373,12 +474,12 @@ class WebPushService(): 
			
		
	
		
			
				
					        result  =  WebPushService . _send_push_notification ( subscription_info ,  message ,  vapid_key )  
			
		
	
		
			
				
					
 
			
		
	
		
			
				
					        # Returning the operation status  
			
		
	
		
			
				
					        return  jsonify ( success = result [ " success " ] ,  message = result [ " message " ] )  
			
		
	
		
			
				
					        return  jsonify ( success = result [ " success " ] ,  message = result [ " message " ] ) ,  200  
			
		
	
		
			
				
					
 
			
		
	
		
			
				
					
 
			
		
	
		
			
				
					    @staticmethod  
			
		
	
		
			
				
					    @app . route ( ' /web-push/unsubscribe ' ,  methods = [ ' POST ' ] )  
			
		
	
		
			
				
					    def  unsubscribe ( )  - >  Tuple [ str ,  int ] :  
			
		
	
		
			
				
					    def  unsubscribe ( )  - >  Tuple [ Response ,  int ] :  
			
		
	
		
			
				
					        """  
			
		
	
		
			
				
					        Endpoint  to  handle  web  push  unsubscription  requests .  
			
		
	
		
			
				
					
 
			
		
	
	
		
			
				
					
						
							
								 
						
						
							
								 
						
						
					 
				
				@ -409,7 +510,7 @@ class WebPushService(): 
			
		
	
		
			
				
					        if  subscription :  
			
		
	
		
			
				
					            db . session . delete ( subscription )  
			
		
	
		
			
				
					            db . session . commit ( )  
			
		
	
		
			
				
					            return  jsonify ( success = True ,  message = " Subscription deleted successfully " )  
			
		
	
		
			
				
					            return  jsonify ( success = True ,  message = " Subscription deleted successfully " ) ,  200  
			
		
	
		
			
				
					
 
			
		
	
		
			
				
					        # If the subscription is not found, return an error message  
			
		
	
		
			
				
					        else :  
			
		
	
	
		
			
				
					
						
						
						
							
								 
						
					 
				
				@ -418,7 +519,7 @@ class WebPushService(): 
			
		
	
		
			
				
					
 
			
		
	
		
			
				
					    @staticmethod  
			
		
	
		
			
				
					    @app . route ( ' /web-push/send-test ' ,  methods = [ ' POST ' ] )  
			
		
	
		
			
				
					    def  send_test ( )  - >  Tuple [ str ,  int ] :  
			
		
	
		
			
				
					    def  send_test ( )  - >  Tuple [ Response ,  int ] :  
			
		
	
		
			
				
					        """  
			
		
	
		
			
				
					        Endpoint  to  send  a  test  push  notification  to  a  specific  client .  
			
		
	
		
			
				
					
 
			
		
	
	
		
			
				
					
						
							
								 
						
						
							
								 
						
						
					 
				
				@ -473,7 +574,7 @@ class WebPushService(): 
			
		
	
		
			
				
					            )  
			
		
	
		
			
				
					
 
			
		
	
		
			
				
					            print ( f " Test sent:  { result [ ' success ' ] } " )  
			
		
	
		
			
				
					            return  jsonify ( success = result [ " success " ] ,  message = result [ " message " ] )  
			
		
	
		
			
				
					            return  jsonify ( success = result [ " success " ] ,  message = result [ " message " ] ) ,  200  
			
		
	
		
			
				
					        else :  
			
		
	
		
			
				
					            print ( f " Test failed due to missing subscription. Request:  { json . dumps ( content ) } " )  
			
		
	
		
			
				
					            return  jsonify ( { " success " :  False ,  " message " :  " Subscription not found " } ) ,  404