Здравствуйте, форумчане)) У меня такой вопрос: написал бота для telegram, который извлекает определенную информацию из фотографии и заносит ее в базу данных. Далее код, после- пояснение.
private static async void BotOnPhotoReceived(object sender, MessageEventArgs messageEventArgs)
{
var message = messageEventArgs.Message;
try
{
if (message == null || message.Type != MessageType.PhotoMessage)
return;
var fileId = message.Photo[message.Photo.Length - 1].FileId;
var file = await Bot.GetFileAsync(fileId);
var stream = file.FileStream;
using (Stream output = new FileStream($"../../Photo/img{message.Chat.Id}{fileId}.jpg", FileMode.Append))
{
byte[] buffer = new byte[32 * 1024];
int read;
while ((read = stream.Read(buffer, 0, buffer.Length)) > 0)
{
output.Write(buffer, 0, read);
}
}
await Bot.SendChatActionAsync(message.Chat.Id, ChatAction.Typing);
var FileUrl = @"D:\\128.png";
using (var streamm = System.IO.File.Open(FileUrl, FileMode.Open))
{
FileToSend fts = new FileToSend();
fts.Content = streamm;
fts.Filename = FileUrl.Split('\\').Last();
var test = await Bot.SendStickerAsync(message.Chat.Id, fts);
}
string imagePath = $"../../Photo/img{message.Chat.Id}{fileId}.jpg";
TextDetection newTD = new TextDetection();
string text = newTD.photo2string(imagePath);
string result = ParseString(text);
Console.WriteLine(Convert.ToDouble(result));
double result1 = Math.Abs(Convert.ToDouble(result));
DataBaseCon.InsertUser((int)message.Chat.Id, message.Chat.FirstName);
DataBaseCon.InsertAmount((int)message.Chat.Id, result1);
var keyboard = new Telegram.Bot.Types.ReplyMarkups.InlineKeyboardMarkup();
keyboard.InlineKeyboard = new Telegram.Bot.Types.InlineKeyboardButtons.InlineKeyboardButton[][]
{
new Telegram.Bot.Types.InlineKeyboardButtons.InlineKeyboardButton[]
{
new KeyboardButton("Продукты питания"),
new KeyboardButton("Техника"),
},
new Telegram.Bot.Types.InlineKeyboardButtons.InlineKeyboardButton[]
{
new KeyboardButton("Транспорт"),
new KeyboardButton("Мобильная связь")
},
new Telegram.Bot.Types.InlineKeyboardButtons.InlineKeyboardButton[]
{
new KeyboardButton("Другое")
},
};
await Bot.SendTextMessageAsync(message.Chat.Id, "Выберите категорию товара, который вы приобрели", replyMarkup: keyboard);
await Task.Delay(1000);
bool flag = true;
Bot.OnCallbackQuery += (object sc, CallbackQueryEventArgs ev) =>
{
Task.Delay(5000);
if (ev.CallbackQuery.Data == "Транспорт" && flag)
{
DataBaseCon.InsertCategory((int)message.Chat.Id, "Транспорт");
Bot.AnswerCallbackQueryAsync(ev.CallbackQuery.Id, "Расходы на транспорт зафиксированы");
Bot.AnswerCallbackQueryAsync(ev.CallbackQuery.Id);
}
else
if (ev.CallbackQuery.Data == "Мобильная связь" && flag)
{
DataBaseCon.InsertCategory((int)message.Chat.Id, "Мобильная связь");
Bot.AnswerCallbackQueryAsync(ev.CallbackQuery.Id, "Расходы на мобильную связь зафиксированы");
Bot.AnswerCallbackQueryAsync(ev.CallbackQuery.Id);
}
else
if (ev.CallbackQuery.Data == "Продукты питания" && flag)
{
DataBaseCon.InsertCategory((int)message.Chat.Id, "Продукты питания");
Bot.AnswerCallbackQueryAsync(ev.CallbackQuery.Id, "Расходы на продукты питания зафиксированы");
Bot.AnswerCallbackQueryAsync(ev.CallbackQuery.Id);
}
else
if (ev.CallbackQuery.Data == "Техника" && flag)
{
DataBaseCon.InsertCategory((int)message.Chat.Id, "Техника");
Bot.AnswerCallbackQueryAsync(ev.CallbackQuery.Id, "Расходы на технику зафиксированы");
Bot.AnswerCallbackQueryAsync(ev.CallbackQuery.Id);
}
else
if (ev.CallbackQuery.Data == "Другое" && flag)
{
DataBaseCon.InsertCategory((int)message.Chat.Id, "Другое");
Bot.AnswerCallbackQueryAsync(ev.CallbackQuery.Id, "Расходы на другую категорию зафиксированы");
Bot.AnswerCallbackQueryAsync(ev.CallbackQuery.Id);
}
flag = !flag;
};
if (flag)
{
await Bot.SendTextMessageAsync(message.Chat.Id, WalletKeeper.Constants.IT_IS_DONE);
}
}
catch (Exception e){
await Bot.SendTextMessageAsync(message.Chat.Id, WalletKeeper.Constants.FAILED);
}
}
Как видите, я тут использую кнопки и с ними проблема(вернее, с их обработкой). Я загружаю фотографию, после чего выбираю, в какую категорию внести данные(в БД) "Транспорт", "Мобильная связь" e.t.c. и у меня возникает следующая проблема: допустим, загружаю фото в первый раз и выбираю категорию- все хорошо, во второй раз- тоже информация вводится корректно, а в третий раз у меня одни данные вносятся в БД дважды, уже всю голову сломал(и дебаггер тоже), но баг так и не нашел. Предположительно, проблемы из-за неправильного применения async & await. На всякий случай выложу еще код
static void Main(string[] args)
{
Bot.OnMessage += BotOnMessageReceived;
Bot.OnMessage += BotOnPhotoReceived;
var me = Bot.GetMeAsync().Result;
Console.Title = me.Username;
Bot.StartReceiving();
Console.ReadLine();
Bot.StopReceiving();
}
Заранее спасибо))
Ваша ошибка в том, что внутри обработчика BotOnPhotoReceived
вы каждый раз заново подписываетесь на OnCallbackQuery
. Таким образом, с каждой новой полученной картинкой, у вас на собитие OnCallbackQuery
вешается всё больше и больше одинаковых обработчиков. При наступлении события, они все срабатывают поочередно.
Просто вынесите эту часть кода наружу из BotOnPhotoReceived
.
Bot.OnCallbackQuery += (object sc, CallbackQueryEventArgs ev) =>
{
//...
}
Сделайте аналогично тому, как вы подписываетесь на BotOnMessageReceived
и BotOnPhotoReceived
. То есть весь код из лямбда-выражения поместите в обычный метод, и подпишите его на событие один раз в начале программы. В методе BotOnPhotoReceived
вообще не трогайте Bot.OnCallbackQuery
(уберите оттуда все упоминания). Вот приблизительный вид того, что должно получиться:
static void Main(string[] args)
{
// ...
Bot.OnCallbackQuery += BotOnCallbackQuery;
// ...
}
private static void BotOnCallbackQuery(object sender, CallbackQueryEventArgs ev)
{
if (ev.CallbackQuery.Data == "Транспорт")
{
DataBaseCon.InsertCategory((int)message.Chat.Id, "Транспорт");
Bot.AnswerCallbackQueryAsync(ev.CallbackQuery.Id, "Расходы на транспорт зафиксированы");
Bot.AnswerCallbackQueryAsync(ev.CallbackQuery.Id);
}
else if (ev.CallbackQuery.Data == "Мобильная связь")
{
DataBaseCon.InsertCategory((int)message.Chat.Id, "Мобильная связь");
Bot.AnswerCallbackQueryAsync(ev.CallbackQuery.Id, "Расходы на мобильную связь зафиксированы");
Bot.AnswerCallbackQueryAsync(ev.CallbackQuery.Id);
}
else if (ev.CallbackQuery.Data == "Продукты питания")
{
DataBaseCon.InsertCategory((int)message.Chat.Id, "Продукты питания");
Bot.AnswerCallbackQueryAsync(ev.CallbackQuery.Id, "Расходы на продукты питания зафиксированы");
Bot.AnswerCallbackQueryAsync(ev.CallbackQuery.Id);
}
else if (ev.CallbackQuery.Data == "Техника")
{
DataBaseCon.InsertCategory((int)message.Chat.Id, "Техника");
Bot.AnswerCallbackQueryAsync(ev.CallbackQuery.Id, "Расходы на технику зафиксированы");
Bot.AnswerCallbackQueryAsync(ev.CallbackQuery.Id);
}
else if (ev.CallbackQuery.Data == "Другое")
{
DataBaseCon.InsertCategory((int)message.Chat.Id, "Другое");
Bot.AnswerCallbackQueryAsync(ev.CallbackQuery.Id, "Расходы на другую категорию зафиксированы");
Bot.AnswerCallbackQueryAsync(ev.CallbackQuery.Id);
}
}
(Это не готовое решение, а просто пример. Как видите, я убрал из кода переменную flag
т.к. не понимаю для чего она у вас служит.)
Виртуальный выделенный сервер (VDS) становится отличным выбором
Всем доброго времени суток! Недавно написал небольшой (я правда не знаю, как это классифицировать) на js