From b9bc46128fb766daaa0aead71180e818a1c3d12c Mon Sep 17 00:00:00 2001 From: Alexandre Morignot <erdnaxeli@cervoi.se> Date: Fri, 7 Oct 2016 01:46:26 +0200 Subject: [PATCH] Slack support --- bot/bot.go | 1 + bot/collection.go | 8 ++-- bot/db.go | 4 +- main.go | 24 ++++++----- site/tag.go | 11 +++++ transport/irc/events.go | 4 +- transport/irc/irc.go | 1 - transport/slack/events.go | 29 ++++++++++++++ transport/slack/print.go | 39 ++++++++++++++++++ transport/slack/slack.go | 84 +++++++++++++++++++++++++++++++++++++++ 10 files changed, 187 insertions(+), 18 deletions(-) create mode 100644 site/tag.go create mode 100644 transport/slack/events.go create mode 100644 transport/slack/print.go create mode 100644 transport/slack/slack.go diff --git a/bot/bot.go b/bot/bot.go index 7712d57..f09e026 100644 --- a/bot/bot.go +++ b/bot/bot.go @@ -72,6 +72,7 @@ func (pb *PlayBot) ParseLine(author string, source string, line string, contents var wg sync.WaitGroup for _, url := range urls { + log.Print(url) wg.Add(1) go func(url string) { defer wg.Done() diff --git a/bot/collection.go b/bot/collection.go index 5597c27..c1adf6c 100644 --- a/bot/collection.go +++ b/bot/collection.go @@ -43,11 +43,11 @@ func (pbc *PlayBotCollection) InsertPost(post *Post) error { return err } - pbc.Db.Model(&content).Related(&content.Tags) + pbc.Db.Model(&content).Related(&content.Tags) - if len(post.Content.Tags) > 0 { - content.Tags = append(content.Tags, post.Content.Tags...) - } + if len(post.Content.Tags) > 0 { + content.Tags = append(content.Tags, post.Content.Tags...) + } post.Content = &content } diff --git a/bot/db.go b/bot/db.go index c4a76e4..72cd2bd 100644 --- a/bot/db.go +++ b/bot/db.go @@ -20,8 +20,8 @@ type Db interface { Error() error Insert(interface{}) Db First(interface{}) Db - Model(interface{}) Db - Related(interface{}) Db + Model(interface{}) Db + Related(interface{}) Db Where(interface{}) Db } diff --git a/main.go b/main.go index 8f27e4f..f0c4652 100644 --- a/main.go +++ b/main.go @@ -9,7 +9,9 @@ import ( "git.iiens.net/morignot2011/playbot/bot" "git.iiens.net/morignot2011/playbot/site" + "git.iiens.net/morignot2011/playbot/transport" "git.iiens.net/morignot2011/playbot/transport/irc" + "git.iiens.net/morignot2011/playbot/transport/slack" ) type config struct { @@ -45,21 +47,25 @@ func startTransport(name string, config transportParams, factory bot.Factory) ch log.Fatalf("Missing type for transport %s", name) } + log.Printf("Start %s", name) c := make(chan bool) + var t transport.Transport + var err error switch transportType { case "irc": - log.Printf("Start %s", name) - t, err := irc.New(name, config, factory, c) - if err != nil { - log.Fatalf("%s: %s", name, err) - } - - if err := t.Run(); err != nil { - log.Fatalf("%s: %s", name, err) - } + t, err = irc.New(name, config, factory, c) + case "slack": + t, err = slack.New(name, config, factory, c) } + if err != nil { + log.Fatalf("%s: %s", name, err) + } + + if err := t.Run(); err != nil { + log.Fatalf("%s: %s", name, err) + } return c } diff --git a/site/tag.go b/site/tag.go new file mode 100644 index 0000000..37c0d5d --- /dev/null +++ b/site/tag.go @@ -0,0 +1,11 @@ +package site + +type Tag struct { + Tag string `gorm:"primary_key:true"` + ContentId int `gorm:"column:id;primary_key:true"` + Content Content +} + +func (Tag) TableName() string { + return "playbot_tags" +} diff --git a/transport/irc/events.go b/transport/irc/events.go index 362f5d2..4a4a84e 100644 --- a/transport/irc/events.go +++ b/transport/irc/events.go @@ -23,11 +23,11 @@ func (t *IrcTransport) disconnected(conn *irc.Conn, line *irc.Line) { func (t *IrcTransport) privmsg(conn *irc.Conn, line *irc.Line) { channel := line.Target() msg := line.Args[1] - b := t.bots[channel] + bot := t.bots[channel] contents := make(chan *site.Content) source := t.getSourceName(channel) - go b.ParseLine(line.Nick, source, msg, contents) + go bot.ParseLine(line.Nick, source, msg, contents) for content := range contents { t.printNewContent(conn, content, channel) diff --git a/transport/irc/irc.go b/transport/irc/irc.go index 5bede3e..bee292d 100644 --- a/transport/irc/irc.go +++ b/transport/irc/irc.go @@ -46,7 +46,6 @@ func New(name string, config map[string]interface{}, factory bot.Factory, quit c return nil, transport.NewConfigurationError("chans") } for _, channel := range channels.([]interface{}) { - t.Logger.Print(channel) t.channels = append(t.channels, channel.(string)) } diff --git a/transport/slack/events.go b/transport/slack/events.go new file mode 100644 index 0000000..2f22132 --- /dev/null +++ b/transport/slack/events.go @@ -0,0 +1,29 @@ +package slack + +import ( + "github.com/nlopes/slack" + + "git.iiens.net/morignot2011/playbot/site" +) + +func (t *SlackTransport) connected(ev *slack.ConnectedEvent) { + t.Logger.Print("Connected") + + for _, channel := range t.channels { + bot := t.botFactory.GetBot(t.Name) + t.bots[channel] = bot + } + + t.bot = t.botFactory.GetBot(t.Name) +} + +func (t *SlackTransport) message(ev *slack.MessageEvent) { + contents := make(chan *site.Content) + + source := t.getSourceName(ev.Channel) + go t.bot.ParseLine(ev.User, source, ev.Text, contents) + + for content := range contents { + t.printNewContent(content, ev.Channel) + } +} diff --git a/transport/slack/print.go b/transport/slack/print.go new file mode 100644 index 0000000..3d44dfb --- /dev/null +++ b/transport/slack/print.go @@ -0,0 +1,39 @@ +package slack + +import ( + "fmt" + + "git.iiens.net/morignot2011/playbot/site" +) + +func (t *SlackTransport) printNewContent(content *site.Content, channel string) { + msg := fmt.Sprintf("[%d] %s", content.Id, content.Title) + + if content.Author != "" { + msg += " | " + content.Author + } + + if content.Duration > 0 { + h := content.Duration / 3600 + m := (content.Duration % 3600) / 60 + s := (content.Duration % 3600) % 60 + + msg += " (" + + if h > 0 { + msg += fmt.Sprintf("%02d:", h) + } + + if m > 0 { + msg += fmt.Sprintf("%02d:", m) + } + + msg += fmt.Sprintf("%02d)", s) + } + + for _, tag := range content.Tags { + msg += " #" + tag.Tag + } + + t.rtm.SendMessage(t.rtm.NewOutgoingMessage(msg, channel)) +} diff --git a/transport/slack/slack.go b/transport/slack/slack.go new file mode 100644 index 0000000..ddf2bf6 --- /dev/null +++ b/transport/slack/slack.go @@ -0,0 +1,84 @@ +package slack + +import ( + "fmt" + "log" + "os" + + "github.com/nlopes/slack" + + "git.iiens.net/morignot2011/playbot/bot" + "git.iiens.net/morignot2011/playbot/transport" +) + +type SlackTransport struct { + transport.Base + + api *slack.Client + bot bot.Bot + bots map[string]bot.Bot + channels []string + botFactory bot.Factory + rtm *slack.RTM + quit chan bool +} + +func New(name string, config map[string]interface{}, factory bot.Factory, quit chan bool) (transport.Transport, error) { + token, ok := config["token"] + if !ok { + return nil, transport.NewConfigurationError("token") + } + + api := slack.New(token.(string)) + rtm := api.NewRTM() + t := &SlackTransport{ + api: api, + bots: make(map[string]bot.Bot), + botFactory: factory, + rtm: rtm, + quit: quit, + + Base: transport.Base{ + Logger: log.New(os.Stdout, name, log.LstdFlags), + Name: name, + }, + } + + channels, ok := config["chans"] + for _, channel := range channels.([]interface{}) { + t.channels = append(t.channels, channel.(string)) + } + + return t, nil +} + +func (t *SlackTransport) Run() error { + go t.rtm.ManageConnection() + go t.dispatchEvents() + + return nil +} + +func (t *SlackTransport) dispatchEvents() { + for { + select { + case msg := <-t.rtm.IncomingEvents: + switch ev := msg.Data.(type) { + case *slack.ConnectedEvent: + t.connected(ev) + case *slack.MessageEvent: + t.message(ev) + case *slack.InvalidAuthEvent: + t.Logger.Printf("Invalid credentials") + t.quit <- true + return + case *slack.RTMError: + t.Logger.Printf("Error: %q", ev) + } + } + } +} + +func (t *SlackTransport) getSourceName(channel string) string { + return fmt.Sprintf("%s@%s", channel, t.Name) +} -- GitLab