Habrahabr用のTelegramボットの作成

この記事では、Telegramボットがどのように作成されたかについてお話したいと思います。これにより、Habrahabrから記事を最初にPythonに、次にGoに送信できます。







少しの背景



それはすべて、夏にテレグラムが私の人生にますます浸透し始めたときに始まりました。 Pythonでいくつかのテストボットを作成した後、Habrahabr向けに何かを作成するというアイデアが生まれました。 最初のアイデアはシンプルでした。ボットは新しい記事の通知を送信するだけでした。







最初のバージョン(Python 3.5)



短いグーグルの後、サイトにRSSフィードがあることが発見されました。 記事を投稿するプロセスはすぐに簡素化されました。今では、サイト全体を解析する必要はなく、数分ごとにRSSフィードのみを見るだけで十分です(私の場合は10)。







ボットの最初のバージョンは非常に迅速に作成されました。 Telegram APIとやり取りするために、 pyTelegramBotAPIライブラリが使用され 、RSSフィードの解析にはfeedparserが使用されました







その過程で、構造はさらに複雑になりました。ボットは新しい記事を送信するだけでなく、ユーザーがサブスクライブしたタグを含まない記事を除外することもできました。 実装は非常に簡単でした。SQLiteデータベースが使用され、2列(idとタグ)しかありませんでした。幸いなことに、Python3には対話するための組み込みライブラリがありました。 タグを編集するためのコマンドも追加されました。ユーザーはタグを削除、追加、コピーできます。 後者は非常に簡単に発生しました。ユーザーがボットにプロファイルへのリンクを送信し、その後、タグが(悔い改め!これが悪いことを知りませんでした)正規表現を使用して検索されました。







問題



最終的なプログラムはかなり不安定であることが判明しました:非常に頻繁にクラッシュしました(これを避けるためにwhile True:



コードの一部をラップする必要がありましたwhile True:



。 その正規表現を忘れないでください。 その結果、ボットは曲がっていたにも関わらず動作したため、すべてをそのままにして、(2月末まで判明したように)ライブにすることが決定されました。 ソースはGitHubを見つけることができます(しかし必要ですか?)。







2番目のバージョン(Go)



かなり前に、Goを試すというアイデアが頭に残っていましたが、手が届きませんでした。 そして最後に、自由時間が見つかりました。 ドキュメントを読んだ後、私は何かを書きたかったのですが、ちょうどそのときPythonボットが落ちました( while True



が役に立たなかったとしても)。 これが上からの兆候であることを認識して、Goでボットを書き直し始めました。







残念ながら、Goでの実際の開発経験はなく、尋ねる人はいません。 したがって、私が使用するソリューションは、経験のある人には最適ではないようです。 何かが本当に悪い場合は、間違っているものを書いてください。 それでは、アプリケーションアーキテクチャの説明に移りましょう。







ライブラリから始めましょう。 Telegram -bot-api.v4は Telegram APIとの対話に使用され、 go-sqlite3は SQLite3との対話に使用されます。 RSSフィードはgofeedを使用して解析されます。 ユーザータグをコピーするには、Go- soupの Beautiful Soupのアナログを使用します。







それでは、コードに移りましょう。 ボットから新しいメッセージを受信するメインループがあります。 コマンドのタイプを決定します。







 for update := range updateChannel { if update.Message == nil { continue } else if update.Message.Command() == "start" { startChan <- update.Message } else if update.Message.Command() == "help" { helpChan <- update.Message ... } else { message := tgbotapi.NewMessage(update.Message.Chat.ID, "...") message.ReplyToMessageID = update.Message.MessageID bot.send(message) } }
      
      





コードから理解できるように、各コマンドは個別のゴルーチンで処理され、メッセージはチャネルを使用して送信されます。







 startChan := make(chan *tgbotapi.Message, 50) helpChan := make(chan *tgbotapi.Message, 50) getTagsChan := make(chan *tgbotapi.Message, 50) ... // Goroutines go bot.start(startChan) go bot.help(helpChan) go bot.getTags(getTagsChan) ...
      
      





ユーザーにアラートを送信することもできます。 これは専用のWebページを使用して行われます。







ウェブページ







プロジェクトは、いくつかのパッケージに分割されることが決定されました。









プログラムの開始方法は次のとおりです。







  1. ログを開くためのファイル
  2. 構成ファイルの読み取り
  3. ボットの初期化とデータベースのオープン
  4. ボットは別のゴルーチンで起動します(ボットが起動すると、ゴルーチンはコマンドを処理する機能で起動します)
  5. サイトは別のゴルーチンで起動されます


ボットの起動または操作中にプログラムが正常に動作しないエラーが発生した場合、プログラムはコード1で終了します。







問題



残念ながら、今回は問題を回避できませんでした。 しかし、これらはボットの動作とは関係なく、プログラムの開発とLinuxの実行可能ファイルのコレクション(開発はWindows 10で実行され、サーバーはUbuntu 16.04で実行されます): go-sqlite3



ライブラリが動作するにはCGOが必要であり、 go build



コマンドがCGO_ENABLED=1



フラグで実行されますCGO_ENABLED=1



エラーが表示されます。 このため、Ubuntuを使用して仮想マシンでプロジェクトをコンパイルする必要があります。







なんで?



「ウェブサイトがあるのに、なぜこのボットを使用するのですか?」と尋ねることができます。 答えようとします。 しかしその前に、ボットは決してサイトの代替ではなく、単なる追加であると言いたいです。









おわりに



要約すると、Goでボットを作成した経験は非常に興味深く、有用でした(私は願っています)。 ボットに興味がある場合は、 ここで自分見つけることができ、そのソースコードは再びGitHubにあります








All Articles