def lambda_handler(event, context): """ Handler function for Lambda events Deletes a media entry from the database """ # Get the mediaId mediaId = cc.get_queryString(event, "mediaid") try: if not mediaId.isdigit(): raise Exception except Exception as e: # Return an error to the client if a mediaId is not specified correctly msg = f"'mediaid' must be specified in the queryStringParameters header and must be an integer." reason = {"reason": msg} return cc.response_bad_request(json.dumps(reason)) #Create a connection to the database conn = cc.db_connect(os.environ["dbName"], os.environ["dbUser"], os.environ["dbHost"], os.environ["dbPass"]) # Delete the media entry try: with conn, conn.cursor() as cursor: cursor.execute(sql.SQL("DELETE FROM {} WHERE mediaid = %s;").format(sql.Identifier("media")), [mediaId]) except psycopg2.Error as e: print(f"Error: {e}") return cc.response_bad_request(json.dumps(json.dumps("An error occured when removing the media entry."))) return cc.response_ok(json.dumps(f'Removed the media entry for mediaid: {mediaId}.'))
def insertMedia(conn, media): """Inserts media data into the media table Arguments: conn: A connection to the database media: A tuple containing the media data """ try: with conn, conn.cursor() as cursor: cursor.execute("""CREATE TABLE IF NOT EXISTS media (mediaId SERIAL NOT NULL, carId int4 NOT NULL, name varchar(100), type varchar(30) NOT NULL, link varchar(250) NOT NULL, primaryTag int4 NOT NULL, secondaryTag int4, PRIMARY KEY (mediaId), FOREIGN KEY (carId) REFERENCES car (carId), FOREIGN KEY (primaryTag) REFERENCES tag(tagId), FOREIGN KEY (secondaryTag) REFERENCES tag (tagId));""") cursor.execute("INSERT INTO media (carId, name, type, link, primaryTag, secondaryTag) VALUES %s", [media,]) #If all of the writes were successfuly, return a 200 response code. return cc.response_ok("Successfully added media to database") except psycopg2.Error as e: print(e) #If all of the writes were successfuly, return a 200 response code. return cc.response_bad_request(repr(e))
def lambda_handler(event, context): """ Handler function for Lambda events Returns all of the media in the database for a specified car and tag as JSON """ # Get the carid carId = cc.get_queryString(event, "carid") try: if not carId.isdigit(): raise Exception except Exception as e: # Return an error to the client if a carId is not specified correctly msg = f"'carid' must be specified in the queryStringParameters header and must be an integer." reason = {"reason": msg} return cc.response_bad_request(json.dumps(reason)) # Get the tagid tagId = cc.get_queryString(event, "tagid") try: if not tagId.isdigit(): raise Exception except Exception as e: # Return an error to the client if a tagId is not specified correctly msg = f"'tagid' must be specified in the queryStringParameters header and must be an integer." reason = {"reason": msg} return cc.response_bad_request(json.dumps(reason)) #Create a connection to the database conn = cc.db_connect(os.environ["dbName"], os.environ["dbUser"], os.environ["dbHost"], os.environ["dbPass"]) # Return the list of media if(conn != None): return cc.response_ok(json.dumps(get_media_by_car_tag(conn, carId, tagId)))
def insertArButtons(conn, buttons): """Inserts AR buttons into the ar_button table Arguments: conn: A connection to the database media: A list of tuples containing the AR buttons """ try: with conn, conn.cursor() as cursor: cursor.execute("""CREATE TABLE IF NOT EXISTS ar_button (ar_buttonId SERIAL NOT NULL, feature varchar(100) NOT NULL, section varchar(50) NOT NULL, image varchar(250) NOT NULL, PRIMARY KEY (ar_buttonId));""") #Executes an insert SQL query to insert the AR button data psycopg2.extras.execute_values( cursor, "INSERT INTO ar_button (feature, section, image) VALUES %s", buttons) #If all of the writes were successfuly, return a 200 response code. return cc.response_ok("Successfully added AR buttons to database") except psycopg2.Error as e: print(e) #If the writing failed return a 400 response code. return cc.response_bad_request(repr(e))
def lambda_handler(event, context): """ Handler function for Lambda events Returns all of the available AR buttons """ #Create a connection to the database conn = cc.db_connect(os.environ["dbName"], os.environ["dbUser"], os.environ["dbHost"], os.environ["dbPass"]) # Return the list of ar features and tags if (conn != None): return cc.response_ok(json.dumps(getArButtons(conn)))
def lambda_handler(event, context): """ Handler function for Lambda events Returns all of the media in the database for a specified car as JSON """ # Get the carid carId = cc.get_queryString(event, "carid") try: if not carId.isdigit(): raise Exception except Exception as e: # Return an error to the client if a carId is not specified correctly msg = f"'carid' must be specified in the queryStringParameters header and must be an integer." reason = {"reason": msg} return cc.response_bad_request(json.dumps(reason)) # Get the optional tagNames tagNames = cc.get_queryString(event, "tagnames") #Create a connection to the database conn = cc.db_connect(os.environ["dbName"], os.environ["dbUser"], os.environ["dbHost"], os.environ["dbPass"]) # Return the list of media if(conn != None): if tagNames and tagNames == "true": mediaJson = get_media_by_car(conn, carId) tagJson = get_tag_by_car(conn, carId) tagDict = {td["tagid"]:td["name"] for td in tagJson} for md in mediaJson: md["primarytagname"] = tagDict[md["primarytag"]] md["secondarytagname"] = "N/A" if md["secondarytag"] == None else tagDict[md["secondarytag"]] return cc.response_ok(json.dumps(mediaJson)) # Get the media without the tag names return cc.response_ok(json.dumps(get_media_by_car(conn, carId)))
def lambda_handler(event, context): """ Handler function for Lambda events Removes a specific car and all associated data from the database """ # Get the carId carId = cc.get_queryString(event, "carid") try: if not carId.isdigit(): raise Exception except Exception as e: # Return an error to the client if a carId is not specified correctly msg = f"'carid' must be specified in the queryStringParameters header and must be an integer." reason = {"reason": msg} return cc.response_bad_request(json.dumps(reason)) #Create a connection to the database conn = cc.db_connect(os.environ["dbName"], os.environ["dbUser"], os.environ["dbHost"], os.environ["dbPass"]) # Delete the car and all its data try: with conn, conn.cursor() as cursor: # Remove all the media for the car cursor.execute( sql.SQL("DELETE FROM {} WHERE carid = %s;").format( sql.Identifier("media")), [carId]) # Remove all ar_tag entries for the car cursor.execute( sql.SQL( "DELETE FROM {} USING ar WHERE ar.carid = %s AND ar.arid = ar_tag.arid;" ).format(sql.Identifier("ar_tag")), [carId]) # Remove all the tags for the car cursor.execute("DELETE FROM tag WHERE carid = %s", [carId]) # Remove all the ar tags for the car cursor.execute("DELETE FROM ar WHERE carid = %s", [carId]) # Remove the car cursor.execute("DELETE FROM car WHERE carid = %s", [carId]) except psycopg2.Error as e: print(f"Error: {e}") return cc.response_bad_request( json.dumps(json.dumps("An error occured when removing the car."))) return cc.response_ok( json.dumps(f'Removed the car and all data for carid: {carId}.'))
def lambda_handler(event, context): """ Handler function for Lambda events Returns all of the cars in the database as JSON """ # Get the platform: web or iOS platform = cc.get_queryString(event, "platform") if not platform in cc.valid_platforms: # Return an error to the client if a platform is not specified correctly msg = f"'platform' must be specified in the queryStringParameters header with a value from: {cc.valid_platforms}." reason = {"reason": msg} return cc.response_bad_request(json.dumps(reason)) #Create a connection to the database conn = cc.db_connect(os.environ["dbName"], os.environ["dbUser"], os.environ["dbHost"], os.environ["dbPass"]) # Return the list of cars if (conn != None): return cc.response_ok(json.dumps(get_car_all(conn, platform)))
def insertAr(conn, ar): """Inserts AR data into the ar table Arguments: conn: A connection to the database ar: A list of tuples containing the AR data """ try: with conn, conn.cursor() as cursor: cursor.execute("""CREATE TABLE IF NOT EXISTS ar (ar_buttonid int4 NOT NULL, carId int4 NOT NULL, enabled bool NOT NULL, location varchar(50) NOT NULL, primaryTag int4 NOT NULL, secondaryTag int4, PRIMARY KEY (ar_buttonid, carId));""") #Executes an insert SQL query to insert the player data psycopg2.extras.execute_values(cursor, """INSERT INTO ar (carId, enabled, location, primaryTag, secondaryTag, ar_buttonid) VALUES %s ON CONFLICT (carId, ar_buttonid) DO UPDATE SET enabled = EXCLUDED.enabled, location = EXCLUDED. location, primaryTag = EXCLUDED.primaryTag, secondaryTag = EXCLUDED.secondaryTag """, ar) #If all of the writes were successful, return a 200 response code. return cc.response_ok("Successfully added AR to database") except psycopg2.Error as e: print(e) #If the write fails, return a 400 response code. return cc.response_bad_request(repr(e))
def lambda_handler(event, context): #Try to retrieve the appropriate data from the body. If an error occurs, send a 400 error code as a response try: body = json.loads(event["body"]) make = body["make"].title() model = body["model"].title() year = body["year"] icon = "https://owner.ford.com/ownerlibs/content/dam/assets/ford/vehicle/" + str(year) + "/" + str(year) + "-" + make.lower() + "-" + model.lower() + "-s.png" except Exception as e: print(e) return cc.response_bad_request("Invalid body format. Please follow formatting instructions.") if(int(year) < 2005): return cc.response_bad_request("Cannot add vehicle prior to 2005.") try: #Build the url to retrieve the PDFs for this vehicle url = "https://www.fleet.ford.com/aemservices/cache/ownermanuals?" "year="+ str(year) + "&" + "make=" + make.lower() + "&" + "model=" + model.title() + "&country=USA&language=EN-US" page = requests.get(url) data = json.loads(page.text) #Parse the returned JSON to find the latest version of the owner's manual ownerManual = "" pattern = re.compile("Owner's Manual Printing \d") for item in data: if(pattern.match(item["title"])): ownerManual = item["link"] print(ownerManual) except Exception as e: print(e) return cc.response_bad_request("Invalid vehicle make, model, or year.") #Create a tuple containing the vehicle data car = [make, model, year, ownerManual, icon] #Call the writeCar function and get a response containing the carId of the row written to the DB writeCarResponse = lambdaClient.invoke( FunctionName= os.environ['writeCarArn'], InvocationType='RequestResponse', LogType='None', Payload=json.dumps(car), ) writeCarResponse = writeCarResponse['Payload'].read().decode('utf-8').strip('\"') print(writeCarResponse) #Check the writeCarResponse to see if the car was successfully written to the database try: #Try to convert the response to an int. If it fails, it means the database write failed. carId = int(writeCarResponse) #Call generateTags Lambda to generate tags from the linked owner's manual and wait for a response payload = {"carId": carId, "manualUrl": ownerManual} generateTagsResponse = lambdaClient.invoke( FunctionName= os.environ['generateTagsArn'], InvocationType='RequestResponse', LogType='None', Payload=json.dumps(payload), ) generateTagsResponse = generateTagsResponse['Payload'].read().decode('utf-8').strip('\"') print(generateTagsResponse) except: #Return the error message from attempting to write the car to the database return cc.response_bad_request(writeCarResponse) #Check the response from generating the tags try: list(generateTagsResponse) #Call writeTags Lambda to write the generated tags to the database writeTagsResponse = lambdaClient.invoke( FunctionName= os.environ['writeTagsArn'], InvocationType='RequestResponse', LogType='None', Payload=json.dumps(generateTagsResponse), ) except: #Return the error message from attempting to write the car to the database return cc.response_bad_request("Unable to generate tags for the vehicle. Ensure the link to the owner's manual is the correct PDF") #If all of the writes were successfuly, return a 200 response code. return cc.response_ok("Successfully created new vehicle") #TODO: Write AR features after writeMedia has been completed and AR tagging writing is next. """