Как запустить бесконечный l oop и получать обновления в боте Telegram - PullRequest
1 голос
/ 28 мая 2020

Я пишу телеграм-бота, используя Go (go -telegram-bot-api ). Он постоянно анализирует сайт и уведомляет об изменениях (каждую минуту). Сегодня я добавил простую клавиатуру, и теперь не могу заставить их работать вместе.

Проблема в том, что синтаксический анализ веб-страницы находится в бесконечном l oop и программа, когда она входит в l oop, игнорирует обновления, поступающие из «клиент».

Я пробовал помещать все в один l oop, меняя порядок и т.д. c. Может, есть другой или подходящий способ сделать это?

Пример кода:

    u := tgbotapi.NewUpdate(0)
    u.Timeout = 60

    updates, err := bot.GetUpdatesChan(u)

    for update := range updates {
            if update.Message != nil {

                  switch update.Message.Text {
                        case "Show Keyboard":
                              Keyboard is sent
                        case "OptionsForParsing":
                              options.applied
                        case "StartParsing":
                              search bool = true
                        case "StopParsing":
                              search bool = false
                   }
            }

            if search == true{  
            for{
                 time.Sleep(1 * time.Minute)
                 AreThereChanges?()
                 if yes{
                         msg := tgbotapi.NewMessage(update.Message.Chat.ID, "help please")
                         bot.Send(msg)
                 }
            }}
     }

Ответы [ 2 ]

1 голос
/ 28 мая 2020

Если я все правильно понял, вам следует начать парсить l oop внутри отдельной горутины, чтобы цикл обновлений продолжал работать.

Попробуйте сделать что-то вроде этого:

// you can use cancel to stop running parsing goroutine
ctx, cancel := context.WithCancel(context.Background())

go func() {
  ticker := time.NewTicker(5 * time.Second)
  defer ticker.Stop()

  for {
    select {
      case <-ctx.Done():
        return
      case <-ticker.C:
        AreThereChanges?()
        if yes {
          msg := tgbotapi.NewMessage(update.Message.Chat.ID, "help please")
          bot.Send(msg)
        }
      }
  }
}()

Пишу от всей души, поэтому не ожидайте, что он скомпилируется с первой попытки, но демонстрирует идею. Пожалуйста, проверьте следующие ссылки для получения дополнительной информации о тикере и контекстах с отменой: нажмите , нажмите .

0 голосов
/ 29 мая 2020

Спасибо kimgrey Немного покопался в горутинах и каналах. Бесконечный l oop находится в отдельной горутине, и экранирование выполняется через небуферизованный канал (проверьте комментарии «game changer» в примере кода). Теперь я могу войти и выйти из бесконечного l oop, когда это необходимо. Вот как я решил свою проблему:

u := tgbotapi.NewUpdate(0)
u.Timeout = 60

updates, err := bot.GetUpdatesChan(u)
done := make(chan bool)                       //game changer
for update := range updates {
        if update.Message != nil {

              switch update.Message.Text {
                    case "Show Keyboard":
                          Keyboard is sent
                    case "OptionsForParsing":
                          options.applied
                    case "StartParsing":
                          search bool = true
                    case "StopParsing":
                          search bool = false
                          done<-true                 //game changer
               }

            go func() {
                ticker := time.NewTicker(time.Minute)
                defer ticker.Stop()
                if search{
                for {
                    select {
                        case <-done:                //game changer
                            return
                        case <-ticker.C:
                            AnyChanges?()
                    }
                }}              
            }()
        }
 }
...