Skip to content

Commit

Permalink
Merge pull request #1 from Crazybus/moon_lettuce
Browse files Browse the repository at this point in the history
First commit for moonsla
  • Loading branch information
Crazybus authored Jul 3, 2018
2 parents 0c3b463 + 6fb8483 commit bc414bd
Show file tree
Hide file tree
Showing 6 changed files with 441 additions and 2 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
moonsla
25 changes: 25 additions & 0 deletions .travis.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
language: go

go:
- "1.10"

services:
- docker

script:
- go test -v -race -coverprofile=coverage.txt -covermode=atomic
- wget https://github.com/Crazybus/lope/releases/download/0.2.0/lope-linux_amd64 -O lope && chmod +x lope
- ./lope -workDir /go/src/github.com/Crazybus/moonsla -blacklist GO golang:1.10 '/usr/local/go/bin/go get -v ./... && /usr/local/go/bin/go run build/build.go'

after_success:
- bash <(curl -s https://codecov.io/bash)

deploy:
provider: releases
api_key:
secure: hT+TBmMhj8yFvGfTOGPhoVuiINprm600JijpT//kgO2PBiiQ/Tcc+ShEiXGXNoXb+mngMj+w4NsPbNjFR6K1TIxsyFDrmN2RvKi01SJZMKgpbJH5+VmkMPHJX0AxMcHjYTBkz9inM6PLzFsSHrDO296gjGpM4xMvh4wuOYz/4JH9dLcsn6BdchhrA1ipKrHwsDU6DaK9YvZwjRpB3eO4s5woUuYfHgr9OkAPLCUuh6u+HCRhtxH8F9aNtNVlHm43u9lLcwJ41YVycpfRNEhHp30Nrghn4PciPoqISJVyRSSva96HSlR9+T55aCGY0ch762k9P6CeP3OQfK/2s8v5Fcq40ScUm+GLntRv49O1eJuqBkI7HImnHzrb1w329MgJTijFVxf3W7jEj4mjyttuyScMzd9b7/ERRGUzhqqQx488ICw3tU9+fnfguhEaNt3DanyijT6ZYqVA6TQTanc/z+w+uQTy7w92mRocNNYPJA17yL8BOS7EJb5vu0+ifVyXco+5McTBcJUSm+zqFzLm2Ey3VGs4eVbCY3r4XvOSr3P3MjR1iB8u+fBeVqL6TPi+p0eRPtSHjoRRPjsmoupv9fpmRIDA7hXi3GoT9HZB8fSfFtKoEgfi7lz67UPwQXADhIEnTD5SKptt897lvq1DOj4lDDETakdkBkBKIBWdh4w=
file_glob: true
file: build/moonsla*
skip_cleanup: true
on:
tags: true
42 changes: 40 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,2 +1,40 @@
# moonsla
View all the slack messages!
# Moonsla

[![Build Status](https://travis-ci.org/Crazybus/moonsla.svg?branch=master)](https://travis-ci.org/Crazybus/moonsla)

Moonsla is a small tool to display a stream of slack messages in a single view.

It looks something like this

```
10:42:37 - general - Michael Russell: Weird I never knew that slack threads were just normal messages
10:42:55 - random - Someone Else: Sweet Potato!
10:43:37 - general - John Smith: Can people please stop using threads for everything!
```

# Usage

If you don't have one already you will need to generate a [slack API token](https://api.slack.com/custom-integrations/legacy-tokens)

You need to set this to your `SLACK_TOKEN` environment variable
```
export SLACK_TOKEN='xoxp-1231231231232323-123123123123-123123123123123-c91238917239123'
moonsla
```

You can also set `SLACK_CHANNELS` to a comma separated list of channels to filter for
```
export SLACK_CHANNELS='general,random'
```

# Why?

I'm not a fan of notifications because they are very intrusive. Instead I used to keep slack always open with the slackbot channel active (so I don't accidentally type shell commands into #general). Whenever I had a spare moment I would then check each slack channel to see if there was anything that needed my attention. This took a bit too long and quite often the message would be bot telling me I had just submitted a pull request

# Future

* Fix channel naming for slackbot and private channels
* Improve formatting of messages so that sub-teams, urls and everything else is formatted as expected
* Automatically link to the slack message so it is easy to open up the message from moonsla in slack
* Support multiple slack workspaces
* Add an optional web interface to make things look pretty and allow displaying of images
84 changes: 84 additions & 0 deletions build/build.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
package main

import (
"crypto/sha256"
"fmt"
"io"
"log"
"os"
"os/exec"
"path/filepath"
)

var buildDir = filepath.FromSlash("build/")

var operatingSystems = [...]string{
"darwin",
"linux",
"windows",
}

var archs = [...]string{
"386",
"amd64",
}

func checksum(goos string, goarch string) error {
file := buildDir + "moonsla-" + goos + "_" + goarch
f, err := os.Open(file)
if err != nil {
return err
}
defer f.Close()

h := sha256.New()
if _, err := io.Copy(h, f); err != nil {
return err
}
sumFile := file + ".sha256"
hash := fmt.Sprintf("%x", h.Sum(nil))
fmt.Println(hash, file)

hashFile, err := os.Create(sumFile)
if err != nil {
return err
}
defer hashFile.Close()

_, err = hashFile.WriteString(hash)
if err != nil {
return err
}
return nil
}

func build(goos string, goarch string) error {
os.Setenv("GOOS", goos)
os.Setenv("GOARCH", goarch)

cmd := exec.Command(
"/usr/local/go/bin/go",
"build",
"-v",
"-o",
buildDir+"moonsla-"+goos+"_"+goarch,
)
return cmd.Run()
}

func main() {
for _, goos := range operatingSystems {
for _, goarch := range archs {
err := build(goos, goarch)
if err != nil {
log.Printf("Failed to build %s/%s with error: %v", goos, goarch, err)
os.Exit(1)
}
err = checksum(goos, goarch)
if err != nil {
log.Printf("Failed to generate checksums for %s/%s with error: %v", goos, goarch, err)
os.Exit(1)
}
}
}
}
143 changes: 143 additions & 0 deletions moonsla.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,143 @@
package main

import (
"fmt"
"log"
"os"
"regexp"
"strconv"
"strings"
"time"

"github.com/nlopes/slack"
)

func getChannels(api *slack.Client) (channels map[string]string) {
channels = make(map[string]string)
chans, _ := api.GetChannels(true)
for _, c := range chans {
channels[c.ID] = c.Name
}
return channels
}

func getUsers(api *slack.Client) (users map[string]string) {
users = make(map[string]string)
allUsers, _ := api.GetUsers()
for _, u := range allUsers {
users[u.ID] = u.RealName
}
return users
}

func getTimeStamp(ts string) (timeStamp time.Time) {
i, err := strconv.ParseInt(strings.Split(ts, ".")[0], 10, 64)
if err != nil {
panic(err)
}
timeStamp = time.Unix(i, 0)
return timeStamp
}

func formatMentions(msg string, users map[string]string) string {
re := regexp.MustCompile("<@U.*?>")
matches := re.FindAllString(msg, -1)
for _, m := range matches {
userID := m[2:(len(m) - 1)]
username, ok := users[userID]
if ok {
username = "@" + username
msg = strings.Replace(msg, m, username, -1)
}
}
return msg
}

func filterChannel(name string, channels map[string]string, whitelist []string) (whitelisted bool, cName string) {
whitelisted = false

cName, ok := channels[name]
if ok {
for _, w := range whitelist {
if cName == w {
whitelisted = true
}
}
} else {
whitelisted = true
cName = name
}

if len(whitelist) == 0 {
whitelisted = true
}

return whitelisted, cName
}

func main() {

slackToken, ok := os.LookupEnv("SLACK_TOKEN")
if !ok {
fmt.Println("Please set your SLACK_TOKEN")
}
api := slack.New(slackToken)

logger := log.New(os.Stdout, "slack-bot: ", log.Lshortfile|log.LstdFlags)
slack.SetLogger(logger)
api.SetDebug(false)

channels := getChannels(api)
fmt.Printf("Found %v channels\n", len(channels))

users := getUsers(api)
fmt.Printf("Found %v users\n", len(users))

rtm := api.NewRTM()
go rtm.ManageConnection()

whitelist := strings.Split(os.Getenv("SLACK_CHANNELS"), ",")
fmt.Printf("Channel whitelist: %v\n", whitelist)

for msg := range rtm.IncomingEvents {

switch ev := msg.Data.(type) {

case *slack.MessageEvent:

// Skip empty messages
if ev.Text == "" {
continue
}

whitelisted, cName := filterChannel(ev.Channel, channels, whitelist)
if !whitelisted {
continue
}

// Map the users ID to a username if it exists
uName, ok := users[ev.User]
if !ok {
uName = ev.User
}

t := getTimeStamp(ev.EventTimestamp)
timeStamp := fmt.Sprintf("%02d:%02d:%02d", t.Hour(), t.Minute(), t.Second())

msg := formatMentions(ev.Text, users)

fmt.Printf("%v - %v - %v: %v\n", timeStamp, cName, uName, msg)

case *slack.RTMError:
fmt.Printf("Error: %s\n", ev.Error())

case *slack.InvalidAuthEvent:
fmt.Printf("Invalid credentials")
return

default:
// Ignore other events..
// fmt.Printf("Unexpected: %v\n", msg.Data)
}
}
}
Loading

0 comments on commit bc414bd

Please sign in to comment.