File size: 6,065 Bytes
5af9455
 
 
 
ab41f96
 
5af9455
 
ab41f96
5af9455
ab41f96
5af9455
ab41f96
5af9455
 
 
 
 
ab41f96
5af9455
 
 
 
 
 
 
 
 
 
 
 
 
 
ab41f96
5af9455
 
 
 
 
ab41f96
5af9455
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
ab41f96
5af9455
 
ab41f96
5af9455
 
 
 
 
ab41f96
5af9455
ab41f96
5af9455
 
 
 
 
 
 
 
ab41f96
5af9455
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
ab41f96
5af9455
 
ab41f96
5af9455
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
from flask import Flask, request, jsonify, make_response
from requests.auth import HTTPBasicAuth
from helpers import *
import requests
import os

app = Flask(__name__)
app.config['MAX_CONTENT_LENGTH'] = 16 * 1024 * 1024

def post_candidate_analysis_to_lever(analysis_result, candidate_id):
    """
    Sends the analysis result of a candidate's video interview to Lever via a POST request.

    This function constructs a request to the Lever API to add a note to a specific opportunity
    (candidate) identified by the candidate_id. The note contains the result of the machine learning
    analysis of the candidate's video interview. It handles various exceptions that might occur during
    the request, logs the attempt and outcome of the request, and ensures that any HTTP or connection
    errors are caught and logged appropriately.

    Parameters:
    - analysis_result (str): The result of the video interview analysis to be sent to Lever.
    - candidate_id (str): The unique identifier for the candidate/opportunity in Lever.

    Returns:
    - dict: The JSON response from the Lever API if the request is successful.
    - None: If the request fails due to an exception, the function returns None.

    The function logs an info message before sending the data, and upon successful data transmission.
    In case of exceptions such as HTTPError, ConnectionError, Timeout, or any other RequestException,
    it logs the specific error. A general exception catch is also implemented to log any unexpected errors.

    It uses the requests library for making HTTP requests, and the HTTPBasicAuth for authentication.
    The Lever API key is expected to be available as an environment variable 'LeverKey'.
    """
    lever_api_url = 'https://api.lever.co/v1/opportunities/{}/notes'.format(candidate_id)
    data = {
        "value": "Video Interview ML Decision: {}".format(analysis_result)
    }
    
    try:
        # Log the attempt to send data
        logging.info(f"Sending analysis result to Lever for candidate ID {candidate_id}")
        
        response = requests.post(lever_api_url, auth=HTTPBasicAuth(os.getenv('LeverKey'), ''), json=data)
        
        # Check if the request was successful
        response.raise_for_status()
        
        # Log successful data sending
        logging.info(f"Successfully sent analysis result to Lever for candidate ID {candidate_id}")
        
        return response.json()
    except requests.exceptions.HTTPError as http_err:
        # Log HTTP errors (e.g., 404, 401, etc.)
        logging.error(f'HTTP error occurred: {http_err}')
    except requests.exceptions.ConnectionError as conn_err:
        # Log connection errors (e.g., DNS failure, refused connection, etc.)
        logging.error(f'Connection error occurred: {conn_err}')
    except requests.exceptions.Timeout as timeout_err:
        # Log timeout errors
        logging.error(f'Timeout error occurred: {timeout_err}')
    except requests.exceptions.RequestException as req_err:
        # Log any other requests-related errors
        logging.error(f'Error sending data to Lever: {req_err}')
    except Exception as e:
        # Catch-all for any other exceptions not related to requests
        logging.error(f'An unexpected error occurred: {e}')

    # Return None or an appropriate response in case of failure
    return None

@app.route('/webhook', methods=['POST'])
def handle_webhook():
    """
    Processes incoming webhook POST requests, analyzes video transcripts, and posts results to Lever.

    Validates the presence of required data ('opportunityId') in the request, retrieves the candidate's
    video URL, analyzes the video transcript, and sends the analysis result to Lever. It handles errors
    at each step by logging the error and returning an appropriate HTTP response.

    Returns:
        - A success response with the analysis result and a 200 status code if all operations succeed.
        - An error response with a relevant message and an appropriate status code (400, 404, 500) if any operation fails.
    """
    try:
        data = request.json
        if not data:
            # If no data is received
            logging.error("No data received in request")
            return make_response(jsonify({"error": "No data received"}), 400)

        opportunity_id = data.get('opportunityId')
        if not opportunity_id:
            # If opportunityId is not provided in the data
            logging.error("No opportunityId provided")
            return make_response(jsonify({"error": "No opportunityId provided"}), 400)

        candidate_video_url = get_youtube_url(opportunity_id)
        if not candidate_video_url:
            # If no URL is returned for the given opportunity_id
            logging.error(f"Unable to process video URL for opportunityId {opportunity_id}")
            analysis_result = "Unable to process the video URL. Currently only YouTube URLs are accepted."

            return jsonify(analysis_result), 200

        analysis_result = analyze_transcript(candidate_video_url)
        if analysis_result is None:
            # Handle case where analysis_result is None or an error occurred during analysis
            logging.error(f"Error analyzing transcript for opportunityId {opportunity_id}")
            return make_response(jsonify({"error": "Failed to analyze transcript"}), 500)

        send_result = post_candidate_analysis_to_lever(analysis_result, opportunity_id)
        if send_result is None:
            # Assuming post_candidate_analysis_to_lever returns None on failure
            logging.error(f"Failed to send results to Lever for opportunityId {opportunity_id}")
            return make_response(jsonify({"error": "Failed to send results to Lever"}), 500)
        
        return jsonify(analysis_result), 200
    except Exception as e:
        logging.error(f"An unexpected error occurred: {e}")
        return make_response(jsonify({"error": "An unexpected error occurred"}), 500)

if __name__ == '__main__':
    app.run(debug=True, port=5002)