Last active
August 19, 2016 08:15
-
-
Save artemnikitin/7a9a6a92a1d4e452295f730e6587662c to your computer and use it in GitHub Desktop.
Slack bot for repost messages
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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