gitee.com/liuxuezhan/go-micro-v1.18.0@v1.0.0/agent/input/slack/conn.go (about) 1 package slack 2 3 import ( 4 "errors" 5 "fmt" 6 "strings" 7 "sync" 8 "time" 9 10 "gitee.com/liuxuezhan/go-micro-v1.18.0/agent/input" 11 "github.com/nlopes/slack" 12 ) 13 14 // Satisfies the input.Conn interface 15 type slackConn struct { 16 auth *slack.AuthTestResponse 17 rtm *slack.RTM 18 exit chan bool 19 20 sync.Mutex 21 names map[string]string 22 } 23 24 func (s *slackConn) run() { 25 // func retrieves user names and maps to IDs 26 setNames := func() { 27 names := make(map[string]string) 28 users, err := s.rtm.Client.GetUsers() 29 if err != nil { 30 return 31 } 32 33 for _, user := range users { 34 names[user.ID] = user.Name 35 } 36 37 s.Lock() 38 s.names = names 39 s.Unlock() 40 } 41 42 setNames() 43 44 t := time.NewTicker(time.Minute) 45 defer t.Stop() 46 47 for { 48 select { 49 case <-s.exit: 50 return 51 case <-t.C: 52 setNames() 53 } 54 } 55 } 56 57 func (s *slackConn) getName(id string) string { 58 s.Lock() 59 name := s.names[id] 60 s.Unlock() 61 return name 62 } 63 64 func (s *slackConn) Close() error { 65 select { 66 case <-s.exit: 67 return nil 68 default: 69 close(s.exit) 70 } 71 return nil 72 } 73 74 func (s *slackConn) Recv(event *input.Event) error { 75 if event == nil { 76 return errors.New("event cannot be nil") 77 } 78 79 for { 80 select { 81 case <-s.exit: 82 return errors.New("connection closed") 83 case e := <-s.rtm.IncomingEvents: 84 switch ev := e.Data.(type) { 85 case *slack.MessageEvent: 86 // only accept type message 87 if ev.Type != "message" { 88 continue 89 } 90 91 // only accept DMs or messages to me 92 switch { 93 case strings.HasPrefix(ev.Channel, "D"): 94 case strings.HasPrefix(ev.Text, s.auth.User): 95 case strings.HasPrefix(ev.Text, fmt.Sprintf("<@%s>", s.auth.UserID)): 96 default: 97 continue 98 } 99 100 // Strip username from text 101 switch { 102 case strings.HasPrefix(ev.Text, s.auth.User): 103 args := strings.Split(ev.Text, " ")[1:] 104 ev.Text = strings.Join(args, " ") 105 event.To = s.auth.User 106 case strings.HasPrefix(ev.Text, fmt.Sprintf("<@%s>", s.auth.UserID)): 107 args := strings.Split(ev.Text, " ")[1:] 108 ev.Text = strings.Join(args, " ") 109 event.To = s.auth.UserID 110 } 111 112 if event.Meta == nil { 113 event.Meta = make(map[string]interface{}) 114 } 115 116 // fill in the blanks 117 event.From = ev.Channel + ":" + ev.User 118 event.Type = input.TextEvent 119 event.Data = []byte(ev.Text) 120 event.Meta["reply"] = ev 121 return nil 122 case *slack.InvalidAuthEvent: 123 return errors.New("invalid credentials") 124 } 125 } 126 } 127 } 128 129 func (s *slackConn) Send(event *input.Event) error { 130 var channel, message, name string 131 132 if len(event.To) == 0 { 133 return errors.New("require Event.To") 134 } 135 136 parts := strings.Split(event.To, ":") 137 138 if len(parts) == 2 { 139 channel = parts[0] 140 name = s.getName(parts[1]) 141 // try using reply meta 142 } else if ev, ok := event.Meta["reply"]; ok { 143 channel = ev.(*slack.MessageEvent).Channel 144 name = s.getName(ev.(*slack.MessageEvent).User) 145 } 146 147 // don't know where to send the message 148 if len(channel) == 0 { 149 return errors.New("could not determine who message is to") 150 } 151 152 if len(name) == 0 || strings.HasPrefix(channel, "D") { 153 message = string(event.Data) 154 } else { 155 message = fmt.Sprintf("@%s: %s", name, string(event.Data)) 156 } 157 158 s.rtm.SendMessage(s.rtm.NewOutgoingMessage(message, channel)) 159 return nil 160 }