skip to Main Content

I’m writing telegram-bot using Go (go-telegram-bot-api). It constantly parses a website and notifies about changes (every minute). Today I added simple keyboard and now can’t make them work together.

The problem is that webpage parsing is in the infinite loop and program when it enters the loop ignores updates coming from the “client”.

I’ve tried putting everything in a single loop, changing orders, etc. Maybe there is another or proper way of doing this?

Sample code:

    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

Answers


  1. Chosen as BEST ANSWER

    Thanks to kimgrey I dug a bit into goroutines and channels. Infinite loop is in a separate goroutine and escaping is done through unbuffered channel (check "game changer" comments in the sample code). Now I can enter and escape infinite loop when needed. Here's how I solved my problem:

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

  2. If I understood everything right you should start parsing loop inside of separated goroutine so updates cycle will keep working.

    Try to do something like this:

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

    Writing from the top of my brain, so do not expect it to compile from the first attempt, but demonstrates the idea. Please, check out following links for more information regarding Ticker and contexts with cancellation: click, click.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search