Skip to content

Instantly share code, notes, and snippets.

@artemnikitin
Last active August 19, 2016 08:15
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save artemnikitin/7a9a6a92a1d4e452295f730e6587662c to your computer and use it in GitHub Desktop.
Save artemnikitin/7a9a6a92a1d4e452295f730e6587662c to your computer and use it in GitHub Desktop.
Slack bot for repost messages
package main
import (
"flag"
"fmt"
"log"
"os"
"regexp"
"strings"
"github.com/nlopes/slack"
)
var (
token = flag.String("token", "", "Token for Slack")
fromChannel = flag.String("from", "", "Name of channel where to look for messages")
toChannel = flag.String("to", "", "Name of channel where to post messages")
slackUser = flag.String("user", "", "User name for Slack")
debug = flag.Bool("debug", false, "Enable debug mode")
keywords = []string{"ваканси", "работа", "позици", "тестировщик", "автоматизатор", "должность", "требования"}
URLKeywords = []string{"hh.ru", "job", "linkedin", "position", "vacancy", "work", "career"}
fromID, toID, userID string
)
const regex = "(http|ftp|https)://([\\w_-]+(?:(?:\\.[\\w_-]+)+))([\\w.,@?^=%&:/~+#-]*[\\w@?^=%&/~+#-])?"
func main() {
flag.Parse()
log.SetFlags(log.Lshortfile | log.LstdFlags)
log.SetPrefix("slack-bot:")
if *token == "" || *fromChannel == "" || *toChannel == "" || *slackUser == "" {
fmt.Println("Specify correct flags")
flag.PrintDefaults()
os.Exit(1)
}
r, err := regexp.Compile(regex)
if err != nil {
log.Fatal("Can't compile regexp:", err)
}
api := slack.New(*token)
api.SetDebug(*debug)
users, err := api.GetUsers()
if err != nil {
log.Println("Can't get list of users:", err)
return
}
for _, user := range users {
if user.Name == *slackUser {
userID = user.ID
break
}
}
channels, err := api.GetChannels(false)
if err != nil {
log.Println("Can't get list of channels:", err)
return
}
for _, channel := range channels {
switch channel.Name {
case *fromChannel:
fromID = channel.ID
case *toChannel:
toID = channel.ID
default:
}
}
rtm := api.NewRTM()
go rtm.ManageConnection()
for {
select {
case msg := <-rtm.IncomingEvents:
fmt.Println("Event Received")
switch ev := msg.Data.(type) {
case *slack.MessageEvent:
if ev.Channel == fromID {
text := ev.Text
if ev.SubMessage != nil {
text = ev.SubMessage.Text
}
if isJobPosting(text, r) {
text = strings.Replace(text, "<", "", -1)
text = strings.Replace(text, ">", "", -1)
rtm.SendMessage(rtm.NewOutgoingMessage(text, toID))
}
}
if ev.Channel == toID {
if ev.User != userID {
api.DeleteMessage(toID, ev.Timestamp)
}
}
case *slack.RTMError:
fmt.Printf("Error: %s\n", ev.Error())
case *slack.InvalidAuthEvent:
fmt.Println("Error: Invalid credentials!")
break
default:
}
}
}
}
func isJobPosting(text string, r *regexp.Regexp) bool {
text = strings.ToLower(text)
return r.MatchString(text) && (containsKeyword(text, keywords) || containsKeyword(text, URLKeywords))
}
func containsKeyword(text string, list []string) bool {
result := false
for _, v := range list {
if strings.Contains(text, v) {
result = true
break
}
}
return result
}
package main
import (
"regexp"
"testing"
)
func TestRegexp(t *testing.T) {
cases := []struct {
in string
res bool
}{
{"[skype - tamara.mishcherina ]\nВсем привет! Открылась вакансия для QA automation (опыт от 3+) на удаленку. English level (speaking, writing, reading) - intermediate level. Автоматизация на С#. Пишите в личку, отвечу на все вопросы. :slightly_smiling_face:", false},
{"htttp://hh.ru/dfffgfgf", false},
{"http://hh.ru/dfffgfgf", true},
{"something http://example.com/jobs", true},
{"http://example.com/jobs dfdf f- dfd ", true},
{"dsssdsdsd http://example.com dfdf f- dfd ", true},
}
r, _ := regexp.Compile(regex)
for _, v := range cases {
result := r.MatchString(v.in)
if result != v.res {
t.Errorf("For string: %s, actual result: %v, expected: %v", v.in, result, v.res)
}
}
}
func TestContainsKeyword(t *testing.T) {
cases := []struct {
in string
res bool
}{
{"dfd/", false},
{"htttp://hh.ru/dfffgfgf", true},
{"http://example.com/jobs", true},
}
for _, v := range cases {
result := containsKeyword(v.in, URLKeywords)
if result != v.res {
t.Errorf("For string: %s, actual result: %v, expected: %v", v.in, result, v.res)
}
}
}
func TestIsJobPosting(t *testing.T) {
cases := []struct {
in string
res bool
}{
{"[skype - tamara.mishcherina ]\nВсем привет! Открылась вакансия для QA automation (опыт от 3+) на удаленку. English level (speaking, writing, reading) - intermediate level. Автоматизация на С#. Пишите в личку, отвечу на все вопросы. :slightly_smiling_face:", false},
{"http://hh.ru/something", true},
{"something interesting http://example.com/jobs", true},
}
r, _ := regexp.Compile(regex)
for _, v := range cases {
result := isJobPosting(v.in, r)
if result != v.res {
t.Errorf("For string: %s, actual result: %v, expected: %v", v.in, result, v.res)
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment