另一个电报机器人或约会机器人实现

我的名字叫弗拉德(Vlad),从职业上来说我是一名军人,但是我在一家商业自动化公司兼职,该公司在.net上进行编程。

简要背景


在与我的前任(常规)新娘发生下一次婚约时,她说,出于无聊,她正在通过电报机器人寻找约会对象,该机器人可以发送照片和地理位置,并接您到附近的人那里。 我保证如果再次分散我会写类似的东西。 亚拉适合你。
我安全地忘记了这一点,但是在下一次闲置时,我在绿色背景用纸杯蛋糕滚动了网站,在那儿我碰到了一个部分,人们刚刚张贴了一张带有照片的帖子,简要介绍了自己并指出了联系方式。

因此提出了编写您的机器人的想法,这将帮助人们找到朋友或其他任何人。

挑战赛


创建一个机器人,任何想聊天的人都可以在其中发布自己的简短信息,然后等他们写信给他。



准备工作


如何通过BotFather创建一个bot并不只知道一个不感兴趣的人,因此我不会在本文中添加其他信息。

存储“配置文件”


最初,我创建了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
更新数据库

现在,在我们的数据库中将出现两个表:迁移历史记录和用户表本身。



解决了存储数据并连接到数据库的问题之后,您可以继续编写机器人处理程序本身。

处理程序机器人


Telegram本身提供了两种接收更新的选项: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按下消息下方显示的按钮的处理程序。

案件很小,可以留下调查表,还可以滚动浏览其余内容。 因此,您需要向用户发送两个按钮:注册和下一步。 一个按钮代表一个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; } 

结论


尽管简单,但公众都喜欢该机器人。

在不到一天的时间内,有134位用户离开了他们的个人资料,得到了积极的反馈。 而且,如果没有特殊的广告-网站上只有一个帖子,得分没有特别高。

机器人是一个久已被遗忘的旧时代,已经找到了新生命。 它们有助于真正实现许多流程的自动化,甚至可以在Internet上寻找伴侣。 绕过获利的约会网站。

感谢您阅读到最后。

祝你好运,玩得开心,不要吃黄雪。

Source: https://habr.com/ru/post/zh-CN430314/


All Articles