Ein weiterer Telegramm-Bot oder eine Dating-Bot-Implementierung

Mein Name ist Vlad, von Beruf bin ich ein Soldat, aber ich arbeite Teilzeit bei einem Unternehmen für Geschäftsautomatisierung, wo ich auf .net programmiere.

Kurzer Hintergrund


Zum Zeitpunkt der nächsten Konvergenz-Diskrepanz mit meiner ehemaligen (regulären) Braut sagte sie, dass sie aus Langeweile über einen Telegramm-Bot nach Männern für Dates suchte, die Fotos und Geolokalisierung senden und Sie Leute in der Nähe abholen konnten. Ich habe versprochen, dass ich etwas Ähnliches schreiben würde, wenn wir wieder weglaufen. Yara ist für dich.
Ich habe es sicher vergessen, aber zum Zeitpunkt des nächsten Müßiggangs habe ich die Website mit einem Cupcake auf grünem Hintergrund gescrollt , wo ich auf einen Abschnitt gestoßen bin, in dem Leute gerade einen Beitrag mit einem Foto gepostet, kurz über sich selbst geschrieben und Kontakte angegeben haben.

So kam die Idee auf, Ihren Bot zu schreiben, der den Leuten helfen würde, Freunde oder andere zu finden.

Herausforderung


Erstellen Sie einen Bot, in dem jeder, der chatten möchte, kurze Informationen über sich selbst veröffentlichen und warten kann, bis er ihm schreibt.



Vorbereitung auf die Arbeit


Wie man einen Bot über BotFather erstellt, kennt nicht nur denjenigen, der nicht interessiert ist, daher werde ich den Artikel nicht mit zusätzlichen Informationen füllen.

Speicherung von "Profilen"


Zunächst habe ich das ClassLibrary-Projekt erstellt, mit dem ich mit Daten arbeiten wollte.

Zuerst müssen Sie entscheiden, wie Benutzerdaten gespeichert werden sollen. Dazu müssen wir den Benutzer "beschreiben".

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; }// ,    } 

Für die Speicherung wurde die PostgreSQL-Datenbank ausgewählt, die auf einem Remote-Server bereitgestellt wurde.
Legen Sie zunächst das EntityFramework über NuGet fest. Es vereinfacht unrealistisch das Leben in der Arbeit mit der Datenbank.

Um zu arbeiten, benötigen Sie das Paket:

NpgSQL.EntityFrameworkCore.PostgreSQL

Und für Migrationen ist ein Paket erforderlich:

Microsoft.EntityFrameworkCore.Tools

Um die routinemäßige Erstellung der Tabelle nicht zu behandeln, erstellen wir einfach das Datenmodell selbst (unsere Klasse oben) und stellen die Verbindung zur Datenbank her.

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

Weiter führen wir Migration durch.

Führen Sie dazu in der Package Manager-Konsole die folgenden Befehle aus:
enable-migrations
Aktivieren Sie den Migrationsmechanismus
Add-migration * *
Erstellen Sie eine Migration
update-database
Aktualisieren der Datenbank

Jetzt werden in unserer Datenbank zwei Tabellen angezeigt: der Migrationsverlauf und die Benutzertabelle selbst.



Nachdem Sie das Problem des Speicherns von Daten und des Verbindens mit der Datenbank gelöst haben, können Sie mit dem Schreiben des Bot-Handlers selbst fortfahren.

Handler bot


Das Telegramm selbst bietet zwei Optionen zum Empfangen von Updates: Webhook oder ständiges Ziehen des Servers, um nach Updates zu suchen. Webhook hat viele Schwierigkeiten, daher ist es einfacher, nur nach Updates zu suchen.

Erhalten Sie Updates, verarbeiten Sie sie


Um kein Fahrrad zu erstellen (manchmal ist es nützlich), ist es einfacher, eine vorgefertigte Lösung zu verwenden: Telegram. Bot von MrRoundRobin ist eine ausgezeichnete, sehr praktische Bibliothek für die Arbeit mit Telegram.

Wir erstellen ein neues ConsoleApp-Projekt in der Lösung, in dem wir dieses Paket installieren.

 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(); } 

Daher haben wir nach Updates gesucht und unsere Fehlerbehandlungsroutinen installiert.
BotOnMessageReceived - ein Handler zum Empfangen "normaler" Nachrichten
BotOnCallbackQueryReceived - der Handler zum Drücken der Schaltflächen, die unter der Nachricht BotOnCallbackQueryReceived .

Der Fall ist klein, die Möglichkeit, einen Fragebogen zu hinterlassen und durch den Rest zu scrollen. Sie müssen dem Benutzer also zwei Schaltflächen senden: Registrierung und Weiter. Eine Schaltfläche stellt ein InlineKeyboardButton Objekt dar, und alle Schaltflächen müssen verpackt sein

 IEnumerable<IEnumerable<InlineKeyboardButton>> 

Wenn der Bot geöffnet wird, wird sofort eine Nachricht mit dem Text "/ start" an ihn gesendet. BotOnMessageReceived müssen wir diese Nachricht in BotOnMessageReceived und unsere Schaltflächen als Antwort senden.

 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; } 

Registrierung


Um sich zu registrieren, müssen Sie sich merken, was der Benutzer zuvor eingegeben hat. Das heißt, wir müssen einen Bot-Speicher erstellen. Ich habe gerade eine Klasse erstellt, in der ich die Logik des Füllens von Daten beschrieben habe.

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; } } 

In dieser Klasse können Sie die Datenvalidierung implementieren, z. B. das Alter in Form von Text usw. nicht verpassen.

Und der Speicher selbst ist das static Dictionary<string, RegForm> registrations = new Dictionary<string, RegForm>(); in die wir auf Knopfdruck ein neues KeyValuePair einfügen.

Damit der Bot auf den Klick reagieren kann, müssen Sie BotOnCallbackQueryReceived hinzufügen

 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; } 

Auf die gleiche Weise können Sie bei der Verarbeitung der empfangenen Daten das Formular ausfüllen und die Daten speichern.
  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(); } 

Wenn der Benutzer bereits ein Profil hat, aktualisieren Sie einfach die Daten.

Benutzerfoto speichern
 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); } 


Andere Profile anzeigen


Dazu müssen Sie nur Daten aus der Datenbank entnehmen und an den Benutzer senden.

Zu diesem Zweck schreiben wir eine einfache Methode, mit der Daten aus der Datenbank in einem geeigneten Format zurückgegeben werden:

 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; } 

Klick-Handler für die nächste Schaltfläche:

 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; } 

Fazit


Trotz seiner Einfachheit mochte die Öffentlichkeit den Bot.

In weniger als einem Tag haben 134 Benutzer ihr Profil verlassen, es gibt positive Rückmeldungen. Und ohne spezielle Werbung - es gibt nur einen Beitrag auf der Website, der keine besonderen Pluspunkte erzielt hat.

Bots sind eine lange vergessene alte, die ein neues Leben gefunden hat. Sie helfen dabei, viele Prozesse wirklich zu automatisieren und suchen sogar im Internet nach einem Partner. Monetarisierte Dating-Sites umgehen.

Vielen Dank für das Lesen bis zum Ende.

Viel Glück, viel Spaß, iss keinen gelben Schnee.

Source: https://habr.com/ru/post/de430314/


All Articles