Esempio n. 1
0
func main() {
	c := client.NewClient("testbot", "testuser", "Test thing")

	c.AddCallback(client.OnMessage, func(c *client.IrcClient, command *parser.IrcMessage) {
		fmt.Printf("In CONNECTED callback: %v\n", command)
	})

	c.AddCallback(client.OnConnected, func(c *client.IrcClient, command *parser.IrcMessage) {
		fmt.Printf("In CONNECTED callback: %v\n", command)
	})

	c.Join("#gobo")

	go c.Run("irc.chatspike.net:6667")

	for {
		select {
		case command := <-c.CommandChannel:
			c.ProcessCallbacks(command)
		}
	}
}
Esempio n. 2
0
func main() {
	// TODO: move all env var checks here.
	if len(gerritChannel) == 0 {
		panic("Must provide environment variable GERRIT_CHANNEL")
	}

	c := client.NewClient("qt_gerrit", "qt_gerrit", "Qt IRC Bot")

	c.AddCallback(client.OnMessage, func(c *client.IrcClient, command *parser.IrcMessage) {
		directRegex := regexp.MustCompile(`^([^ ]+[,:] )`)
		directTo := directRegex.FindString(command.Parameters[1]) // was this directed at someone?
		if len(directTo) == 0 {
			directTo = command.Prefix.Nick + ": " // if not, default to sender of the message
		}

		br := regexp.MustCompile(`\b(Q[A-Z]+-[0-9]+)\b`)
		bugs := br.FindAllString(command.Parameters[1], -1)

		go func() {
			hclient := http.Client{
				Timeout: time.Duration(4 * time.Second),
			}

			for _, bugId := range bugs {
				res, err := hclient.Get("https://bugreports.qt.io/rest/api/2/issue/" + bugId)
				if err != nil {
					c.WriteMessage(command.Parameters[0], fmt.Sprintf("Error retrieving bug %s (while fetching HTTP): %s", bugId, err.Error()))
					continue
				}

				jsonBlob, err := ioutil.ReadAll(res.Body)
				res.Body.Close()
				if err != nil {
					c.WriteMessage(command.Parameters[0], fmt.Sprintf("Error retrieving bug %s (while reading response): %s", bugId, err.Error()))
					continue
				}

				var bug JiraBug
				err = json.Unmarshal(jsonBlob, &bug)
				if err != nil {
					c.WriteMessage(command.Parameters[0], fmt.Sprintf("Error retrieving bug %s (while parsing JSON): %s", bugId, err.Error()))
					continue
				}

				if len(bug.ErrorMessages) > 0 {
					c.WriteMessage(command.Parameters[0], fmt.Sprintf("Error retrieving bug %s: %s", bugId, bug.ErrorMessages[0]))
					continue
				}

				if len(bug.Fields.Summary) == 0 {
					c.WriteMessage(command.Parameters[0], fmt.Sprintf("Error retrieving bug %s: malformed reply", bugId))
					continue
				}

				c.WriteMessage(command.Parameters[0], fmt.Sprintf("%s%s - https://bugreports.qt.io/browse/%s (%s)",
					directTo,
					bug.Fields.Summary,
					bugId,
					bug.Fields.Status.Name))
			}
		}()

		cr := regexp.MustCompile(`(I[0-9a-f]{40})`)
		changes := cr.FindAllString(command.Parameters[1], -1)

		cr2 := regexp.MustCompile(`https:\/\/codereview\.qt\-project\.org\/\#\/c\/([0-9]+)\/`)
		changes2 := cr2.FindAllStringSubmatch(command.Parameters[1], -1)

		for _, change := range changes2 {
			changes = append(changes, change[1])
		}

		go func() {
			hclient := http.Client{
				Timeout: time.Duration(4 * time.Second),
			}

			for _, changeId := range changes {
				res, err := hclient.Get("https://codereview.qt-project.org/changes/" + changeId)
				if err != nil {
					c.WriteMessage(command.Parameters[0], fmt.Sprintf("Error retrieving change %s (while fetching HTTP): %s", changeId, err.Error()))
					continue
				}

				jsonBlob, err := ioutil.ReadAll(res.Body)
				res.Body.Close()
				if err != nil {
					c.WriteMessage(command.Parameters[0], fmt.Sprintf("Error retrieving change %s (while reading response): %s", changeId, err.Error()))
					continue
				}

				// From the Gerrit documentation:
				// To prevent against Cross Site Script Inclusion (XSSI) attacks, the JSON
				// response body starts with a magic prefix line that must be stripped before
				// feeding the rest of the response body to a JSON parser:
				//    )]}'
				//    [ ... valid JSON ... ]
				if !bytes.HasPrefix(jsonBlob, []byte(")]}'\n")) {
					c.WriteMessage(command.Parameters[0], fmt.Sprintf("Error retrieving change %s (couldn't find Gerrit magic)", changeId))
					continue
				}

				// strip off the gerrit magic
				jsonBlob = jsonBlob[5:]

				var change GerritChange
				err = json.Unmarshal(jsonBlob, &change)
				if err != nil {
					c.WriteMessage(command.Parameters[0], fmt.Sprintf("Error retrieving change %s (while parsing JSON): %s", changeId, err.Error()))
					continue
				}

				if len(change.Id) == 0 {
					c.WriteMessage(command.Parameters[0], fmt.Sprintf("Error retrieving change %s: malformed reply", changeId))
					continue
				}

				c.WriteMessage(command.Parameters[0], fmt.Sprintf("%s[%s/%s] %s from %s - %s (%s)",
					directTo, change.Project, change.Branch, change.Subject, change.Owner.Name,
					fmt.Sprintf("https://codereview.qt-project.org/%d", change.Number), change.Status))
			}
		}()
	})

	c.AddCallback(client.OnConnected, func(c *client.IrcClient, command *parser.IrcMessage) {
		fmt.Printf("In CONNECTED callback: %v\n", command)

		nsUser := os.Getenv("NICKSERV_USER")
		if len(nsUser) == 0 {
			panic("Must provide environment variable NICKSERV_USER")
		}

		nsPass := os.Getenv("NICKSERV_PASS")
		if len(nsPass) == 0 {
			panic("Must provide environment variable NICKSERV_PASS")
		}

		c.WriteLine(fmt.Sprintf("NS IDENTIFY %s %s", nsUser, nsPass))
	})

	ircServer := os.Getenv("IRC_SERVER")
	if len(ircServer) == 0 {
		panic("Must provide environment variable IRC_SERVER")
	}

	ircChannels := os.Getenv("IRC_CHANNELS")
	if len(ircChannels) == 0 {
		panic("Must provide environment variable IRC_CHANNELS")
	}

	c.Join(ircChannels)
	go c.Run(ircServer)

	gc := NewClient()
	go gc.Run()

	for {
		select {
		case command := <-c.CommandChannel:
			c.ProcessCallbacks(command)
		case msg := <-gc.MessageChannel:
			if msg.Type == "comment-added" {
				handleCommentAdded(c, msg)
			} else if msg.Type == "patchset-created" {
				handlePatchSetCreated(c, msg)
			} else if msg.Type == "change-merged" {
				handleChangeMerged(c, msg)
			} else if msg.Type == "merge-failed" {
				handleMergeFailed(c, msg)
			} else if msg.Type == "reviewer-added" {
				// ignore, too spammy
			} else if msg.Type == "ref-updated" {
				// ignore, too spammy
			}
			println(fmt.Sprintf("Gerrit: Message: %s\n", msg.OriginalJson))
		}
	}
}