Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add talk to filter query docs #1074

Merged
merged 18 commits into from
Jun 29, 2024
Merged
24 changes: 20 additions & 4 deletions site/docs/guide/filter-queries.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,12 +24,12 @@ bot.on("message", async (ctx) => {
const text: string | undefined = ctx.msg.text;
});
bot.on("message:text", async (ctx) => {
// Text is always defined because this handler is called when a text message is received.
// Text is always present because this handler is called when a text message is received.
const text: string = ctx.msg.text;
});
```

In a sense, grammY implements the filter queries both at runtime, and on the type level.
In a sense, grammY implements the filter queries both [at runtime](#performance), and [on the type level](#type-safety).

## Example Queries

Expand Down Expand Up @@ -133,7 +133,7 @@ bot.on("message:new_chat_members:is_bot");
bot.on("message:left_chat_member:me");
```

Note that while this syntactic sugar is useful to work with service messages, is should not be used to detect if someone actually joins or leaves a chat.
Note that while this syntactic sugar is useful to work with service messages, it should not be used to detect if someone actually joins or leaves a chat.
Services messages are messages that inform the users in the chat, and some of them will not be visible in all cases.
For example, in large groups, there will not be any service messages about users that join or leave the chat.
Hence, your bot may not notice this.
Expand Down Expand Up @@ -347,8 +347,24 @@ In this case, you will be provided with helpful error messages.
The validation of the filter queries happens only once, when the bot is initialized and `bot.on()` is called.

On start-up, grammY derives a predicate function from the filter query by splitting it into its query parts.
Every part will be mapped to a function that performs a single `in` check, or two checks if the part is omitted and two values need to be checked.
Every part will be mapped to a function that performs a single truthiness check for an object property, or two checks if the part is omitted and two values need to be checked.
quadratz marked this conversation as resolved.
Show resolved Hide resolved
These functions are then combined to form a predicate that only has to check for as many values as are relevant for the query, without iterating over the object keys of `Update`.

This system uses less operations than some competing libraries, which need to perform containment checks in arrays when routing updates.
grammY's filter query system is faster despite being much more powerful.

### Type Safety

As mentioned above, filter queries will automatically narrow down certain properties on the context object.
The predicate derived from one or more filter queries is a TypeScript type predicate that performs this narrowing.
In general, you can trust that type inference works correctly.
If a property is inferred to be present, you can safely rely on it.
If a property is inferred to be potentially absent, then this means that there are certain cases of it missing.
It is not a good idea to perform type casts with the `!` operator.

> It may not be obvious to you what those cases are.
> Don't hesitate to ask in the [group chat](https://t.me/grammyjs) if you cannot figure it out.

