Telegram-bot:私の話。 パート2







こんにちは、ハブラハブル! この資料は第1部の続きであり、クラウドプラットフォームで製品を開発するためのツールと機会を強調しています。 例は、大学でのペアのスケジュールへのアクセスの現在のモバイル拡張-テレグラムボットです。



最初の公開に時間がかかったので、最初の展開と必要なリソースだけでなく、作成者からのアプリケーションの概要にも慣れることができます。 以下の情報は、技術的な側面の説明に焦点を当てており、現時点での結果の結論には焦点を当てていません。



UPD :プロジェクトは、大学の時間割に関する著者のフレームワーク「Rutetider」を使用して正常にリファクタリングされました( Habrahabrに関する記事GitHub )。 したがって、この記事のいくつかのポイントは一致しない場合があり、そのいくつかは存在しないか、異なって見える場合がありますが、概念は保持されます。



プロジェクト技術概要



説明と並行して、ライティングプロセスのより深い理解のために「シーンから」スクリーンショットを当てにすることができます。また、完全なソースコード( github.com )に注意を払うことをお勧めします。著者の裁量で、使用および提供されるコンポーネントの説明。 説明の一部が明確でない場合は、コメントまたはダイアログで著者に尋ねるか、主題領域と直接対話するために2分間かかることができます。これにより、記事と与えられた例をよりうまくナビゲートできます。



大学カップルのスケジュール



アプリケーションアーキテクチャの設計時には、公式サイトからの情報の直接収集(解析)を除いて、講義スケジュールを取得する他のオプションはありませんでした。 スケジュールが配置されているプラ​​ットフォームのAPIは利用できません。また、データベースから直接情報を抽出する可能性はありません。



必要な技術的操作( github.com )は、サーバー上の有用なスケジュールされた作業と密接に関連しています。その情報はセクションの最後にあります。



使用されるモジュールは次のとおりです。





dataLib.pyファイルには、各アカデミックグループにリクエストを行うための値キーの配列と、日付範囲を入力してスケジュールが必要な日付フレームを決定する関数が含まれています。



groupExample = {'TimeTableForm[date1]': firstDay, 'TimeTableForm[date2]': lastDay, 'TimeTableForm[faculty]':5, 'TimeTableForm[course]':3, 'TimeTableForm[group]':613}
      
      





これに続いて、ページオブジェクトを受信するためのポストリクエストを送信し、さらにそれをスープオブジェクトに渡します。スープオブジェクトには、便利な作業のための多数のメソッドがあります。



 for formData in dataLib.dateToDateForm(firstDay, lastDay): r = requests.post(config.url, data = formData) soup = BeautifulSoup(r.text, 'html.parser') dataProcessing.dataProcessing(soup)
      
      





dataProcessingモジュールには同じ名前の機能があり、必要なデータが処理されます。 たとえば、変数mainHtmlTableは、独自の一意の識別子を持つスケジュールを持つベーステーブルです。



 mainHtmlTable = soup.find("table", {"id": "timeTableGroup"})
      
      











(説明のための表の一部、学部、コース、およびグループを選択した後、完全版はリンクによって 「感じられる」ことができます)



もう1つの例は、10の長さ(「12/12/2016」-10文字)のテキストを内部に含むブロックタイプのすべての要素の受信に基づく日付です。



 divDate = [i.text[:-5] for i in mainHtmlTable.findAll('div') if len(i.get_text()) == 10][:-2]
      
      





次に、さらに便利な作業のために要約値を提供する相互に関連する多くのメソッドと関数の呼び出しがあります。



学部、コース、グループの名前、スケジュール自体、日付の3つの配列を使用します。これにより、データを簡単に処理し、さらに操作を実行できます。



一般的なユーザーインタラクションの概念



開発の最も重要な特質の1つは、最終結果のビジョンと建築の有能な構築です。 専門的な開発のどの段階でも、記述されたコードのモジュール性とコンパクトさ、システムコンポーネントの相互接続性、および発生していることのシンプルさのために多大な努力が必要です。



製品の開始点では反対であるにもかかわらず、行われた作業は例外ではなく、その結果、ユーザー要求ハンドラー(ハンドラー)、後続の一連の操作(クエリ)、ソースデータの生成(返信)など、ほとんどの操作に対して特定の概念設計パターンが形成されました)応答。









このテンプレートは珍しいものではありません。そのようなアプリケーションの動作モデルを事前に決定できれば、多くの時間と労力を無駄にすることを防ぐことができます。



