Skip to content

Commit

Permalink
feat(yolo): smart slack channel notification, avoiding flood (#yololo…
Browse files Browse the repository at this point in the history
…gs, #yolodebug)
  • Loading branch information
moul committed Feb 6, 2019
1 parent 7a18ab8 commit 08b43de
Showing 1 changed file with 47 additions and 20 deletions.
67 changes: 47 additions & 20 deletions server/handler.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import (
"sort"
"strconv"
"strings"
"sync"
"time"

slack "github.com/ashwanthkumar/slack-go-webhook"
Expand All @@ -32,9 +33,13 @@ const (
SLACK_WEBHOOK_URL = "https://hooks.slack.com/services/T2AJ2MM5Z/BFX8ZASKW/***REMOVED***"
)

var reIPA = regexp.MustCompile("/([^/]+).ipa$")
var reAPK = regexp.MustCompile("/([^/]+).apk$")
var reVersion = regexp.MustCompile("/version$")
var (
reIPA = regexp.MustCompile("/([^/]+).ipa$")
reAPK = regexp.MustCompile("/([^/]+).apk$")
reVersion = regexp.MustCompile("/version$")
slackFloodMap = map[string]time.Time{}
slackFloodMutex = sync.Mutex{}
)

func (s *Server) Build(c echo.Context) error {
id := c.Param("build_id")
Expand Down Expand Up @@ -93,39 +98,61 @@ func (s *Server) getVersion(arts []*circleci.Artifact, kind string) (string, err
return "", fmt.Errorf("no version found")
}

func (s *Server) sendUserActionToSlack(c echo.Context, action string, color string, channel string) {
if s.NoSlack {
return
}
func userProfileFromContext(c echo.Context) (map[string]interface{}, error) {
sessAuth, err := session.Get(authSessionCookieName, c)
if err != nil {
c.Logger().Warn("failed to parse cookie:", err.Error())
//c.Redirect(http.StatusTemporaryRedirect, "/oauth/logout")
return nil, err
}
if sessAuth != nil && sessAuth.Values != nil && sessAuth.Values["profile"] != nil {
return sessAuth.Values["profile"].(map[string]interface{}), nil
}
return nil, nil
}

func (s *Server) sendUserActionToSlack(c echo.Context, action, color, channel, floodChannel string) {
if s.NoSlack {
return
}

profile, err := userProfileFromContext(c)
attachment := slack.Attachment{}
auth := c.RealIP()
username := fmt.Sprintf("anonymous (%s)", c.RealIP())
if sessAuth != nil && sessAuth.Values != nil && sessAuth.Values["profile"] != nil {
profile := sessAuth.Values["profile"].(map[string]interface{})

username := "anonymous"
if err != nil {
username = err.Error()
}
if profile != nil {
username = profile["name"].(string)
if profile["picture"] != nil {
profilePicture := profile["picture"].(string)
attachment.ThumbnailUrl = &profilePicture
}
auth = fmt.Sprintf("realip=%q nickname=%q sub=%q", c.RealIP(), profile["nickname"].(string), profile["sub"].(string))
username = profile["name"].(string)
}
//username := fmt.Sprintf("%s - %s (%s)", profile["nickname"].(string), profile["name"].(string), profile["sub"].(string))

username += fmt.Sprintf(" (%s)", c.RealIP())
//attachment.AddField(slack.Field{Title: "action", Value: action, Short: true})
//attachment.AddField(slack.Field{Title: "author", Value: username, Short: true})
//attachment.AddField(slack.Field{Title: "ip", Value: c.RealIP(), Short: true})
//attachment.AddField(slack.Field{Title: "path", Value: c.Path(), Short: true})
//attachment.AddField(slack.Field{Title: "groups", Value: strings.Join(profile["groups"].([]string), ","), Short: true})
attachment.AddField(slack.Field{Title: "user-agent", Value: c.Request().UserAgent(), Short: true})
ua := c.Request().UserAgent()
attachment.AddField(slack.Field{Title: "user-agent", Value: ua, Short: true})
attachment.AddField(slack.Field{Title: "auth", Value: auth, Short: true})
attachment.Color = &color

if channel != floodChannel {
slackFloodMutex.Lock()
defer slackFloodMutex.Unlock()
key := fmt.Sprintf("%s:%s:%s:%s", username, action, auth, ua)
last, found := slackFloodMap[key]
if found && -time.Until(last) < 30*time.Second {
channel = floodChannel
}
slackFloodMap[key] = time.Now()
}

payload := slack.Payload{
Text: fmt.Sprintf("%s (%s)", action, c.Path()),
//Username: "yolo",
Expand All @@ -143,11 +170,11 @@ func (s *Server) sendUserActionToSlack(c echo.Context, action string, color stri
}

func (s *Server) sendUserErrorToSlack(c echo.Context, err error) {
s.sendUserActionToSlack(c, fmt.Sprintf("error: %v", err), "#ff0000", "#yolodebug")
s.sendUserActionToSlack(c, fmt.Sprintf("error: %v", err), "#ff0000", "#yolodebug", "#yolodebug")
}

func (s *Server) GetIPA(c echo.Context) error {
s.sendUserActionToSlack(c, "IPA download", "#0000ff", "#yolologs")
s.sendUserActionToSlack(c, "IPA download", "#0000ff", "#yolologs", "#yolologs")
id := c.Param("*")
arts, err := s.client.GetArtifacts(id, true)
if err != nil {
Expand All @@ -172,7 +199,7 @@ func (s *Server) GetIPA(c echo.Context) error {
}

func (s *Server) GetAPK(c echo.Context) error {
s.sendUserActionToSlack(c, "Android download", "#00ff00", "#yolologs")
s.sendUserActionToSlack(c, "Android download", "#00ff00", "#yolologs", "#yolologs")
id := c.Param("*")
arts, err := s.client.GetArtifacts(id, true)
if err != nil {
Expand Down Expand Up @@ -343,7 +370,7 @@ type ReleasesDay struct {
}

func (s *Server) ListRelease(c echo.Context, job string) error {
s.sendUserActionToSlack(c, fmt.Sprintf("List Releases (%s)", job), "#00ffff", "#yolodebug")
s.sendUserActionToSlack(c, fmt.Sprintf("List Releases (%s)", job), "#00ffff", "#yolologs", "#yolodebug")

data := map[string]interface{}{}

Expand Down Expand Up @@ -518,7 +545,7 @@ func (s *Server) ReleaseIOS(c echo.Context) error {
}

func (s *Server) Itms(c echo.Context) error {
s.sendUserActionToSlack(c, "ITMS download", "#0000ff", "#yolologs")
s.sendUserActionToSlack(c, "ITMS download", "#0000ff", "#yolologs", "#yolologs")

pull := c.Param("*")

Expand Down

0 comments on commit 08b43de

Please sign in to comment.