Skip to content
Snippets Groups Projects
redcap.py 6.1 KiB
Newer Older
Aayush Kachhia's avatar
Aayush Kachhia committed
import requests
import json
from datetime import datetime
from db.db_query import get_config

appv2 = get_config('appv2')
# REDCap API configuration
API_URL = appv2.redcap.REDCAP_API_URL
API_TOKEN = appv2.redcap.REDCAP_API_TOKEN
EVENT_NAME = appv2.redcap.REDCAP_EVENT_NAME
REPEAT_INSTANCE = appv2.redcap.REDCAP_REPEAT_INSTANCE

def get_record(record_id):
    """
    Retrieve a specific record from REDCap by record_id.
    
    Args:
        record_id: The REDCap record ID to retrieve
        
    Returns:
        The record as a dictionary, or None if not found
    """
    payload = {
        "token": API_TOKEN,
        "content": "record",
        "format": "json",
        "type": "flat",
        "records[0]": record_id,
        "returnFormat": "json"
    }
    
    try:
        response = requests.post(API_URL, data=payload)
        if response.status_code == 200:
            records = response.json()
            if records and len(records) > 0:
                return records[0]
    except Exception as e:
        print(f"Error retrieving record {record_id}: {str(e)}")
    
    return None

def update_message_log(record_id, message):
    """
    Update the message_log field in a REDCap record with a new message.
    
    Args:
        record_id: The REDCap record ID to update
        message: The message to add to the log
        
    Returns:
        True if successful, False otherwise
    """
    # First get the current record to see if there's an existing message log
    record = get_record(record_id)
    if not record:
        print(f"Cannot update message log: Record {record_id} not found")
        return False
    
    # Get current message log, if it exists
    current_log = record.get("message_log", "")
    
    # Append new message with timestamp
    timestamp = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
    new_log = f"{current_log}\n[{timestamp}] {message}".strip()
    
    # Prepare data for update
    data = {
        "record_id": record_id,
        "message_log": new_log
    }
    
    # Add event name if specified
    if EVENT_NAME:
        data["redcap_event_name"] = EVENT_NAME
    
    # Convert data to JSON format for the API
    payload = {
        "token": API_TOKEN,
        "content": "record",
        "format": "json",
        "type": "flat",
        "overwriteBehavior": "normal",
        "data": json.dumps([data]),
        "returnContent": "count",
        "returnFormat": "json"
    }
    
    try:
        response = requests.post(API_URL, data=payload)
        if response.status_code == 200:
            try:
                result = response.json()
                if 'count' in result and result['count'] == 1:
                    print(f"Successfully updated message log for record {record_id}")
                    return True
                else:
                    print(f"REDCap API returned: {result}")
            except:
                print(f"REDCap API returned: {response.text}")
        else:
            print(f"Error updating message log: {response.status_code} - {response.text}")
    except Exception as e:
        print(f"Exception updating message log: {str(e)}")
    
    return False

def log_message_sent(record_id, phone_number, survey_link, status="Sent"):
    """
    Log a message sent to a participant in the REDCap record.
    
    Args:
        record_id: The REDCap record ID
        phone_number: The phone number the message was sent to
        survey_link: The survey link that was sent
        status: The status of the message (default: "Sent")
        
    Returns:
        True if successful, False otherwise
    """
    # Create the log message in JSON format
    timestamp = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
    message_data = {
        "timestamp": timestamp,
        "status": f"Message {status}",
        "phone": phone_number,
        "link": survey_link
    }
    
    # Convert JSON to string format for REDCap
    message = json.dumps(message_data, indent=2)
    
    return update_message_log(record_id, message)

def log_message_failed(record_id, phone_number, survey_link, error):
    """
    Log a failed message attempt in the REDCap record.
    
    Args:
        record_id: The REDCap record ID
        phone_number: The phone number the message was attempted to be sent to
        survey_link: The survey link that was to be sent
        error: The error message
        
    Returns:
        True if successful, False otherwise
    """
    # Create the log message in JSON format
    timestamp = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
    message_data = {
        "timestamp": timestamp,
        "status": "Message FAILED",
        "phone": phone_number,
        "link": survey_link,
        "error": error
    }
    
    # Convert JSON to string format for REDCap
    message = json.dumps(message_data, indent=2)
    
    return update_message_log(record_id, message)

def check_message_log_field_exists():
    """
    Check if the message_log field exists in the REDCap project.
    This can be used to validate the setup before using the logging functions.
    
    Returns:
        True if the field exists, False otherwise
    """
    # Get the REDCap metadata (field definitions)
    payload = {
        "token": API_TOKEN,
        "content": "metadata",
        "format": "json",
        "returnFormat": "json"
    }
    
    try:
        response = requests.post(API_URL, data=payload)
        if response.status_code == 200:
            fields = response.json()
            for field in fields:
                if field.get("field_name") == "message_log":
                    return True
            
            print("WARNING: 'message_log' field not found in REDCap project metadata")
            print("Please add a Text Box (notes) field named 'message_log' to your REDCap project")
        else:
            print(f"Error checking metadata: {response.status_code} - {response.text}")
    except Exception as e:
        print(f"Exception checking metadata: {str(e)}")
    
    return False