victoria-latynina commited on
Commit
976c655
Β·
verified Β·
1 Parent(s): f263bbb

Upload whoop_gradio_server.py

Browse files
Files changed (1) hide show
  1. whoop_gradio_server.py +116 -0
whoop_gradio_server.py ADDED
@@ -0,0 +1,116 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #!/usr/bin/env python3
2
+ import os
3
+ from pathlib import Path
4
+ from datetime import datetime, timedelta
5
+ import logging
6
+
7
+ import gradio as gr
8
+ from dotenv import load_dotenv
9
+ from whoop import WhoopClient
10
+
11
+ # Configure logging
12
+ logging.basicConfig(level=logging.INFO)
13
+ logger = logging.getLogger(__name__)
14
+
15
+ # Global Whoop client
16
+ whoop_client = None
17
+
18
+ def initialize_whoop_client():
19
+ global whoop_client
20
+ env_path = Path(__file__).parent / 'config' / '.env'
21
+
22
+ if not env_path.exists():
23
+ return "❌ .env file not found."
24
+
25
+ load_dotenv(dotenv_path=env_path)
26
+ email = os.getenv("WHOOP_EMAIL")
27
+ password = os.getenv("WHOOP_PASSWORD")
28
+
29
+ if not email or not password:
30
+ return "❌ Missing WHOOP_EMAIL or WHOOP_PASSWORD in environment variables."
31
+
32
+ try:
33
+ whoop_client = WhoopClient(username=email, password=password)
34
+ return "βœ… Successfully authenticated with Whoop."
35
+ except Exception as e:
36
+ return f"❌ Authentication failed: {e}"
37
+
38
+ def get_latest_cycle_gr():
39
+ if not whoop_client:
40
+ return "❌ Not authenticated."
41
+
42
+ try:
43
+ end_date = datetime.now().strftime("%Y-%m-%d")
44
+ start_date = (datetime.now() - timedelta(days=1)).strftime("%Y-%m-%d")
45
+ cycles = whoop_client.get_cycle_collection(start_date, end_date)
46
+ if not cycles:
47
+ return "⚠️ No cycle data available."
48
+
49
+ latest = cycles[0]
50
+ score = latest.get("score", {}).get("recovery", "N/A")
51
+ return f"πŸŒ€ Latest Cycle:\nRecovery Score: {score}\n\nFull Data:\n{latest}"
52
+ except Exception as e:
53
+ return f"❌ Error: {e}"
54
+
55
+ def get_average_strain_gr(days):
56
+ if not whoop_client:
57
+ return "❌ Not authenticated."
58
+
59
+ try:
60
+ end_date = datetime.now().strftime("%Y-%m-%d")
61
+ start_date = (datetime.now() - timedelta(days=int(days))).strftime("%Y-%m-%d")
62
+ cycles = whoop_client.get_cycle_collection(start_date, end_date)
63
+
64
+ if not cycles:
65
+ return "⚠️ No cycle data available."
66
+
67
+ strains = [c['score']['strain'] for c in cycles if c.get('score') and c['score'].get('strain') is not None]
68
+ if not strains:
69
+ return "⚠️ No strain data available."
70
+
71
+ avg = sum(strains) / len(strains)
72
+ return f"πŸ“Š Average Strain over {days} days: {avg:.2f} (from {len(strains)} entries)"
73
+ except Exception as e:
74
+ return f"❌ Error: {e}"
75
+
76
+ def get_auth_status_gr():
77
+ if not whoop_client:
78
+ return "πŸ”’ Not authenticated."
79
+
80
+ try:
81
+ profile = whoop_client.get_profile()
82
+ return f"πŸ”“ Authenticated.\nUser: {profile.get('name', 'Unknown')}\nEmail: {profile.get('email', 'Unknown')}"
83
+ except Exception as e:
84
+ return f"❌ Error checking auth: {e}"
85
+
86
+ # UI definition
87
+ with gr.Blocks(title="Whoop API Explorer") as demo:
88
+ gr.Markdown("# 🧠 WHOOP API Dashboard")
89
+ gr.Markdown("Authenticate and explore your recovery and strain data.")
90
+
91
+ with gr.Row():
92
+ auth_output = gr.Textbox(label="Auth Status", interactive=False)
93
+ auth_button = gr.Button("Authenticate with Whoop")
94
+
95
+ with gr.Row():
96
+ cycle_output = gr.Textbox(label="Latest Cycle", lines=10, interactive=False)
97
+ cycle_button = gr.Button("Get Latest Cycle")
98
+
99
+ with gr.Row():
100
+ days_input = gr.Number(value=7, label="Days for Avg Strain")
101
+ strain_output = gr.Textbox(label="Average Strain", lines=4, interactive=False)
102
+ strain_button = gr.Button("Get Average Strain")
103
+
104
+ with gr.Row():
105
+ status_output = gr.Textbox(label="Whoop Profile Info", lines=4, interactive=False)
106
+ status_button = gr.Button("Check Auth Status")
107
+
108
+ # Bind actions
109
+ auth_button.click(fn=initialize_whoop_client, outputs=auth_output)
110
+ cycle_button.click(fn=get_latest_cycle_gr, outputs=cycle_output)
111
+ strain_button.click(fn=get_average_strain_gr, inputs=days_input, outputs=strain_output)
112
+ status_button.click(fn=get_auth_status_gr, outputs=status_output)
113
+
114
+ # Launch app
115
+ if __name__ == "__main__":
116
+ demo.launch(mcp_server=True)