From cf2b4be03385d328190c75d6ba6a70c6ce579016 Mon Sep 17 00:00:00 2001 From: chelsea Date: Tue, 17 Feb 2026 18:33:43 -0600 Subject: [PATCH] med scheduling fixes --- bot/commands/medications.py | 94 ++++++++++++++++++++++++++++++------- 1 file changed, 78 insertions(+), 16 deletions(-) diff --git a/bot/commands/medications.py b/bot/commands/medications.py index 84dc38b..3192402 100644 --- a/bot/commands/medications.py +++ b/bot/commands/medications.py @@ -424,8 +424,18 @@ async def handle_medication(message, session, parsed): await message.channel.send(f"Error: {resp.get('error', 'Failed to log')}") elif action == "take_all": - # Mark all currently pending (untaken, non-skipped, non-PRN) doses as taken + # Auto-mark doses due within the last hour (clearly "just taken"). + # Ask about doses due 1–6 hours ago (today or yesterday) that aren't logged. timezone_offset = await _get_user_timezone(message, session, token) + if timezone_offset is None: + timezone_offset = 0 + + now_local = datetime.now(timezone(timedelta(minutes=-timezone_offset))) + now_min = now_local.hour * 60 + now_local.minute + current_hhmm = now_local.strftime("%H:%M") + + CURRENT_WINDOW_MIN = 60 # ≤ 1 hour ago → auto-mark + LOOKBACK_MIN = 6 * 60 # 1–6 hours ago → ask resp, status = api_request("get", "/api/medications/today", token) if status != 200: @@ -433,34 +443,86 @@ async def handle_medication(message, session, parsed): return meds_today = resp if isinstance(resp, list) else [] - marked = [] - skipped_already = [] + auto_doses = [] # (med_id, med_name, time_str) → mark silently + ask_doses = [] # (med_id, med_name, time_str) → prompt user for item in meds_today: med = item.get("medication", {}) if item.get("is_prn"): continue - times = item.get("scheduled_times", []) - taken = set(item.get("taken_times", [])) + times = item.get("scheduled_times", []) + taken = set(item.get("taken_times", [])) skipped = set(item.get("skipped_times", [])) med_id_local = med.get("id") - med_name = med.get("name", "Unknown") + med_name = med.get("name", "Unknown") - pending_times = [t for t in times if t not in taken and t not in skipped] - if not pending_times: - skipped_already.append(med_name) - continue + for t in times: + if t in taken or t in skipped: + continue - for t in pending_times: - api_request("post", f"/api/medications/{med_id_local}/take", token, {"scheduled_time": t}) - marked.append(f"**{med_name}** ({', '.join(pending_times)})") + h, m = map(int, t.split(":")) + dose_min = h * 60 + m + # Handle doses that cross midnight (yesterday's late doses) + minutes_ago = now_min - dose_min + if minutes_ago < 0: + minutes_ago += 24 * 60 - if not marked: - await message.channel.send("✅ All medications are already logged for today!") - else: + if minutes_ago > LOOKBACK_MIN: + continue # too old — ignore + if t > current_hhmm and minutes_ago > CURRENT_WINDOW_MIN: + continue # future dose that somehow wasn't caught — skip + + if minutes_ago <= CURRENT_WINDOW_MIN: + auto_doses.append((med_id_local, med_name, t)) + else: + ask_doses.append((med_id_local, med_name, t)) + + # Mark the clearly-current doses immediately + marked = [] + for med_id_local, med_name, t in auto_doses: + api_request("post", f"/api/medications/{med_id_local}/take", token, {"scheduled_time": t}) + marked.append(f"**{med_name}** at {t}") + + if marked: lines = "\n".join(f"✅ {m}" for m in marked) await message.channel.send(f"Logged as taken:\n{lines}") + # Ask about doses from 1–6 hours ago that weren't logged + if ask_doses: + if "pending_confirmations" not in session: + session["pending_confirmations"] = {} + session["pending_confirmations"]["med_past_due_check"] = { + "action": "take_all_past_confirm", + "interaction_type": "medication", + "needs_confirmation": False, + "doses": [[mid, name, t] for mid, name, t in ask_doses], + } + dose_lines = "\n".join(f"- **{name}** at {t}" for _, name, t in ask_doses) + await message.channel.send( + f"❓ Also found unlogged doses from the past 6 hours:\n{dose_lines}\n\n" + f"Did you take these too? Reply **yes** or **no**." + ) + elif not marked: + await message.channel.send("✅ No past-due medications to log right now.") + + elif action == "take_all_past_confirm": + # Handles yes-confirmation for past-due doses surfaced by take_all + doses = parsed.get("doses", []) + marked = [] + for dose_info in doses: + if isinstance(dose_info, (list, tuple)) and len(dose_info) >= 3: + med_id_local, med_name, t = dose_info[0], dose_info[1], dose_info[2] + api_request( + "post", f"/api/medications/{med_id_local}/take", token, + {"scheduled_time": t} + ) + marked.append(f"**{med_name}** at {t}") + if marked: + lines = "\n".join(f"✅ {m}" for m in marked) + await message.channel.send(f"Logged as taken:\n{lines}") + else: + await message.channel.send("No doses to log.") + elif action == "skip": med_id = parsed.get("medication_id") name = parsed.get("name")