File size: 5,361 Bytes
976c655 d9c9ba1 149df1f 976c655 d9c9ba1 976c655 149df1f 976c655 149df1f 976c655 149df1f 976c655 149df1f 976c655 149df1f 976c655 149df1f 976c655 149df1f 976c655 149df1f 976c655 d9c9ba1 149df1f 976c655 |
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 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 |
#!/usr/bin/env python3
import os
from datetime import datetime, timedelta
import logging
import gradio as gr
from whoop import WhoopClient
# Configure logging
logging.basicConfig(level=logging.INFO)
logger = logging.getLogger(__name__)
# Global Whoop client
whoop_client = None
def initialize_whoop_client_with_input(email, password):
"""
Authenticates a user using the provided WHOOP email and password.
Stores credentials in the environment variables and initializes the WhoopClient.
Args:
email (str): WHOOP account email.
password (str): WHOOP account password.
Returns:
str: Success or error message indicating authentication status.
"""
global whoop_client
if not email or not password:
return "β Please enter both email and password."
os.environ["WHOOP_EMAIL"] = email
os.environ["WHOOP_PASSWORD"] = password
try:
whoop_client = WhoopClient(username=email, password=password)
return "β
Successfully authenticated with Whoop."
except Exception as e:
return f"β Authentication failed: {e}"
def get_latest_cycle_gr():
"""
Retrieves the most recent WHOOP cycle (recovery data) for the authenticated user.
Returns:
str: Summary of latest recovery data or an error message.
"""
if not whoop_client:
return "β Not authenticated."
try:
end_date = datetime.now().strftime("%Y-%m-%d")
start_date = (datetime.now() - timedelta(days=1)).strftime("%Y-%m-%d")
cycles = whoop_client.get_cycle_collection(start_date, end_date)
if not cycles:
return "β οΈ No cycle data available."
latest = cycles[0]
score = latest.get("score", {}).get("recovery")
recovery_score = f"{score}" if score is not None else "Not Available"
return f"π Latest Cycle:\nRecovery Score: {recovery_score}\n\nFull Data:\n{latest}"
except Exception as e:
return f"β Error: {e}"
def get_average_strain_gr(days):
"""
Calculates the average strain over a given number of past days.
Args:
days (int): Number of days to include in the average.
Returns:
str: Average strain value or an error message.
"""
if not whoop_client:
return "β Not authenticated."
try:
end_date = datetime.now().strftime("%Y-%m-%d")
start_date = (datetime.now() - timedelta(days=int(days))).strftime("%Y-%m-%d")
cycles = whoop_client.get_cycle_collection(start_date, end_date)
if not cycles:
return "β οΈ No cycle data available."
strains = [c['score']['strain'] for c in cycles if c.get('score') and c['score'].get('strain') is not None]
if not strains:
return "β οΈ No strain data available."
avg = sum(strains) / len(strains)
return f"π Average Strain over {days} days: {avg:.2f} (from {len(strains)} entries)"
except Exception as e:
return f"β Error: {e}"
def format_latest_cycle(raw_text):
"""
Formats the raw text returned by get_latest_cycle_gr for display.
Args:
raw_text (str): Raw output from get_latest_cycle_gr.
Returns:
Tuple[str, str]: A short summary and detailed cycle data.
"""
if raw_text.startswith("β") or raw_text.startswith("β οΈ"):
return raw_text, ""
try:
lines = raw_text.splitlines()
recovery_score_line = next((line for line in lines if "Recovery Score" in line), "Recovery Score: Not Available")
full_data = "\n".join(lines[2:]) # skip title and recovery line
return recovery_score_line, full_data
except Exception as e:
return f"β Failed to parse cycle: {e}", ""
# UI definition
with gr.Blocks(title="Whoop API Explorer") as demo:
gr.Markdown("# π§ WHOOP API Dashboard")
gr.Markdown("Easily authenticate and explore your WHOOP recovery and strain data.")
with gr.Group():
gr.Markdown("## π Authentication")
with gr.Row():
email_input = gr.Textbox(label="WHOOP Email", placeholder="[email protected]")
password_input = gr.Textbox(label="WHOOP Password", type="password", placeholder="β’β’β’β’β’β’β’β’")
auth_button = gr.Button("Authenticate")
auth_output = gr.Label(label="Auth Status")
with gr.Group():
gr.Markdown("## π Latest Recovery Cycle")
cycle_button = gr.Button("Fetch Latest Cycle")
latest_recovery = gr.Label(label="Recovery Score")
cycle_details = gr.Textbox(label="Full Cycle Data", visible=False, lines=6)
with gr.Group():
gr.Markdown("## π Strain Insights")
with gr.Row():
days_input = gr.Number(value=7, label="Number of Days", precision=0)
strain_button = gr.Button("Calculate Average Strain")
average_strain = gr.Label(label="Average Strain")
# Bind actions
auth_button.click(fn=initialize_whoop_client_with_input, inputs=[email_input, password_input], outputs=auth_output)
cycle_button.click(fn=lambda: format_latest_cycle(get_latest_cycle_gr()), outputs=[latest_recovery, cycle_details])
strain_button.click(fn=get_average_strain_gr, inputs=days_input, outputs=average_strain)
# Launch app
if __name__ == "__main__":
demo.launch(mcp_server=True) |