
機能をテストしますか?このリンクを使用してボットに書き込み、彼はあなたに答えます。
そして、それがどのように機能し、16歳の学生がどのようにそれを書くことができたかに興味がある人のために、私はこの記事ですべてを詳細に喜んでお話しします。
バックグラウンド
それはすべて、音声メッセージを復号化するノードjs上のVK用の他のボットから始まりました(そのようなボットは1ダースほどなので、いくつかの特徴的な機能もありますが、その開発についての記事を書かないことにしました)。私がそれを立ち上げた後、私の父は私が電報を介して私たちの家族のチャットのために別のボットを開発することを提案しました。このボットの本質は単純でした。人のテキストメッセージから日付と時刻を抽出し、電報の遅延メッセージを使用して、家族のチャットでリマインダーを作成することです。
しかし、すぐに私はがっかりしました。ボットは遅延メッセージを作成できないことが判明したため、リマインダーを保存および実行するための独自のシステムを作成することにしました。
開発
一般情報
このボットはで書かれているノードのJSとに住んでHerokuの。
正確な分単位のテキストリマインダーを保存できます。
彼はグループ会話でも働くことができます。
現時点では、ボットはロシア語でのみ日付と時刻を認識します。
SmartSchedulerは、私のgithubで利用できるオープンソースプロジェクトです。
メッセージから日付と時刻を抽出する
私は最も難しいタスクから始めることにしました。テキストリマインダーを日付とリマインダー自体に分割することです。これを行うには、「12:00」から「次の日曜日の25時から8時まで」まで、人が日付を書くためのすべての可能な基準を考慮に入れる必要がありました。
大規模なデータベース(constValues.js)が作成され、人がスピーチで使用する定数式とそのプロパティが格納されています。次に、時間の各スペルを認識する関数が作成されました。
たとえば、関数を使用して、「through X%time_type%」の形式で日付を認識し
FindAdditiveLiterals
、曜日を検索しますFindDayOfWeek
。
毎回指定オプションには独自の優先順位がありました。
その結果、パーサーのアルゴリズムは次のようになります。
- 元の文字列は単語に分割されます。時間の検索が実行される単語は40を超えることはできません。
- 単語の配列は、単語から数値への変換関数を介して渡されます。
- メッセージにはすべての時間表示があり、表示に使用されている単語もマークされています(たとえば、「アラームクロック8時」の表示では、「8」と「時間」という単語がマークされています)。
- テキストメッセージで時間の特性(月など)が見つからなかった場合は、この特性の現在の値が取得されます。
- 最終的な判断では、優先度が最も高い時間表示と、同じソースワードを持つ隣接する表示が選択されます(たとえば、「10:30」という単語では、時間と分が同時に表示されます)。
- , , , .
- , .
- ,
{ string: answer, string: text, date: date }
{ string: answer, string: text }
(answer – , text – , date – ).
次の質問は、すべてのリマインダーをどこに保存するか、およびそれらの実装を追跡する方法でした。
最初はノードスケジュールライブラリを使用したかったのですが、すべてのリマインダーでRAMを詰まらせたくなかったため、このアイデアをあきらめました。
代わりに、SQLデータベースがどのように機能するかを調べて、独自のデータベースを作成することにしました。
インターネットで多くの記事を読んだ後、アプリケーションにデータベースを埋め込むことができるので、herokuプラットフォームでpostgresqlデータベースを作成しました。これは非常に便利です。
データベースを操作するために、小さなスクリプト(db.js)を作成しました。このスクリプトでは、データベースの初期化、リマインダーのリストの取得など、必要なすべての機能を実装しました。
私のデータベースには2つのテーブルがあります。1つはリマインダーを保存するためのもので、もう1つはユーザーのタイムゾーンを保存するためのものです(これについては後で詳しく説明します)。
その後、解析したリマインダーをテキストメッセージからデータベースに保存することを実装しました。1分に1回動作するタイマーは、リマインダーの時間をチェックします。リマインダーの時間になると、データベースから削除され、リマインダーのテキストを含むメッセージが、リマインダーを作成したユーザーに送信されます。
また、/ listコマンドを使用してすべてのリマインダーの表示を追加しました。

(各リマインダーの横にクリック可能な/ Nコマンドがあり、クリックすると削除されます)
タイムゾーン設定
この記事を書いてHabrに載せる前に、モスクワのタイムゾーンは環境変数にハードコードされていました。これは私たちの家族内で使用するには十分でしたが、SmartSchedulerボットで誰もができるすべての喜びと便利さを利用するために、個別のタイムゾーン設定を追加することにしました。
構成を完了するには、/ tzコマンドを記述する必要があります。これは、ボットがユーザーにタイムゾーンをまだ指定していない場合に警告します:(

タイムゾーンが指定されていないため、応答は現地時間ではなくグリニッジ時間を使用します)
コマンド/ tzを入力するときタイムゾーンを決定するプロセスが開始され、キーボードに3つのボタンが表示されます。

- ユーザーの場所を使用します。
- 手動入力。
- キャンセル。
最初のボタンは、タイムゾーンの計算に基づいてユーザーに場所を尋ねます。
使用例

2番目のボタンを使用すると、±HH:MMの形式でタイムゾーンを手動で入力できます。
ここで、±-プラスまたはマイナス、HH-時間、MM-分です。
使用例

3番目のボタンは、定義プロセスをキャンセルします。
ユーザーが自分のタイムゾーンを指定すると、ボットはリマインダー時間を正しく表示して保存します。
最終的な改善
主な機能が終了したら、主な機能を備えたメインキーボードを追加し、/ startコマンドと/ helpコマンド、およびその他の小さなことに対する回答を修正しました。
また、すべてのユーザーのデフォルトのタイムゾーンをモスクワに置き換えることにしました。
結果
SmartSchedulerボットの主な利点は、もちろん、日付の解析です。これにより、最も予測不可能な状況でも、必要な情報やタスクをリマインダーの形式ですばやく便利に書き留めることができます。
適切な日を探すためにカレンダーをめくったり、時計を回して適切な時間を設定したりする必要はもうありません。ボットに「何を」「いつ」と人間が伝えるだけで十分です。
結論
ノードjsでボットを開発する前は、javascriptに完全に慣れていなかったため、コードの記述に使用したすべての知識はインターネットから取得されました。インターネットでは、本当に必要なものが正確に見つからないことがよくあります。このため、おそらく、私のコードのどこかに非常にばかげたエラーがありますが、それについてはまだ特定することがあまりわかりません。
当初、私の目標は、プロジェクト構造の観点から最も高度で理想的なものを作成することではありませんでした。新しい知識を習得し、新しいプログラミング言語を学習してコンピュータサイエンス全般の理解を深め、MVP製品を作成することが最も重要でした。
しかし、この開発が求められている場合、私は喜んでそれを改善し続けます。何かアイデアがあったり、バグを見つけたりした場合は、プロジェクトのgithubへようこそ。私はすでに何をどこでどのように変更するか(たとえば、通常のビジターパターンを使用して解析モジュールのひどいスパゲッティコードを書き直す)のアイデアを持っており、英語のサポートを追加する予定です。
このボットがあなたの助けになるだけでなく、私と私の家族の日常の活動にも役立つことを願っています。
清聴ありがとうございました!
UPD:一般的な需要による音声メッセージのサポートが追加されました。
UPD 2:記事が公開されてから、ボットはメジャーアップデートを受け取りました。変更のリスト。