File size: 5,305 Bytes
20c8fc2
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
import dotenv from "dotenv";
import fs from "fs";
import path from "path";

dotenv.config();

const API_BASE_URL = "https://finalchatdoc.onrender.com";

import { spawn } from "child_process";
import { fileURLToPath } from "url";

const __filename = fileURLToPath(import.meta.url);
const __dirname = path.dirname(__filename);

const customAPI = {
    chat: async (message, userId) => {
        try {
            const effectiveUserId = userId || "demo_user_123";
            console.log(`Sending Chat request to ${API_BASE_URL}/chat for user: ${effectiveUserId}`);
            const controller = new AbortController();
            const timeoutId = setTimeout(() => controller.abort(), 60000); // 60 second timeout

            const response = await fetch(`${API_BASE_URL}/chat`, {
                method: "POST",
                headers: {
                    "Content-Type": "application/json",
                },
                body: JSON.stringify({
                    message: message,
                    user_id: effectiveUserId,
                    language: "en"
                }),
                signal: controller.signal
            });
            clearTimeout(timeoutId);

            if (!response.ok) {
                const errorText = await response.text();
                throw new Error(`Chat API error: ${response.status} ${response.statusText} - ${errorText}`);
            }

            const data = await response.json();

            // The API returns the message in the 'reply' field
            const botResponse = data.reply || data.response || data.message || "I didn't get a reply.";

            return botResponse;
        } catch (error) {
            console.error("Chat API Error:", error);
            return "I'm having trouble connecting to the doctor right now. Please try again later.";
        }
    },

    tts: async (text) => {
        return new Promise((resolve, reject) => {
            try {
                console.log(`Generating local TTS for text: "${text.substring(0, 20)}..."`);

                const ttsScript = path.join(__dirname, "..", "utils", "tts.py");
                const tempFile = path.join(__dirname, "..", "tmp", `tts_${Date.now()}_${Math.random().toString(36).substring(7)}.mp3`);

                // Ensure tmp dir exists
                const tmpDir = path.dirname(tempFile);
                if (!fs.existsSync(tmpDir)) {
                    fs.mkdirSync(tmpDir, { recursive: true });
                }

                const pythonProcess = spawn("python", [ttsScript, "-", tempFile]);

                pythonProcess.stdin.write(text);
                pythonProcess.stdin.end();

                let errorOutput = "";

                pythonProcess.stderr.on("data", (data) => {
                    errorOutput += data.toString();
                });

                pythonProcess.on("close", async (code) => {
                    if (code !== 0) {
                        console.error(`TTS Process Error: ${errorOutput}`);
                        // Fallback to silent buffer on error to prevent crash
                        resolve(Buffer.alloc(1024));
                        return;
                    }

                    try {
                        const audioBuffer = await fs.promises.readFile(tempFile);
                        console.log(`TTS generated audio size: ${audioBuffer.length} bytes`);

                        if (audioBuffer.length < 1000) {
                            console.warn("⚠️ Warning: Generated audio is suspiciously small.");
                        }

                        // Clean up
                        fs.unlink(tempFile, (err) => { if (err) console.error("Error deleting temp file:", err); });
                        resolve(audioBuffer);
                    } catch (err) {
                        console.error("Error reading TTS file:", err);
                        resolve(Buffer.alloc(1024));
                    }
                });
            } catch (error) {
                console.error("TTS Wrapper Error:", error);
                resolve(Buffer.alloc(1024));
            }
        });
    },

    stt: async (audioBuffer) => {
        try {
            console.log(`Sending STT request to ${API_BASE_URL}/stt`);

            // Create a Blob from the buffer
            const blob = new Blob([audioBuffer], { type: 'audio/wav' });

            const formData = new FormData();
            formData.append("audio", blob, "input.wav");

            const controller = new AbortController();
            const timeoutId = setTimeout(() => controller.abort(), 60000);

            const response = await fetch(`${API_BASE_URL}/stt`, {
                method: "POST",
                body: formData,
                signal: controller.signal
            });
            clearTimeout(timeoutId);

            if (!response.ok) {
                const errorText = await response.text();
                throw new Error(`STT API error: ${response.status} ${response.statusText} - ${errorText}`);
            }

            const data = await response.json();
            return data.text;
        } catch (error) {
            console.error("STT API Error:", error);
            return "I couldn't hear you.";
        }
    },
};

export default customAPI;