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
|
import { db } from "@/server/db";
import { storedContent, users } from "@repo/db/schema";
import { cipher } from "@/server/encrypt";
import { eq } from "drizzle-orm";
import { Bot, webhookCallback } from "grammy";
import { User } from "grammy/types";
export const runtime = "edge";
if (!process.env.TELEGRAM_BOT_TOKEN) {
throw new Error("TELEGRAM_BOT_TOKEN is not defined");
}
console.log("Telegram bot activated");
const token = process.env.TELEGRAM_BOT_TOKEN;
const bot = new Bot(token);
function escapeMarkdown(text: string): string {
return text.replace(/[_*[\]()~`>#+=|{}.!-]/g, "\\$&");
}
bot.command("start", async (ctx) => {
const user: User = (await ctx.getAuthor()).user;
const cipherd = cipher(user.id.toString());
await ctx.reply(
escapeMarkdown(
`Welcome to Supermemory bot. I am here to help you remember things better. [Click here to create and link your account](https://supermemory.ai/signin?telegramUser=${cipherd})`,
),
{
parse_mode: "MarkdownV2",
},
);
});
bot.on("message", async (ctx) => {
const user: User = (await ctx.getAuthor()).user;
const cipherd = cipher(user.id.toString());
const dbUser = await db.query.users
.findFirst({
where: eq(users.telegramId, user.id.toString()),
})
.execute();
if (!dbUser) {
await ctx.reply(
escapeMarkdown(
`Welcome to Supermemory bot. I am here to help you remember things better. [Click here to create and link your account](https://supermemory.ai/signin?telegramUser=${cipherd})`,
),
{
parse_mode: "MarkdownV2",
},
);
return;
}
const message = await ctx.reply("I'm thinking...");
const response = await fetch(
`${process.env.BACKEND_BASE_URL}/api/autoChatOrAdd?query=${encodeURIComponent(ctx.message.text!)}&user=${dbUser.id}`,
{
method: "POST",
headers: {
Authorization: "Bearer " + process.env.BACKEND_SECURITY_KEY,
"Content-Type": "application/json",
},
body: JSON.stringify({
// TODO: we can use the conversations API to get the last 5 messages
// get chatHistory from this conversation.
// Basically the last 5 messages between the user and the assistant.
// In ths form of [{role: 'user' | 'assistant', content: string}]
// https://grammy.dev/plugins/conversations
chatHistory: [],
}),
},
);
if (response.status !== 200) {
console.log("Failed to get response from backend");
console.log(response.status);
await ctx.reply(
escapeMarkdown(
"Sorry, I am not able to process your request at the moment." +
(await response.text()),
),
);
return;
}
const data = (await response.json()) as {
status: string;
response: string;
contentAdded: {
type: string;
content: string;
url: string;
};
};
// TODO: we might want to enrich this data with more information
if (data.contentAdded) {
await db
.insert(storedContent)
.values({
content: data.contentAdded.content,
title: `${data.contentAdded.content.slice(0, 30)}... (Added from chatbot)`,
description: "",
url: data.contentAdded.url,
baseUrl: data.contentAdded.url,
image: "",
savedAt: new Date(),
userId: dbUser.id,
type: data.contentAdded.type,
})
.returning({ id: storedContent.id });
}
await ctx.api.editMessageText(
ctx.chat.id,
message.message_id,
escapeMarkdown(data.response),
{
parse_mode: "MarkdownV2",
},
);
});
export const POST = webhookCallback(bot, "std/http");
export const GET = async () => {
return new Response("OK", { status: 200 });
};
|