-
Notifications
You must be signed in to change notification settings - Fork 0
/
chatbot.ts
129 lines (109 loc) · 3.41 KB
/
chatbot.ts
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
import TelegramBot = require('node-telegram-bot-api')
import dotenv = require('dotenv')
import needle = require('needle')
import ffmpeg = require('fluent-ffmpeg')
import https = require('https')
import fs = require('fs')
dotenv.config()
const telegramToken = process.env.TELEGRAM_TOKEN
const openAIToken = process.env.OPENAI_API_KEY
const openAIChatUrl = 'https://api.openai.com/v1/chat/completions'
const openAIWhisperUrl = 'https://api.openai.com/v1/audio/transcriptions'
const removeFile = (filePath: string) =>
fs.unlink(filePath, (err: any) => {
if (err) {
console.error(err)
return
}
})
const initTelegramBot = (options: TelegramBot.ConstructorOptions = {}) => {
if (!telegramToken) return
const bot = new TelegramBot(telegramToken, { polling: false, ...options })
return bot
}
const bot = initTelegramBot({ polling: true })
function convertToMp3(wavFilename: string): Promise<string> {
if (!fs.existsSync(wavFilename)) {
throw new Error(`File ${wavFilename} does not exist`)
}
return new Promise((resolve, reject) => {
const outputFile = wavFilename.replace('.oga', '.mp3')
ffmpeg({
source: wavFilename,
})
.on('error', (err: any) => {
reject(err)
})
.on('end', () => {
resolve(outputFile)
})
.save(outputFile)
})
}
const transcribeAudio = (audioPath: string) => {
return new Promise<null | string>((resolve, reject) => {
needle.post(
openAIWhisperUrl,
{ model: 'whisper-1', file: { file: audioPath, content_type: 'audio/mpeg' } },
{ headers: { Authorization: `Bearer ${openAIToken}` }, multipart: true },
function (error, response) {
if (error) {
reject(error)
}
const transcription = response?.body?.text
resolve(transcription)
}
)
})
}
const summarizeText = (textToSummarize: string) => {
return new Promise<string | null>((resolve, reject) => {
needle.post(
openAIChatUrl,
{
model: 'gpt-3.5-turbo',
messages: [
{
role: 'user',
content: `Summarize the following content in bullet points with an emoji in front of each point: ${textToSummarize}`,
},
],
},
{ headers: { Authorization: `Bearer ${openAIToken}` }, json: true },
function (error, response) {
if (error) {
reject(error)
}
const telegramResponse = response.body.choices[0].message.content
resolve(telegramResponse)
}
)
})
}
bot.on('voice', async msg => {
const file_id = msg.voice.file_id
const chatId = msg.chat.id
try {
const file = await bot.getFile(file_id)
const filePath = file.file_path
const voiceUrl = `https://api.telegram.org/file/bot${telegramToken}/${filePath}`
const tempFile = fs.createWriteStream(`${__dirname}/${filePath}`)
tempFile.on('open', function () {
https.get(voiceUrl, function (response: any) {
if (!tempFile) return
response.pipe(tempFile)
})
})
tempFile.on('finish', async () => {
const ogaFilePath = `${__dirname}/${filePath}`
const mp3FilePath = await convertToMp3(ogaFilePath)
const transcription = await transcribeAudio(mp3FilePath)
const summary = await summarizeText(transcription)
bot.sendMessage(chatId, summary)
removeFile(mp3FilePath)
removeFile(ogaFilePath)
})
} catch (err) {
console.log(err)
}
})