別のテレグラムボットまたはデートボットの実装

私の名前はVladです。職業上、私は軍人ですが、ビジネスオートメーション会社でパートタイムで働いており、.netでプログラミングをしています。



簡単な背景



私の元(通常の)花嫁との次の収-不一致のとき、彼女は退屈から、写真やジオロケーションを送信し、近​​くにいる人を拾うことができる電信ボットを介してデートの相手を探していると言いました。 私たちが再び逃げたら似たようなものを書くと約束しました。 ヤラはあなたのためです。

私はそれを安全に忘れていましたが、次の怠idleのときに、緑の背景にカップケーキでウェブサイトをスクロールしました 。そこで、写真付きの投稿を投稿したばかりのセクションに出会い、自分自身について簡単に書いて、連絡先を示しました。



だから、アイデアは、友人や他の人を見つけるのに役立つ独自のボットを作成するようになりました。



挑戦する



チャットしたい人が自分自身に関する短いデータを投稿し、彼らが彼に手紙を書くまで待つことができるボットを作成します。







仕事の準備



BotFatherを使用してボットを作成する方法は、興味のない人だけを知っているわけではないので、記事に追加情報を記載しません。



「プロファイル」の保存



最初に、データを操作するために使用するClassLibraryプロジェクトを作成しました。



最初に、ユーザーデータの保存方法を決定する必要があります。 これを行うには、ユーザーを「説明」する必要があります。



public class user { [Key] public string tg_id { get; set; }//   public string name { get; set; }//  public string age { get; set; }//  public string country { get; set; }//  public string city { get; set; }// public string gender { get; set; }// public string photo { get; set; }//   public string tg_username { get; set; }// -,           public string tg_chat_id { get; set; }// ,    }
      
      





ストレージ用に、リモートサーバーに展開されたPostgreSQLデータベースが選択されました。

まず、NuGetを使用してEntityFrameworkを設定します。 データベースを操作する際の生活を非現実的に単純化します。



動作するには、パッケージが必要です。



NpgSQL.EntityFrameworkCore.PostgreSQL







また、移行にはパッケージが必要です。



Microsoft.EntityFrameworkCore.Tools







テーブルのルーチン作成を処理しないために、データモデル自体(上記のクラス)を作成し、データベースへの接続を設定します。



 public DbSet<user> user { get; set; } protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder) { optionsBuilder.UseNpgsql(connectionString); }
      
      





さらに移行を実行します。



これを行うには、パッケージマネージャーコンソールで次のコマンドを実行します。

enable-migrations





移行メカニズムを有効にする

Add-migration * *





移行を作成する

update-database





データベースの更新



これで、データベースに移行の履歴とユーザーテーブル自体の2つのテーブルができます。







データの保存とデータベースへの接続の問題を解決したら、ボットハンドラー自体の作成に進むことができます。



ハンドラーボット



Telegram自体には、更新を受信するための2つのオプションがあります。Webhook、または常にサーバーをプルし、更新を確認します。 Webhookには多くの困難があるため、更新を確認する方が簡単です。



更新を受信して​​処理する



自転車を作成しない(時には便利な)ために、既成のソリューションであるTelegramを使用する方が簡単です。MrRoundRobinのBotは、Telegramを操作するための優れた非常に便利なライブラリです。



ソリューションに新しいConsoleAppプロジェクトを作成し、このパッケージをインストールします。



 private static readonly TelegramBotClient Bot = new TelegramBotClient(token);//  static void Main(string[] args) { var me = Bot.GetMeAsync().Result;//  ,    (  ,   ) Console.Title = me.Username; //   Bot.OnMessage += BotOnMessageReceived; Bot.OnCallbackQuery += BotOnCallbackQueryReceived; Bot.OnReceiveError += BotOnReceiveError; //   Bot.StartReceiving(Array.Empty<UpdateType>()); Console.WriteLine($"Start listening for @{me.Username}"); Console.ReadLine(); Bot.StopReceiving(); }
      
      





したがって、更新プログラムのチェックを開始し、エラーハンドラーをインストールしました。

BotOnMessageReceived



「通常の」メッセージを受信するためのハンドラー

BotOnCallbackQueryReceived



メッセージの下に表示されるボタンをクリックするためのハンドラー。



ケースは小さく、アンケートを残す能力と残りをスクロールする能力です。 そのため、ユーザーに登録と次への2つのボタンを送信する必要があります。 ボタンはInlineKeyboardButton



オブジェクトを表し、すべてのボタンをパッケージ化する必要があります



 IEnumerable<IEnumerable<InlineKeyboardButton>>
      
      





ボットが開かれると、テキスト「/ start」を含むメッセージがすぐに送信されるため、このメッセージをBotOnMessageReceived