リクエスト処理の例



すべてのリクエストのメインハンドラファイル( github.com )の後続のセクションでは、「Updates」という名前のメニュー項目のいずれかを選択したユーザーからのポストリクエストを見ることができますチャットする)、middlewareUserDataクラス( github.com )のotherFeature()メソッドを使用して、ユーザー情報(名、姓、チャットID、メニュー項目としての「news」およびニックネーム)を入力します。 この関数は、アプリケーション関数の使用に関する統計のためのユーザーアクションを記録します。 前の処理の後、プロジェクトニュースの場所に関する情報を含むテキストメッセージが、添付されたチャット識別子による応答として送信されます。



 @bot.message_handler(func=lambda mess: "" == mess.text, content_types=['text']) def handle_text(message): middlewareUserData.otherFeature(message.chat.first_name, message.chat.last_name, message.chat.id, 'news', message.chat.username) bot.send_message(message.chat.id, '       — https://telegram.me/dutbotupdates')
      
      





プロセスの図を以下に示します。 データベーステーブルに関連する画像はクリック可能です(より良く見ることができます)。なぜなら、それらは低品質で表示されますが、開発画像の整合性を失わないようにするためです。











スケジュールを取得する概念



今日または明日のスケジュールは、2つの方法で利用できます。 最初のオプションを検討してください-段階的なデータ入力を通じて:学部、コース、グループを選択する必要があります。 「メッセージ」オブジェクトの「テキスト」属性は、メニュー項目選択のテキスト値であることを思い出させてください。



1. 「スケジュールの取得」ボタン-ユーザーはデータの基本セットを送信します。



 middlewareUserData.getUser(message.chat.first_name, message.chat.last_name, message.chat.id, message.chat.username)
      
      





したがって、アクションはこの形式でデータベーステーブルに表示されます(セクションの最後にある次のデータベース操作の例)。





2.教員の選択:



 middlewareUserData.updateFaculty(message.text, str(message.chat.id))
      
      





3.コースとグループの選択スクリプトは前のものとわずかに異なります。これは、グループリストが全スケジュールのテーブルへのクエリ後に画面に表示され、グループのリスト全体がユーザーによって設定された学部とコースに引き出されるためです:



 middlewareUserData.updateCourse(message.text[:1], str(message.chat.id)) fucAndCourse = middlewareUserData.getFacultyAndGroup(str(message.chat.id)) groupList = selectData.selectGroup(fucAndCourse[0], fucAndCourse[1]) basicMarkupRows.markRowGroupList(groupList, message)
      
      





4. 「今日」または「明日」ボタン。コードには現在の日付セット(今日、明日、今日のインデックス)が含まれ、ユーザーからの入力を確認します(全員に1つのデータベースがあり、特定のユーザーの結果を取得する必要があります)およびスケジュール自体( github.com ):



 day = selectData.selectDates() lastGroup = middlewareUserData.summaryVerification(str(message.chat.id)) bot.send_message(message.chat.id, "   ({0}):".format(day[1])) message.text = printController.show(lastGroup, day[1]) bot.send_message(message.chat.id, message.text)
      
      





ユーザーアクションのために順番にテーブルに入力する図:





前のメニューに戻る



前のセクションを注意深く読んだ場合、テーブルの最も重要な要素である「空」に間違いなく注意を払うことになります。 戻る関数は、そのようなレコードの数から直接プッシュされます。



「スケジュールを取得」-学部、コース、グループ、および最終メニュー項目が選択されていないため(たとえば、特定の日のスケジュールやグループへの登録)、4つの空の値(テキスト値は「空」)とともに最優先オブジェクトが形成されます。



教員の選択はすでに「空」の1つ少なく、コースの選択はすでに2つです。



スクリプト( github.com )は、ユーザーに対してテーブル行のそのようなフィールドの数を決定し、どのメソッドを呼び出す必要があるかを事前に知っています。 たとえば、コースの選択に決着しました。つまり、教員を選択し、3つの「空の」意味があります。



 if emptyCount == 3: backButton.cancelOperation(str(message.chat.id), 3) basicMarkupRows.markRowGetFacultyList(message)
      
      





cancelOperationメソッド( github.com )は、キャンセルするフィールドをクリーンアップする関数を定義します。



 if self.emptyCount == 3: self.cancelFaculty(self.chatid)
      
      





