gitee.com/liuxuezhan/go-micro-v1.18.0@v1.0.0/agent/input/telegram/conn.go (about)

     1  package telegram
     2  
     3  import (
     4  	"errors"
     5  	"strings"
     6  	"sync"
     7  
     8  	"github.com/forestgiant/sliceutil"
     9  	"gitee.com/liuxuezhan/go-micro-v1.18.0/agent/input"
    10  	"gitee.com/liuxuezhan/go-micro-v1.18.0/util/log"
    11  	tgbotapi "gopkg.in/telegram-bot-api.v4"
    12  )
    13  
    14  type telegramConn struct {
    15  	input *telegramInput
    16  
    17  	recv <-chan tgbotapi.Update
    18  	exit chan bool
    19  
    20  	syncCond *sync.Cond
    21  	mutex    sync.Mutex
    22  }
    23  
    24  func newConn(input *telegramInput) (*telegramConn, error) {
    25  	conn := &telegramConn{
    26  		input: input,
    27  	}
    28  
    29  	conn.syncCond = sync.NewCond(&conn.mutex)
    30  
    31  	go conn.run()
    32  
    33  	return conn, nil
    34  }
    35  
    36  func (tc *telegramConn) run() {
    37  	u := tgbotapi.NewUpdate(0)
    38  	u.Timeout = 60
    39  	updates, err := tc.input.api.GetUpdatesChan(u)
    40  	if err != nil {
    41  		return
    42  	}
    43  
    44  	tc.recv = updates
    45  	tc.syncCond.Signal()
    46  
    47  	select {
    48  	case <-tc.exit:
    49  		return
    50  	}
    51  }
    52  
    53  func (tc *telegramConn) Close() error {
    54  	return nil
    55  }
    56  
    57  func (tc *telegramConn) Recv(event *input.Event) error {
    58  	if event == nil {
    59  		return errors.New("event cannot be nil")
    60  	}
    61  
    62  	for {
    63  		if tc.recv == nil {
    64  			tc.mutex.Lock()
    65  			tc.syncCond.Wait()
    66  		}
    67  
    68  		update := <-tc.recv
    69  
    70  		if update.Message == nil || (len(tc.input.whitelist) > 0 && !sliceutil.Contains(tc.input.whitelist, update.Message.From.UserName)) {
    71  			continue
    72  		}
    73  
    74  		if event.Meta == nil {
    75  			event.Meta = make(map[string]interface{})
    76  		}
    77  
    78  		event.Type = input.TextEvent
    79  		event.From = update.Message.From.UserName
    80  		event.To = tc.input.api.Self.UserName
    81  		event.Data = []byte(update.Message.Text)
    82  		event.Meta["chatId"] = update.Message.Chat.ID
    83  		event.Meta["chatType"] = update.Message.Chat.Type
    84  		event.Meta["messageId"] = update.Message.MessageID
    85  
    86  		return nil
    87  	}
    88  }
    89  
    90  func (tc *telegramConn) Send(event *input.Event) error {
    91  	messageText := strings.TrimSpace(string(event.Data))
    92  
    93  	chatId := event.Meta["chatId"].(int64)
    94  	chatType := ChatType(event.Meta["chatType"].(string))
    95  
    96  	msgConfig := tgbotapi.NewMessage(chatId, messageText)
    97  	msgConfig.ParseMode = tgbotapi.ModeHTML
    98  
    99  	if sliceutil.Contains([]ChatType{Group, Supergroup}, chatType) {
   100  		msgConfig.ReplyToMessageID = event.Meta["messageId"].(int)
   101  	}
   102  
   103  	_, err := tc.input.api.Send(msgConfig)
   104  
   105  	if err != nil {
   106  		// probably it could be because of nested HTML tags -- telegram doesn't allow nested tags
   107  		log.Log("[telegram][Send] error:", err)
   108  		msgConfig.Text = "This bot couldn't send the response (Internal error)"
   109  		tc.input.api.Send(msgConfig)
   110  	}
   111  
   112  	return nil
   113  }