Computing these types is complicated.
A lot of knowledge about the Bot API went into this part of grammY.
If you want to understand more about the basic approaches to how these types are computed, there is a [talk on YouTube](https://youtu.be/ZvT_xexjnMk) that you can watch.
19 changes: 17 additions & 2 deletions site/docs/id/guide/filter-queries.md
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ bot.on("message:text", async (ctx) => {
});
```

Filter query grammY diimplementasikan baik di _runtime_ maupun di _type level_.
Filter query grammY diimplementasikan baik di [_runtime_](#performa) maupun di [_type level_](#type-safety).
This conversation was marked as resolved.
Show resolved Hide resolved

## Contoh Query

Expand Down Expand Up @@ -350,8 +350,23 @@ Selain itu, kamu juga akan diberikan pesan error yang lebih bermanfaat.
Validasi filter query hanya dilakukan sekali, ketika bot diinisialisasi dan `bot.on()` dipanggil.

Ketika dimulai, grammY menurunkan _function predicate_ dari filter query dengan cara memecahnya menjadi beberapa komponen query.
Setiap komponen akan di-map ke sebuah function yang mengerjakan satu pemeriksaan `in`, atau dua pemeriksaan jika komponen tersebut diabaikan dan dua value perlu dilakukan pemeriksaan.
Setiap komponen akan di-map ke sebuah function yang mengerjakan satu pemeriksaan truthiness untuk properti objek, atau dua pemeriksaan jika komponen tersebut diabaikan dan dua value perlu dilakukan pemeriksaan.
This conversation was marked as resolved.
Show resolved Hide resolved
Function-function ini kemudian disatukan untuk membentuk sebuah predicate yang akan memeriksa sebanyak mungkin value yang relevan untuk query, tanpa melakukan proses perulangan terhadap key object `Update`.

Sistem ini menggunakan lebih sedikit operasi dibandingkan dengan beberapa library lainnya, dimana dibutuhkan beberapa pengecekan array ketika melakukan routing update.
Ini membuat sistem filter query grammY selain lebih unggul juga jauh lebih cepat.

### Type Safety

Sebagaimana yang disebutkan diatas, filter queries secara otomatis akan mempersempit properti tertentu pada objek context dan menghasilkan satu atau lebih predicate dalam fungsi predicate type di TypeScript.
This conversation was marked as resolved.
Show resolved Hide resolved
Secara umum, kamu dapat mempercayai type inference itu ia selalu bekerja dengan benar.
Jika suatu properti type infer-nya tersedia, kamu dapat dapat menggunakan type tersebut dengan aman.
Jika suatu properti type infer-nya hilang, berarti ada kasus tertentu yang membuat type-nya hilang.
Bukan ide yang baik untuk melakukan casting type dengan operator `!`.

> Mungkin ini kurang jelas tentang apa maksud kasus tersebut.
> Jangan ragu untuk bertanya di [obrolan grup](https://t.me/grammyjs) jika kamu tidak memahaminya.

Membuat type ini merumitkan.
Banyak sekali pengetahuan tentang API Bot yang masuk pada bagian grammY ini.
This conversation was marked as resolved.
Show resolved Hide resolved
Apabila kamu ingin lebih memahami tentang pendekatan dasar bagaimana type ini dibuat, berikut ada [pembahasannya di Youtube](https://youtu.be/ZvT_xexjnMk) yang mungkin bisa kamu tonton.
This conversation was marked as resolved.
Show resolved Hide resolved
This conversation was marked as resolved.
Show resolved Hide resolved
25 changes: 23 additions & 2 deletions site/docs/uk/guide/filter-queries.md
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ bot.on("message:text", async (ctx) => {
});
```

Отже, grammY реалізує запити фільтрування як під час виконання, так і на рівні типів.
Отже, grammY реалізує запити фільтрування як [під час виконання](#продуктивність), так і [на рівні типів](#безпека-типів).

## Приклади запитів

Expand Down Expand Up @@ -347,8 +347,29 @@ bot.on(":text", handler);
Перевірка запитів фільтрування відбувається лише один раз, коли бот ініціалізується та викликається `bot.on()`.

Під час запуску grammY створює предикатну функцію із запиту фільтрування, розділяючи його на частини.
Кожна частина буде зіставлена з функцією, яка виконує одну перевірку `in` або дві перевірки, якщо частина запиту пропущена і потрібно перевірити два значення.
Кожна частина буде зіставлена з функцією, яка виконує одну перевірку істинності для властивості об'єкта або дві перевірки, якщо частина запиту пропущена і потрібно перевірити два значення.
Потім ці функції обʼєднуються у предикат, який перевіряє лише ті значення, що мають відношення до запиту, без перебору ключів обʼєкта `Update`.

Ця система використовує менше операцій, ніж деякі конкуруючі бібліотеки, яким потрібно виконувати перевірку вмісту у масивах для маршрутизації оновлень.
Система запитів фільтрування grammY працює швидше, попри те, що набагато потужніша.

### Безпека типів

Як згадувалося вище, запити фільтрування автоматично звужують певні властивості об'єкта контексту.
Предикат, отриманий з одного або декількох запитів фільтрування, є предикатом типу TypeScript, який виконує це звуження.
Загалом, ви можете довіряти тому, що виведення типів працює коректно.
Якщо властивість виводиться як присутня, ви можете безпечно покладатися на неї.
Якщо властивість виводиться як потенційно відсутня, то це означає, що існують певні випадки, коли вона відсутня.
Не варто виконувати приведення типів за допомогою оператора `!`.

> Для вас може бути неочевидним, що це за випадки.
> Не соромтеся запитувати в [груповому чаті](https://t.me/grammyjs), якщо не можете розібратися.

Обчислення цих типів є складним.
При розробці запитів фільтрування було використано багато знань про Bot API.
Якщо ви хочете дізнатися більше про основні підходи до обчислення цих типів, ви можете подивитися [виступ на YouTube](https://youtu.be/ZvT_xexjnMk).
niusia-ua marked this conversation as resolved.
Show resolved Hide resolved

::: tip
Зауважте, що ця доповідь викладається англійською мовою.
Якщо ви погано розумієте розмовну англійську, скористайтеся англійськими або автоперекладеними субтитрами.
:::
28 changes: 24 additions & 4 deletions site/docs/zh/guide/filter-queries.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,12 +24,12 @@ bot.on("message", async (ctx) => {
const text: string | undefined = ctx.msg.text;
});
bot.on("message:text", async (ctx) => {
// 文本总是被定义的,因为当收到一个文本消息时,这个处理程序被调用
// 文本始终存在,因为收到文本消息时会调用此处理程序
const text: string = ctx.msg.text;
});
```

从某种意义上说,grammY 在运行时和类型层面上都实现了筛选
从某种意义上说,grammY [在运行时](#性能) 和 [类型层面上](#类型安全) 都实现了筛选

## 查询示例

Expand Down Expand Up @@ -222,6 +222,7 @@ bot.on("chat_member");

```ts
bot.on(":forward_origin").command("help"); // 转发的 /help 命令

// 只在私人聊天中处理命令。
const pm = bot.chatType("private");
pm.command("start");
Expand All @@ -243,6 +244,7 @@ pm.command("help");
```ts
// 从 `ctx.senderChat` 发送的频道帖子
bot.on("channel_post");

// 从 `ctx.senderChat`频道自动转发
bot.on("message:is_automatic_forward");
// 从 `ctx.from` 发送的常规信息
Expand Down Expand Up @@ -302,6 +304,7 @@ bot.drop(matchFilter(":text"));
function handler(ctx: Filter<Context, ":text">) {
// 处理缩小的上下文对象
}

bot.on(":text", handler);
```

Expand Down Expand Up @@ -344,7 +347,24 @@ bot.on(":text", handler);
filter 查询的验证只发生一次,当 bot 被初始化和 `bot.on()` 被调用时。

在启动时,grammY 从 filter 查询中导出一个函数语句,将其拆分为查询部分。
每个部分都将被映射到一个函数,该函数执行一个单一的 `in` 检查,或者如果该部分被省略,需要检查两个值,则执行两个检查
每个部分都将被映射到一个函数,该函数对对象属性执行一次真值检查,或者如果该部分被省略并且需要检查两个值,则执行两次检查
然后这些函数被组合成一个语句,这个语句只需要检查与查询相关的值,而不需要对 `Update` 的对象键进行迭代。

这个系统使用的操作比一些同类库要少,这些库在路由更新时需要对数组进行包含性检查。如你所见,grammY 的 filter 查询系统虽说强大得多,但丝毫不影响效率,反而更快。
这个系统使用的操作比一些同类库要少,这些库在路由更新时需要对数组进行包含性检查。
如你所见,grammY 的 filter 查询系统虽说强大得多,但丝毫不影响效率,反而更快。

### 类型安全

如上所述,filter 查询将自动缩小上下文对象上的某些属性的范围。
从一个或多个 filter 查询派生的谓词是执行此范围缩小的 TypeScript 类型谓词。
一般来说,你可以相信类型推断是正确的。
如果推断存在某个属性,你可以放心地信赖它。
如果推断某个属性可能不存在,则意味着在某些情况下它就是缺失的。
使用 `!` 运算符执行类型转换不是一个好主意。

> 这些情况对你来说可能不是显而易见的。
> 如果你无法弄清楚,请随时在 [群聊](https://t.me/grammyjs) 中提问。

计算这些类型是很复杂的。
grammY 的这一部分涉及到很多关于 Bot API 的知识。
如果你想了解更多有关如何计算这些类型的基本方法,你可以观看 [YouTube 上的演讲](https://youtu.be/ZvT_xexjnMk)(英文,可开启自动翻译的中文字幕)。
Loading