Dogecoin暗号通貨ウォレットに関する情報を取得するためのTelegramボットの作成

画像

2008年のブロックチェーン技術の説明と2009年の最初の実装(ビットコイン)以来、今日までに1,000を超える暗号通貨が作成されています。 ICOは数日ごとに開催されます。 多くは暗号通貨交換でマイニングまたはプレイしています。



通貨は不安定であり、為替レートは常に変化しているため、貯蓄の損失を避けるために、アカウントのレートと状態に関する最新情報をできるだけ早く受信できることが重要です。



ブロックチェーンに関する情報は一般公開されているため、Webサービスとモバイルアプリケーションを使用してアクセスできます。 アカウントのステータスを監視するには、マルチ通貨モバイルアプリケーションを使用すると便利です。 ただし、新しい暗号通貨の作成が高速であるため、すべての開発者がサポートを追加できるわけではなく、ユーザーは必要な通貨で他のアプリケーションをインストールすることを余儀なくされ、デバイスの使いやすさと占有メモリスペースに影響します。 ここで、私たちの時代のもう一つのトレンドが私たちの援助に来ます-ほとんどのインスタントメッセンジャーによってその管理APIが提供されるチャットボット



Dogecoinのような暗号通貨のアカウントに関する情報を提供するTelegramのチャットボットの作成を検討してください。 Dogecoinは2013年に導入され、Dogeインターネットミームにちなんで命名されました。 多くの場合、寄付や慈善団体を収集するために使用されます。



Telegramにボットを登録する



メッセンジャーにボットを登録することから始めましょう。 これを行うには、Telegramですべてのボットの父を見つけます-BotFather、「/ newbot」コマンドを送信し、表示(DogeWallet)と一意の名前(DogeWalletBot)の必須パラメーターを入力します。 その後、BotFatherはボットアクセストークンを提供します。 これは登録で行うことができますが、使いやすさのために、ボットの説明、画像、および「/」記号を入力した後に表示されるコマンドのリストも紹介します。





プリセット



ボットが登録され、基本機能が定義されたので、開発プラットフォームの選択を開始できます。 Microsoft Bot Frameworkでボットを作成します。 ダイアログとサポートされている通信チャネルの大規模なセットを使用して十分な機会を提供します(コードをほとんど書き換えることなく、別のメッセンジャーでボットをすばやく起動する機能を提供します)。言語としてC#を選択します(Node.jsを使用することも可能です)。



開始するには、Visual Studio 2015以降、ボットアプリケーション、ボットコントローラー、ボットダイアログ、ボットフレームワークエミュレーターボットテンプレートが必要です。インストール手順については、 Microsoft Bot Frameworkのドキュメントで詳しく説明しています



ボットの作成、コマンドの処理



ボットアプリケーションテンプレートからプロジェクトを作成します。



画像



プロジェクト構造では、MessagesControllerやRootDialogなどのクラスを観察できます。 すべての着信メッセージを受け入れるアプリケーションの入力ポイントは、MessagesControllerクラスのPostメソッドです。 次のコードが含まれています。



public async Task<HttpResponseMessage> Post([FromBody]Activity activity) { if (activity.Type == ActivityTypes.Message) { await Conversation.SendAsync(activity, () => new Dialogs.RootDialog()); } else { HandleSystemMessage(activity); } var response = Request.CreateResponse(HttpStatusCode.OK); return response; }
      
      





テキストであるメッセージは、さらに処理するためにRootDialogに渡され、残りはすべてMessagesControllerクラスのHandleSystemMessageメソッドに渡されます。 テキストではないメッセージは、チャットへのユーザーまたはボットの追加、ダイアログの開始または終了に関するメッセージです。



RootDialogクラスは、すべてのダイアログと同様に、IDialogインターフェイスを実装し、StartAsyncメソッドを含める必要があります。 ボットが最初に受信したメッセージはこのメソッドに送られます。 デフォルトでは、context.Wait(MessageReceivedAsync)の呼び出しが含まれています。つまり、次のメッセージを処理するメソッドがインストールされます(ただし、受信したメッセージのハンドラーが以前にインストールされていないため、MessageReceivedAsync呼び出しはStartAsyncの直後に発生します)。