処理し、応答としてボタンを送信する必要があります。



 if (message.Text == "/start") { var inlineKeyboard = new InlineKeyboardMarkup(new[] { new [] // first row { InlineKeyboardButton.WithCallbackData("!", "Next"), InlineKeyboardButton.WithCallbackData("", "Registration") } }); Bot.SendTextMessageAsync(message.Chat.Id, "   lovebot! \r\n   - /start\r\n       - /register\r\n     - /stats\r\n     - @hahah2016", replyMarkup: inlineKeyboard); return; }
      
      





登録



登録するには、ユーザーが以前に入力した内容を覚えておく必要があります。 つまり、ボットストレージを作成する必要があります。 データを埋めるロジックを説明するクラスを作成しました。



RegForm.cs
 public class RegForm { public string tg_id { get; set; } public string name { get; set; } public string age { get; set; } public string country { get; set; } public string city { get; set; } public string gender { get; set; } public string photo { get; set; } public string tg_username { get; set; } public string tg_chat_id { get; set; } public int stage; public RegForm(string id, string chat_id, string username) { stage = 1; tg_id = id; tg_username = username; } public (string, int) StageText(string id) { if (stage == 1) return ("  :", stage); if (stage == 2) return (" :", stage); if (stage == 3) return ("  :", stage); if (stage == 4) return ("  :", stage); if (stage == 5) return ("  :", stage); else return ("   :", stage); } public bool SetParam(string param) { if (stage == 1) name = param; if (stage == 2) age = param; if (stage == 3) country = param; if (stage == 4) city = param; if (stage == 5) gender = param; if (stage == 6) photo = param; stage++; return true; } }
      
      





このクラスでは、データ検証を実装できます。たとえば、テキストなどの形式で年齢を見逃さないでください。



また、メモリ自体はstatic Dictionary<string, RegForm> registrations = new Dictionary<string, RegForm>();



ボタンをクリックするだけで、新しいKeyValuePairを追加します。



ボットがクリックに応答する方法を知るために、 BotOnCallbackQueryReceived



を追加する必要があります



 var message = e.CallbackQuery; if (message.Data == "Registration") { RegForm form = new RegForm(message.From.Id.ToString(), message.Message.Chat.Id.ToString(), message.From.Username);//    registrations.Add(message.From.Id.ToString(), form);//   "",    telegram_id . var t = form.StageText(form.tg_id); // ,   ,     . Bot.SendTextMessageAsync(message.Message.Chat.Id, t.Item1);//  . return; }
      
      





同様に、受信したデータを処理して、フォームに入力してデータを保存できます。

  using (Context db = new Context()) { IMapper mapper = new MapperConfiguration(cfg => cfg.CreateMap<RegForm, User>()).CreateMapper(); if (db.user.Where(x => x.tg_id == message.From.Id.ToString()).Count() != 0) db.user.Update(mapper.Map<RegForm, tgbot_base.classes.user>(u)); else { db.user.Add(mapper.Map<RegForm, tgbot_base.classes.user>(u)); } db.SaveChanges(); }
      
      





ユーザーが既にプロファイルを持っている場合は、データを更新するだけです。



ユーザーの写真を保存しています
 if (message.Type == MessageType.Photo) { string file = Bot.GetFileAsync(message.Photo[message.Photo.Count() - 1].FileId).Result.FilePath; string filepath = message.From.Id + "." + file.Split('.').Last(); using (FileStream fileStream = new FileStream("C:\\images\\" + filepath, FileMode.OpenOrCreate, FileAccess.ReadWrite)) { var st = Bot.DownloadFileAsync(file).Result; st.Position = 0; st.CopyTo(fileStream); } u.SetParam("C:\\images\\" + filepath); }
      
      







他のプロファイルを表示



これを行うには、データベースからデータを取得してユーザーに送信するだけです。



これを行うには、データベースからデータを取得して便利な形式で返す簡単なメソッドを作成します。



 public static User GetRandom() { Stopwatch s = new Stopwatch(); s.Start(); User u; using (Context db = new Context()) { Random r = new Random(); int count = db.user.Count(); if (count > 1) count = count - 1; List<User> users = mapper.Map<List<tgbot_base.classes.user>, List<User>>(db.user.ToList()); u = users.ElementAt(r.Next(0, count)); } Console.WriteLine("[" + DateTime.Now + "] For finding " + s.ElapsedMilliseconds + " ms"); s = null; return u; }
      
      





次ボタンクリックハンドラー:



 if (message.Data == "Next") { if (searchForms.Count != 0) { searchForms.Remove(message.From.Id.ToString()); } IMapper mapper = new MapperConfiguration(cfg => cfg.CreateMap<RegForm, User>()).CreateMapper(); User user = BaseWorker.GetRandom(); SendAnket(user, message.Message.Chat.Id.ToString());//,     . return; }
      
      





おわりに



そのシンプルさのために、一般の人はボットが好きでした。



1日も経たないうちに、134人のユーザーがプロファイルを離れ、肯定的なフィードバックがありました。 そして、あまり広告がなければ、あまり得られていないサイト上の投稿は1つだけです。



ボットは長い間忘れられてきた老人であり、新しい命を見つけました。 多くのプロセスを実際に自動化するのに役立ち、インターネット上で仲間を探すことさえできます。 収益化で詰まっている出会い系サイトをバイパスします。



最後まで読んでくれてありがとう。



幸運を、楽しんで、黄色い雪を食べないでください。



All Articles