-
Notifications
You must be signed in to change notification settings - Fork 1
/
main.ts
103 lines (93 loc) · 2.91 KB
/
main.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
import {
Bot,
InlineKeyboard,
type InlineQueryResultArticle,
webhookCallback,
} from "./deps.ts";
import { parse } from "./parse.ts";
import {
render,
renderInputMessageContent,
renderNext,
renderSingle,
} from "./render.ts";
import { search, searchOne } from "./search.ts";
const token = Deno.env.get("BOT_TOKEN");
const me = Deno.env.get("BOT_INFO");
if (token === undefined) throw new Error("Missing BOT_TOKEN");
const searchKeyboard = new InlineKeyboard()
.switchInlineCurrent("Search here").row()
.switchInline("Share article");
const bot = new Bot(token, {
botInfo: me === undefined ? undefined : JSON.parse(me),
});
bot.command(
"help",
(ctx) =>
ctx.reply(
`Welcome to the grammY documentation bot!
This bot uses the search that you find at the top of \
grammy.dev. Type @${ctx.me.username} followed by a \
search query to quickly share links to grammY docs.
If you want to send a message with a link to the docs \
embedded in it, you can surround your +search query+ \
by '+' characters. This will insert the title of the \
page as a text link to the respective URL.
– Use +search query|this link+ to send a custom link text.
– Use +search query!+ with a '!' suffix to use the \
search query as the link text.
– Use +search query/+ with a '/' suffix to share the \
URL itself instead of the page title.
Join @grammyjs!`,
{ reply_markup: searchKeyboard },
),
);
bot.drop((ctx) => ctx.msg?.via_bot?.id === ctx.me.id)
.on("message", async (ctx) => {
await ctx.reply("I can search for grammY documentation inline. /help", {
reply_markup: searchKeyboard,
});
});
bot.on("inline_query", async (ctx) => {
const { query, offset } = ctx.inlineQuery;
const { currentQuery, texts, completedQueries } = parse(query);
const links = await Promise.all(
completedQueries.map(async (query) => ({
query,
hit: await searchOne(query.query),
})),
);
let nextOffset = offset;
let results: InlineQueryResultArticle[];
if (currentQuery === undefined) {
// only completed queries, render them
results = [render(texts, links)];
} else {
// pending current query
const off = parseInt(offset, 10);
const hits = isNaN(off)
? await search(currentQuery.query)
: await search(currentQuery.query, { offset: off });
nextOffset += hits.length;
if (texts.length === 0) {
// no rendering
results = await Promise.all(hits.map(renderSingle));
} else {
// render and continue to search
const content = renderInputMessageContent(texts, links);
results = hits.map((hit) =>
renderNext(content, { query: currentQuery, hit })
);
}
}
await ctx.answerInlineQuery(results, {
next_offset: nextOffset,
cache_time: 24 * 60 * 60, // 24 hours (algolia re-indexing)
});
});
if (Deno.env.get("DEBUG")) {
bot.catch(console.error);
bot.start();
} else {
Deno.serve(webhookCallback(bot, "std/http"));
}