How to handle multiple users on Telegram bot in C#?
Asked Answered
E

3

5

I wrote a bot which asks your name and writes it on a photo and sends it to you and it works. But the problem is when there is more than one user on the bot
It doesn't work and crashes and I wanted to know how to separate users entries and outputs.(like each user who connects get a separated session because now everything happens in one session and it crashes) This is my code:

    void bot_OnMessage(object sender, Telegram.Bot.Args.MessageEventArgs e)
    {
     KeyboardButton[] btns = new KeyboardButton[1];
     btns[0] = new KeyboardButton("ساخت عکس");
        if(e.Message.Text=="ساخت عکس")
        {
            bot.SendTextMessageAsync(e.Message.From.Id, "نام خود را وارد کنید", Telegram.Bot.Types.Enums.ParseMode.Default, false, false, 0);
           // e.Message.Text = null;
            shart = 1;

        }
        else
        {
            if (shart == 0)
            {
                Telegram.Bot.Types.ReplyMarkups.ReplyKeyboardMarkup markup = new Telegram.Bot.Types.ReplyMarkups.ReplyKeyboardMarkup(btns);

                bot.SendTextMessageAsync(e.Message.From.Id, "برای شروع و ساخت عکس روی دکمه ساخت عکس کلید کنید", Telegram.Bot.Types.Enums.ParseMode.Default, false, false, 0, markup);
            }
            if (shart==1)
            {
                bot.StartReceiving();
                bot.OnMessage += bot_OnMessage1;
            }
        }
    }

    void bot_OnMessage1(object sender, Telegram.Bot.Args.MessageEventArgs a)
    {
        string watermarkText = a.Message.Text;

        //Get the file name.
        string fileName = "C:\\temp\\01.jpg";

        //Read the File into a Bitmap.
        using (Bitmap bmp = new Bitmap(fileName))
        {
            using (Graphics grp = Graphics.FromImage(bmp))
            {
                //Set the Color of the Watermark text.
                Brush brush = new SolidBrush(Color.White);

                //Set the Font and its size.
                Font font = new System.Drawing.Font("Arial", 50, FontStyle.Bold, GraphicsUnit.Pixel);

                //Determine the size of the Watermark text.
                SizeF textSize = new SizeF();
                textSize = grp.MeasureString(watermarkText, font);

                //Position the text and draw it on the image.
                Point position = new Point((bmp.Width - ((int)textSize.Width + 10)), (bmp.Height - ((int)textSize.Height + 10)));
                grp.DrawString(watermarkText, font, brush, position);
                bmp.Save("c:\\temp\\postpic.jpg", ImageFormat.Png);

                using (FileStream fs = new FileStream("c:\\temp\\postpic.jpg", FileMode.Open))
                {

                    fs.CanTimeout.ToString();
                    FileToSend fileToSend = new FileToSend("postpic.jpg", fs);
                    //  var =   FileToSend fts = new FileToSend("postpic", fs);
                    var rep = bot.SendPhotoAsync(a.Message.From.Id, fileToSend, "این عکس را پست کنید").Result;

                }
            }
        }
    }
}
Evars answered 24/10, 2017 at 10:47 Comment(2)
which platform are you writing this on and where do the connections from from?Intimidate
You seem to be using hardcoded file names: "c:\\temp\\postpic.jpg" when writing the out image file. This will have issues during multiple users access. Instead generate the out file name using user name and timestamp something like string fileName = string.Format("c:\\temp\\postpic_{0}.jpg", DateTime.Now.ToString("ddMMyyyy-HHmmss"));Hibben
O
5

You are writing (and subsequently reading from) the very same file for each user:

mp.Save("c:\\temp\\postpic.jpg"

You need to have a unique filename for each user. Or better yet, don't use a file at all. You could probably just use a local memory stream without cluttering your disk with files at all.

Overgrow answered 24/10, 2017 at 10:52 Comment(1)
yes i know thats ok this code is for test but the problem is when someone is using the bot and sends a massage to bot e.Message.Text is 'x' and the bot is using 'x' to do things but then someone else comes and sends another message and then e.Message.Text changes to 'y' and this crashes the botEvars
S
2

The solution is not language dependent.

You should keep context for each user somewhere.

There are 2 ways to do this:

  1. Create DB record with key by chatID and have some field(s) to keep state. Read the record on every request.
  2. Use inline buttons and pass context in callback data.

It's up to you how you store context. For example https://github.com/strongo/bots-framework uses URL format like:

command_name1/command_name2?param1=value2&param2=value2

This allows you to implement wizard-like interfaces and keep user input in parameters.

For example this approach used during a debt record creation in https://t.me/DebtsTrackerBot

Serin answered 24/10, 2017 at 10:56 Comment(0)
A
0

Instead of handling a received message right away, try creating a "job" or "event" and handling it with some kind of worker/consumer in a separate thread/process. Message Queues can be useful here.

Example using MassTransit:

  1. Create an event model that contains the "job" details (chat ID, message ID, username, unique filename, etc)
  2. Create a consumer (an example of in-memory consumer creation and registration for DI could be found here)
  3. Implement the processing logic in the consumer
  4. Make your telegram listener class inherit from the BackgroundService and register it as a Hosted Service
  5. Map required data to your event model after receiving it from Telegram
  6. Publish it to the queue
  7. The event will be consumed and processed by your consumer

This way you can handle processing messages from multiple users, as MassTransit will provide a separate consumer for each event.

Aqualung answered 19/6, 2023 at 8:32 Comment(0)

© 2022 - 2025 — McMap. All rights reserved.