Skip to content

Commit a71e1e1

Browse files
Sonra0claude
andcommitted
feat: send detailed assessment report via Telegram
After assessment summary and vocal analysis are generated, send a full report to caregivers on Telegram with score, question breakdown, and wellness analysis instead of the previous brief one-liner notification. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
1 parent 18eca26 commit a71e1e1

2 files changed

Lines changed: 67 additions & 19 deletions

File tree

src/app/api/webhooks/assessment/next/route.ts

Lines changed: 57 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import {
77
analyzeVocalBiomarkers,
88
} from "@/lib/gemini";
99
import { textToSpeech } from "@/lib/elevenlabs";
10+
import { sendTelegramNotification } from "@/lib/telegram-api";
1011
import { writeFile, mkdir, access } from "fs/promises";
1112
import path from "path";
1213

@@ -99,7 +100,9 @@ function processAnswerInBackground(
99100
function generateSummaryInBackground(
100101
sessionId: string,
101102
elderlyName: string,
102-
language: string
103+
language: string,
104+
elderlyProfileId: string,
105+
overallScore: number
103106
) {
104107
(async () => {
105108
try {
@@ -150,14 +153,65 @@ function generateSummaryInBackground(
150153

151154
const [report, vocalAnalysis] = await Promise.all([summaryPromise, vocalPromise]);
152155

156+
const severity = report.severity;
157+
153158
await prisma.assessmentSession.update({
154159
where: { id: sessionId },
155160
data: {
156161
summary: report.summary,
157-
severity: report.severity,
162+
severity,
158163
...(vocalAnalysis ? { vocalAnalysis: vocalAnalysis as object } : {}),
159164
},
160165
});
166+
167+
// Send detailed assessment report via Telegram
168+
try {
169+
const scorePct = Math.round(overallScore * 100);
170+
const severityIcon = severity === "GREEN" ? "\u2705" : severity === "YELLOW" ? "\u26A0\uFE0F" : "\u274C";
171+
const totalCorrect = allAnswers.filter((a: { result: string | null }) => a.result === "CORRECT").length;
172+
const totalWrong = allAnswers.filter((a: { result: string | null }) => a.result === "WRONG").length;
173+
const totalUnclear = allAnswers.filter((a: { result: string | null }) => a.result !== "CORRECT" && a.result !== "WRONG").length;
174+
175+
let msg = `${severityIcon} *${elderlyName}'s Assessment Report*\n`;
176+
msg += `${todayStr}\n\n`;
177+
msg += `*Score:* ${scorePct}% (${totalCorrect}/${allAnswers.length} correct)\n`;
178+
msg += `*Status:* ${severity}\n\n`;
179+
180+
if (report.summary) {
181+
msg += `*Summary:* ${report.summary}\n\n`;
182+
}
183+
184+
// Question-by-question breakdown
185+
msg += `*Questions:*\n`;
186+
for (let i = 0; i < allAnswers.length; i++) {
187+
const a = allAnswers[i];
188+
const icon = a.result === "CORRECT" ? "\u2705" : a.result === "WRONG" ? "\u274C" : "\u2753";
189+
msg += `${icon} ${a.questionText}\n`;
190+
msg += ` Answer: ${a.elderAnswer || "No answer"}\n`;
191+
if (a.result !== "CORRECT") {
192+
msg += ` Correct: ${a.correctAnswer}\n`;
193+
}
194+
}
195+
196+
// Vocal analysis
197+
if (vocalAnalysis) {
198+
const va = vocalAnalysis as {
199+
parkinsons: { currentProbability: number; futureRisk: number; details: string };
200+
depression: { currentState: number; futurePropensity: number; details: string };
201+
mood: { todayMood: string; wellnessScore: number; details: string };
202+
};
203+
msg += `\n*Vocal & Wellness Analysis:*\n`;
204+
msg += `Mood: ${va.mood.todayMood} | Wellness: ${va.mood.wellnessScore}/100\n`;
205+
msg += `${va.mood.details}\n\n`;
206+
msg += `Parkinson's Risk: ${va.parkinsons.currentProbability}% (future: ${va.parkinsons.futureRisk}%)\n`;
207+
msg += `Depression: ${va.depression.currentState}% (future: ${va.depression.futurePropensity}%)\n`;
208+
msg += `\n_This analysis is for caregiver awareness only._`;
209+
}
210+
211+
await sendTelegramNotification(elderlyProfileId, msg);
212+
} catch (telegramErr) {
213+
console.error("Telegram report notification failed:", telegramErr);
214+
}
161215
} catch (err) {
162216
console.error("Background summary failed:", err);
163217
}
@@ -258,7 +312,7 @@ export async function POST(req: NextRequest) {
258312
},
259313
}).catch((err: unknown) => console.error("Session completion failed:", err));
260314

261-
generateSummaryInBackground(sessionId, profile.name, profile.language);
315+
generateSummaryInBackground(sessionId, profile.name, profile.language, profile.id, score);
262316

263317
// Generate TTS summary using same ElevenLabs voice
264318
const voiceId = profile.voiceId || undefined;

src/app/api/webhooks/assessment/status/route.ts

Lines changed: 10 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -23,28 +23,22 @@ export async function POST(req: NextRequest) {
2323
data: { status: updatedStatus },
2424
});
2525

26-
// Send Telegram notification
27-
try {
28-
const profile = await prisma.elderlyProfile.findUnique({
29-
where: { id: session.elderlyProfileId },
30-
});
31-
if (profile) {
32-
if (updatedStatus === "COMPLETED" && session.overallScore !== null) {
33-
const severity = session.severity || "GREEN";
34-
const summary = session.summary || "";
35-
await sendTelegramNotification(
36-
session.elderlyProfileId,
37-
`${profile.name}'s assessment: score ${Math.round((session.overallScore ?? 0) * 100)}% (${severity}).\n${summary}`
38-
);
39-
} else if (updatedStatus === "FAILED") {
26+
// Send Telegram notification only for failures
27+
// (Detailed completion reports are sent from the summary generator in the next webhook)
28+
if (updatedStatus === "FAILED") {
29+
try {
30+
const profile = await prisma.elderlyProfile.findUnique({
31+
where: { id: session.elderlyProfileId },
32+
});
33+
if (profile) {
4034
await sendTelegramNotification(
4135
session.elderlyProfileId,
4236
`${profile.name}'s assessment call failed.`
4337
);
4438
}
39+
} catch (err) {
40+
console.error("Telegram notification error:", err);
4541
}
46-
} catch (err) {
47-
console.error("Telegram notification error:", err);
4842
}
4943
}
5044
}

0 commit comments

Comments
 (0)