MessageReceivedAsyncメソッドを変更して、受信したメッセージをユーザーに送信する代わりに、前に定義したコマンドを処理するようにします。



 private async Task MessageReceivedAsync(IDialogContext context, IAwaitable<object> result) { var activity = await result as Activity; // if "/setwallet" command if (activity.Text == "/setwallet") { context.Call(new SetWalletDialog(), SetWalletDialogResumeAfter); } // if "/setwallet [address]" command else if (activity.Text.Contains("/setwallet")) { var forvardedMsg = context.MakeMessage(); forvardedMsg.Text = activity.Text; await context.Forward(new SetWalletDialog(), SetWalletDialogResumeAfter, forvardedMsg, CancellationToken.None); } // if "/balance [address]" command else if (activity.Text.Contains("/balance")) { var forvardedMsg = context.MakeMessage(); forvardedMsg.Text = activity.Text; await context.Forward(new GetBalanceDialog(), GetBalanceDialogResumeAfter, forvardedMsg, CancellationToken.None); } else { if (activity.Text == "/start") //start conversation await GreetUser(context, result); else if (activity.Text == "/help") //show help await ShowHelp(context); context.Wait(MessageReceivedAsync); } }
      
      





「/ setwallet」コマンドが最初に処理されます。アドレスを指定せずにこのコマンドのみを入力すると、context.Callメソッドを使用してSetWalletDialogダイアログが呼び出されます。 呼び出された新しいダイアログや、呼び出されたダイアログの終了時に呼び出される関数(SetWalletDialogResumeAfter)などのパラメーターを受け入れます。 Microsoft Bot Frameworkがダイアログのスタックなどの構造を使用していることは注目に値します。つまり、最初にRootDialogが呼び出され、次にSetWalletDialogが呼び出されてスタックの最上部に配置されます。 一番上にありますが、すべてのメッセージが届きます(必要に応じて制御できるグローバルダイアログは別として)。 新しいダイアログを作成すると、SetWalletDialogクラスのStartAsyncメソッドがすぐに呼び出されます。



  public async Task StartAsync(IDialogContext context) { var msg = context.Activity.AsMessageActivity(); if (msg.Text == "/setwallet") await context.PostAsync("Enter DogeCoin wallet address, please!"); context.Wait(MessageReceivedAsync); }
      
      





コマンドにアドレスが含まれていない場合、ユーザーにアドレスの入力を促すメッセージが表示されます。 次に、次のメッセージハンドラがインストールされ、入力が期待されます。



アドレスを含むコマンドが到着すると( "/ setwallet [address]")、Forwardメソッドを使用して新しいダイアログが呼び出されます。 このメソッドはCallとは異なり、呼び出されたダイアログにメッセージをさらに渡し、StartAsyncメソッドの完了後、入力を待機せず、メッセージはすぐにSetWalletDialogクラスのMessageReceivedAsyncメソッドに渡されます。 この方法を検討してください。



 private async Task MessageReceivedAsync(IDialogContext context, IAwaitable<IMessageActivity> result) { var message = await result; string address = ""; if ((message.Text != null) && (message.Text.Trim().Length > 0)) { if (message.Text.Contains(" ")) //if "/setwallet [address]" command { address = message.Text.Replace("/setwallet ", "").Trim(); } else address = message.Text; try { var balance = await Client.GetBalanceAsync(address); if (balance.Success == 1) { context.UserData.SetValue("wallet", address); context.Done(address); } else await ProcessErrors(context); } catch(Exception ex) { await ProcessErrors(context); } } }
      
      





メッセージが分析され、スペース(コマンドとアドレスの両方)が含まれている場合、このアドレスが割り当てられ、変数に格納されます。 このオプションは、Forwardダイアログが呼び出されたときにトリガーされます。 メッセージにスペースが含まれていない場合(ボットが入力の提案について通知した後にアドレスが入力されたと想定される)、アドレスは処理されずに変数に格納されます。 このケースは、Callメソッドを使用してダイアログを作成するときに発生します。 次に、バランスを取得しようとして、存在するアドレスがチェックされます。 これが成功すると、アドレスはMS Bot Framework内部ストレージ(context.UserData.SetValue( "wallet"、アドレス))に保存され、SetWalletDialogダイアログは終了し、スタックから削除され(context.Done(アドレス))、親ダイアログにアドレスを渡します。



エラー(間違ったアドレス)の場合、ProcessErrorsメソッドでエラー処理が発生します。



 private async Task ProcessErrors(IDialogContext context) { --attempts; if (attempts > 0) { await context.PostAsync(ExceptionMessage); context.Wait(MessageReceivedAsync); } else { /* Fails the current dialog, removes it from the dialog stack, and returns the exception to the parent/calling dialog. */ context.Fail(new TooManyAttemptsException(ExceptionFinalMessage)); } }
      
      





ユーザーは正しいアドレスの入力を何度か試みられ、ダイアログはエラーメッセージ(context.Fail(新しいTooManyAttemptsException(ExceptionFinalMessage)))で終了し、制御はRootDialogに渡されます。



子ダイアログの完了後、親で[DialogClassName] ResumeAfterメソッドが呼び出され、そこで子ダイアログの結果のさらなる処理が実行され、次のメッセージの受信者を示すためにcontext.Wait(MessageReceivedAsync)メソッドが呼び出されます。



残りのコマンドは同様の方法で処理されますが、1つの違いがあります-それらは修飾メッセージの入力を必要としないため、常にForwardメソッドによって送信されます(コマンドが引数なしで入力された場合、アドレスはストアから取得されます(context.UserData.TryGetValue( "wallet"、out address) )



ボットによる出力用のデータの取得、特に前述のClient.GetBalanceAsyncメソッドについて説明します。 クライアントは、暗号通貨ウォレットデータへのアクセスを提供する静的クラスです。 対応するサービスのAPIにアクセスするメソッドが含まれています。 このプロジェクトは、dogechain.infoやchain.soなどのプロジェクトのAPIを使用します。 GetBalanceAsyncメソッドを検討してください。



 public static async Task<BalanceEntity> GetBalanceAsync(string address) { return await GetAsync<BalanceEntity>($"address/balance/{address}"); }
      
      







ここでは、クエリを補完し、返されるデータのタイプを示す一般的なデータ取得メソッドが呼び出されます。 返されるデータのタイプは、単純なPOCOクラスBalanceEntityで説明されています。

 public class BalanceEntity { public string Balance { get; set; } public int Success { get; set; } }
      
      





GetAsyncメソッドを検討してください。



 public static async Task<T> GetAsync<T>(string path) { InitClient(); T entity = default(T); HttpResponseMessage response = await client.GetAsync(path); if (response.IsSuccessStatusCode) { var jsonString = await response.Content.ReadAsStringAsync(); entity = JsonConvert.DeserializeObject<T>(jsonString); } return entity; }
      
      





このメソッドは、InitClientメソッドでHttpClientクラスの新しいインスタンスを初期化します。



 public static void InitClient() => InitClient(WebApiHost); public static void InitClient(string webApiHost) { WebApiHost = webApiHost; if (client != null && !string.IsNullOrEmpty(WebApiHost) && client.BaseAddress.AbsoluteUri == WebApiHost) return; client = new HttpClient { BaseAddress = new Uri(WebApiHost) }; client.DefaultRequestHeaders.Accept.Clear(); client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json")); }
      
      





次に、ウォレットデータを提供するサーバーに対して要求が行われ、jsonオブジェクトが正常に受信されると、対応するクラスに変換されます。



基本的なコマンドを実装した後、ボットのパフォーマンスを確認できます。 これを行うには、以前にダウンロードしたエミュレータを使用します。 ボットが実行されているアドレスを入力し、[接続]をクリックします。 コマンド「/ setwallet」を入力します-ボットはウォレットのアドレスを入力するように指示します。 紹介します。



画像



ボットは、正常に保存したことを報告します。



画像



「/ balance」コマンドを使用して残高を確認し、アカウントに357匹を超える犬がいることを確認します。「D6VDAHdzDuuUxorDN1dRZVudu2PfxZvUNpアドレスのバランスは357.91600317 DogeCoin's」です。



ユーザーが最初にボットを呼び出すときに送信される挨拶を追加します。 Telegramを通信のプラットフォームとして使用しているため、ボットが最初に受信するメッセージは「/ start」になります。 それと、RootDialogクラスのMessageReceivedAsyncの「/ help」コマンドを処理します。



 if (activity.Text == "/start") //start conversation await GreetUser(context, result); else if (activity.Text == "/help") //show help await ShowHelp(context); context.Wait(MessageReceivedAsync);
      
      





コマンドを受信すると、適切なメソッドを呼び出し、次に受信したメッセージを処理するようにメソッドを設定します。 GreetUserメソッドはウェルカムメッセージを送信し、コマンドに関するヘルプを表示します。ShowHelpのみのヘルプです。



 private async Task GreetUser(IDialogContext context, IAwaitable<object> result) { await SendGreetMessage(context); await ShowHelp(context); }
      
      





SendGreetMessageメソッドでは、挨拶メッセージが作成され、Dogeイメージが添付されます。



 private async Task SendGreetMessage(IDialogContext context) { var qrMsg = context.MakeMessage(); qrMsg.Text = "Welcome, Young Shibe!\r\n"; qrMsg.Attachments.Add(new Attachment() { ContentUrl = "http://www.stickpng.com/assets/images/5845e608fb0b0755fa99d7e7.png", ContentType = "image/png", Name = " " }); await context.PostAsync(qrMsg); }
      
      





新しいAttachmentには、ContentUrl(画像へのパス)、ContentType-添付ファイルの種類、Name-名前などのパラメーターが含まれます。



MSボットフレームワークにボットを登録する



ボットを作成し、エミュレーターを使用してローカルでデバッグした後、サーバーにデプロイしてAzureに登録することができます(以前はポータルbotframework.comで登録が行われていましたが、最近Azureへの移行が実行されており、そこで新しいボットを作成することをお勧めします)。 ボットをWindowsホスティング(残念ながら、ボットビルダーは現在のバージョンのコアをサポートしていません)またはAzureで公開しています。 その後、ボットを登録します。 これを行うには、portal.azure.comに移動し、ボタンをクリックして新しいリソース(新規)を作成し、検索に「bot」と入力します。 リストから[ボットチャネル登録]を選択し、[作成]をクリックします。



画像



フィールドに入力し、メッセージングエンドポイントとしてデプロイされたボットのアドレスを入力し、「/ api / messages」 -dogewalletbot.azurewebsites.net/api/messagesを追加します。



画像



「ボットチャネル登録」を作成した後、「設定」タブでMicrosoft App IDとその隣にある「管理」リンクを探します。 apps.dev.microsoft.comにアクセスし、[新しいパスワードを作成]ボタンをクリックします。 Microsoft App IDとパスワード(MicrosoftAppPassword)を覚えて、appSettingsセクションでボットのWeb.configに入力します。 その後、ボットのチャネルとの通信が機能するはずです。 「Webチャットでのテスト」セクションで作成したボットチャネル登録サービスを確認してみましょう。



画像



次に、チャネルを接続してTelegramに接続します。 [チャンネル]をクリックし、[テレグラム]を選択して、BotFatherが提供するトークンを入力します。 Telegramに移動し、ボットを追加して[開始]をクリックします。



画像



「/ start」コマンドを受信したボットは、挨拶とヘルプで応答します。 他のコマンドの処理も発生します。



レポート作成



着信トランザクションに関するレポートをPDF形式の「トランザクションID、値」のリストの形式でウォレットアドレスに送信します。 これを行うには、FastReport.NetレポートジェネレーターとTelegram APIライブラリ(Telegram.Bot)を使用して、pdfをTelegramサーバーに送信します。



chain.so/api/v2/get_tx_received/DOGE [アドレス]でトランザクションデータを受信します。 答えを次の構造のクラスに変換します。



 public class ReceivedTransactionsResponse { public string Status { get; set; } public ReceivedTransactionsEntity Data { get; set; } } public class ReceivedTransactionsEntity { public string Address { get; set; } public List<ReceivedTransaction> Txs { get; set; } } public class ReceivedTransaction { public string Txid { get; set; } public string Value { get; set; } public string Confirmations { get; set; } }
      
      





Clientクラスのトランザクションデータを取得する方法は次のとおりです。



 public static async Task<List<ReceivedTransaction>> GetReceivedTransactions(string address) { WebApiHost = WebApiHostChainSo; var trs = await GetAsync<ReceivedTransactionsResponse>($"get_tx_received/DOGE/{address}"); WebApiHost = WebApiHostDogechain; return trs?.Data?.Txs; }
      
      





メソッドの開始時にAPI呼び出しのURLをオーバーライドし、終了する前に戻ります。



ReportDialogクラスでトランザクションのリストを受け取った後、SendReportメソッドが呼び出されます。



 private async Task SendReport(IDialogContext context, string address, List<ReceivedTransaction> transactions) { Reporter repr = new Reporter(); if (context.Activity.ChannelId != "telegram") return; using (MemoryStream pdfReport = repr.GetReceivedTransactionsPdf(address, transactions)) { TelegramBotClient client = new TelegramBotClient("telegram_bot_token"); var me = await client.GetMeAsync(); var chatId = context.Activity.From.Id; await client.SendDocumentAsync(chatId, new FileToSend("Received transactions.pdf", pdfReport), "First 100 received transactions."); } }
      
      





その中で、Reporterクラスでレポートが作成されます。 次に、TelegramBotClientが作成され、pdfレポートが送信されます。



ReporterクラスのGetReceivedTransactionsPdfメソッドを検討してください。



 public MemoryStream GetReceivedTransactionsPdf(string address, List<ReceivedTransaction> transactions, string afterTXID = null) { string appData = HostingEnvironment.MapPath("~/App_Data/"); Config.WebMode = true; Report = new Report(); Report.Load(appData + "TransactionsReport.frx"); Report.RegisterData(transactions, "txs"); Report.GetDataSource("txs").Enabled = true; (Report.FindObject("Data1") as DataBand).DataSource = Report.GetDataSource("txs"); Report.Prepare(); PDFExport pdf = new PDFExport(); MemoryStream exportStream = new MemoryStream(); Report.Export(pdf, exportStream); exportStream.Position = 0; return exportStream; }
      
      





初めに、Config.WebMode = trueの行はFastReport.Netの動作モードを設定します。これにより、Webモードでは不要なインディケーターやその他のグラフィックスの読み込みが防止されます。 次に、App_Dataフォルダーから事前に準備されたレポートがロードされます。 レポートには、レポートのタイトル、ページ、およびDataBandが含まれます。 データバンドには、トランザクション番号とその値を表示する2つのテキストオブジェクト(TextObject)があります。



画像



レポートを読み込んだ後、データはReport.RegisterDataメソッドを使用して接続され、接続されたデータソースがオンになり、そのデータバンドが割り当てられます。 その後、PDFにエクスポートされ、レポートを含むストリームが返されます。



チームの仕事を確認してください。 Telegramにメッセージを送信します-/ DRapidDiBYggT1zdrELnVhNDqyAHn89cRiを報告し、応答でメッセージを取得します。



画像



ファイルを開き、着信トランザクションとその値のリストを確認します。



画像



おわりに



プロジェクトのソースコードはGitHubで入手できます



現在、MS Bot Frameworkを完全に使用するには、.Net FrameworkとWindowsの完全なホスティングが必要です。これにより、ボットのサービスコストが多少増加しますが、次のバージョンではMicrosoft.Bot.Builderのコアサポートを追加する予定です。 残念ながら、リリース日はまだわかっていません。



便利なリンク



  1. Telegramボットのドキュメント
  2. MS Bot Frameworkドキュメント
  3. GitHubのTelegram Bot API用の.NETクライアント
  4. Telegram Bot APIドキュメント用の.NETクライアント
  5. Dogechain.info APIの説明
  6. chain.so APIの説明



All Articles