教員と間違えた場合は、変更する必要があります。 内部では、状況は次のとおりです。ユーザーIDによって、単純なSQLクエリ「更新」を介して、教員の値(「情報技術」など)を空の値(「空」)に変更します。



 def cancelFaculty(self, chatid): self.chatid = chatid self.cursor.execute("UPDATE statistic SET faculty = (%s) WHERE id IN (SELECT max(id) FROM statistic WHERE chatid = (%s))", ('empty', self.chatid)) self.connection.commit()
      
      





統計テーブルのデータを変更し、「faculty」フィールドを取得するだけで十分です。テーブルフィールド識別子は特定のユーザー識別子の最大値です(つまり、目的のユーザーのテーブルの最後の行を選択すると、メニューとデータの現在の状態になります)。



グループスケジュールサブスクリプション









最初のメニューからグループのスケジュールへのアクセスを2日間アレンジする機能は、グループをテーブルに1回入力することに基づいています。つまり、最後のメニュー( github.com )で利用可能なグループを選択し、サブスクリプションを確認する必要があります



 if message.text == "   ": middlewareUserData.subscribe(message.chat.first_name, message.chat.last_name, message.chat.id, lastGroup, message.chat.username) message.text = '    {0}.'.format(lastGroup) bot.send_message(message.chat.id, message.text)
      
      





subscribe()関数( github.com )は、他のユーザーと接続されていない別のサブスクリプションストレージテーブルに使い慣れたデータを挿入しますが、最も重要なのは識別子とグループ自体です。



 def subscribe(self, firstname, lastname, chatid, group, username): * -* self.cursor.execute("INSERT INTO subscribers (firstname, lastname, chatid, groupa, username) VALUES (%s, %s, %s, %s, %s)", (self.firstname, self.lastname, self.chatid, self.group, self.username)) self.connection.commit()
      
      





スケジュールされたサーバー作業



使いやすいAPSchedulerライブラリは、アプリケーションが配置されているプラ​​ットフォームと完全に互換性があるため、特定の時間に実行するさまざまなタスクを計画できます。



ボットは、ペアのスケジュールと今日と明日の日付を毎日更新する必要があります。これらの日付は、以下のコードの関数を使用して正常にアクセスできます。 サーバーは異なるタイムゾーンにあるため、適切な時間から2時間を差し引く必要があります(00:01に更新があります)。 月曜日から金曜日まで、現在の週の情報は日曜日に撤回されます(その日のインデックスは5です)。



 @sched.scheduled_job('cron', day_of_week='mon-sun', hour=22, minute=1) @sched.scheduled_job('cron', day_of_week='mon-fri', hour=22, minute=1) @sched.scheduled_job('cron', day_of_week=5, hour=22, minute=1)
      
      





ソースコード( github.com )は、戦闘状態では実際には動作せず、まだファイナライズされていますが、コンセプトは正しく定義されています(12/15に修正)。



データベースを操作する



Herokuプラットフォームを使用すると、パスワードとログインの種類ごとにデータを入力した後、ネイティブコンソール(Linux Ubuntu 16.04)からデータベースを直接操作したり、SQLシェル(Windows 7)からデータベースにアクセスしたりできます。



データベースに関連付けられたボットのサーバー部分は、単純なSQLクエリ(たとえば、選択、挿入、更新)、および対応する作成および削除コマンドを使用してテーブルを作成および削除する必要に限定されます。



結論









膝にプログラムコードを入力すると、幸いなことに、最終的な効果についての私の期待が叶わないとは思いませんでした。 しかし、アプリケーションに関与する何らかの方法で、現在の状況に値しないと考える人はいません。 アーキテクチャをアップグレードする間、データベースを使用したり、追加機能を導入する予定はありませんでした。 しかし、最終的には、これらのすべてが開発計画に含まれており、プロジェクトを真剣に進めるだけでなく、一般的および個人的な観点から必要な高品質の結果を得ることができました。 ソフトウェア開発のライフサイクル中にさまざまな役割に慣れる必要があるため、ある段階では、通常の動作モデルを「放棄」する必要がありました。 その過程で、彼はソーシャルマーケティングに従事し、開発された製品に関する情報を学生に広め、当時は少なくとも一部はオンラインだったように「吸い出した」。



そのような取るに足らない結果-毎日100人以上のユニークユーザー-でさえ、毎日他の人の問題を解決するリソースの著者の態度にプラスの影響を与えるだけでなく、主題分野に関連するすべての分野でプロセスを改善し続けるための議論の余地のない動機でもあります。



All Articles