1+ import requests
2+ import json
3+ import os
4+ import datetime
5+
6+ # THESE MUST BE RESET EVERY TIME FOR NOW
7+ COGNITO_CLIENT_ID = "4rtf569eq2brgk3sq8ek4uqc91"
8+ UPLOAD_API_URL = "https://vo54qpw7fy4uarorbxnplilgae0hhwos.lambda-url.us-west-2.on.aws/"
9+ DOWNLOAD_API_URL = 'https://i5y2mfaoh3capmulqehouzcjya0zwedr.lambda-url.us-west-2.on.aws/'
10+ QUERY_API_URL = 'https://stkjssplyeb5deqgn25wiaix2y0icvzg.lambda-url.us-west-2.on.aws/'
11+
12+ USER_TOKEN = None
13+ LOGIN_TIME = None
14+
15+ def _set_user_token (t ):
16+ global USER_TOKEN
17+ global LOGIN_TIME
18+
19+ LOGIN_TIME = datetime .datetime .now ()
20+ USER_TOKEN = t
21+
22+
23+ def _get_user_token ():
24+ global USER_TOKEN
25+ global LOGIN_TIME
26+ if LOGIN_TIME is None :
27+ print ("New login needed. Login is valid for 60 minutes." )
28+ elif (datetime .datetime .now () - LOGIN_TIME ).total_seconds () >= 3600 :
29+ print ("Login expired. Please log in again." )
30+ else :
31+ return USER_TOKEN
32+
33+ t = get_sdc_token ()
34+
35+ return t
36+
37+
38+ def get_sdc_token (user_name = None , password = None ):
39+ '''
40+ This function authenticates the user. An access token is automatically stored in the USER_TOKEN
41+ variable in this file, and functions will attempt to find a valid user token in that variable.
42+
43+ :param user_name: User's SDC username
44+ :param password: User's SDC password
45+
46+ :return: A string that also gets stored in the USER_TOKEN variable in this file. You don't need this string unless
47+ you plan on making your own API calls, using functions outside of this file.
48+ '''
49+ global COGNITO_CLIENT_ID
50+ if user_name is None :
51+ user_name = input ("Username:" )
52+ if password is None :
53+ import getpass
54+ password = getpass .getpass ("Password for " + user_name + ":" )
55+
56+ authentication_url = "https://cognito-idp.us-west-2.amazonaws.com/"
57+ authentication_headers = {'X-Amz-Target' : 'AWSCognitoIdentityProviderService.InitiateAuth' ,
58+ 'Content-Type' : 'application/x-amz-json-1.1' }
59+ data = json .dumps ({"ClientId" : COGNITO_CLIENT_ID , "AuthFlow" : "USER_PASSWORD_AUTH" ,
60+ "AuthParameters" : {"USERNAME" : user_name , "PASSWORD" : password }})
61+
62+ # Attempt to grab the SDC token.
63+ try :
64+ token_response = requests .post (authentication_url , data = data , headers = authentication_headers )
65+ t = token_response .json ()['AuthenticationResult' ]['AccessToken' ]
66+ except KeyError :
67+ print ("Invalid username and/or password. Please try again. " )
68+ return
69+
70+ _set_user_token (t )
71+
72+ return t
73+
74+ def _execute_api (url , ** kwargs ):
75+ token = _get_user_token ()
76+ headers = {"Authorization" : token }
77+ query_parameters = []
78+ for kw in kwargs :
79+ query_parameters .append (kw + "=" + str (kwargs [kw ]))
80+ query_parameters = '&' .join (query_parameters )
81+ url_with_parameters = url + "?" + query_parameters
82+ print (url_with_parameters )
83+ try :
84+ response = requests .get (url_with_parameters , headers = headers )
85+ except Exception as e :
86+ print (f"Could not finish query due to error { str (e )} " )
87+ return
88+ return response
89+
90+ def download (filename , download_dir = '' ):
91+ '''
92+ This function is used to download files from the SDS.
93+
94+ :param filename: The full S3 URI to download
95+ :param download_dir: The directory on the local machine to download the file to.
96+
97+ :return: None, but downloads the file to the specified download directory
98+ '''
99+ global DOWNLOAD_API_URL
100+ download_url = _execute_api (DOWNLOAD_API_URL , s3_uri = filename )
101+
102+ if (download_url .status_code == 400 ):
103+ print ("Not a valid S3 URI. Example input: s3://bucket/path/file.ext" )
104+ return
105+ elif (download_url .status_code == 404 ):
106+ print ("No files were found matching the given URI." )
107+ return
108+
109+ file_name_and_path = os .path .join (download_dir , filename [5 :])
110+ download_dir = os .path .dirname (file_name_and_path )
111+ if not os .path .exists (download_dir ):
112+ os .makedirs (download_dir )
113+
114+ with open (file_name_and_path , 'wb' ) as file :
115+ print (f"Downloading { file_name_and_path } " )
116+ file_location = requests .get (download_url .json ()["download_url" ])
117+ file .write (file_location .content )
118+
119+ return file_location
120+
121+ def query (** kwargs ):
122+ '''
123+ This function is used to query files from the SDS.
124+ There are no required arguments, the search strings will depend on the mission
125+
126+ :return: This returns JSON with all information about the files.
127+ '''
128+ global QUERY_API_URL
129+ response = _execute_api (QUERY_API_URL , ** kwargs )
130+ return response .json ()
131+
132+ def upload (file_location , file_name , ** kwargs ):
133+ '''
134+ This function is used to upload files to the SDS.
135+
136+ :param file_location: The path to the file on the local machine to upload to the SDS.
137+ :param file_name: The name of the file you'd like to upload
138+ :param kwargs: Any additional key word arguments passed into this function are stored as tags on the SDS.
139+
140+ :return: This returns a requests response object. If the upload was successful, it'll be code 200.
141+ '''
142+ global UPLOAD_API_URL
143+ response = _execute_api (UPLOAD_API_URL , filename = file_name , ** kwargs )
144+
145+ if response .status_code != 200 :
146+ print (f"Could not generate an upload URL with the following error: { response .text } " )
147+ return
148+
149+ with open (file_location , 'rb' ) as object_file :
150+ object_text = object_file .read ()
151+ response = requests .put (response .json (), data = object_text )
152+ return response
153+
154+ if __name__ == "__main__" :
155+ #x = upload(file_location='helloworld.txt', file_name='imap_l0_sci_mag_2024_2.pkts', testing='true')
156+ #print(x)
157+ #x = query(instrument='mag')
158+ #print(x)
159+ x = download ("s3://sds-data-harter-asdfasdf/imap/l0/imap_l0_sci_mag_2024_2.pkts" )
160+ print (x )
0 commit comments