Created
December 3, 2018 15:28
-
-
Save DanielOaks/a66839c5b1b3441dde34dd6ae4165c95 to your computer and use it in GitHub Desktop.
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 ( | |
"log" | |
"fmt" | |
"strings" | |
"sync" | |
"strconv" | |
"net" | |
"github.com/nlopes/slack" | |
"github.com/nlopes/slack/slackutilsx" | |
"github.com/goshuirc/eventmgr" | |
"github.com/goshuirc/irc-go/client" | |
"github.com/goshuirc/irc-go/ircfmt" | |
"github.com/goshuirc/irc-go/ircmap" | |
) | |
const ( | |
slackAPIToken = "slack-token-here" | |
slackChannel = "test-irc" | |
ircNick = "test-proxy" | |
ircUser = "test" | |
ircRealName = "test proxy" | |
// ircHost = "localhost" | |
// ircPort = 6667 | |
// ircTLS = false | |
ircHost = "chat.freenode.net" | |
ircPort = 6697 | |
ircTLS = true | |
ircChannel = "#test" | |
ircHereTag = "@here" | |
) | |
const ( | |
ircActionPrefix = "\x01ACTION " | |
) | |
// rawIRCHandler prints raw IRC messages to and from the server. | |
func rawIRCHandler(event string, info eventmgr.InfoMap) { | |
// sc := info["server"].(*gircclient.ServerConnection) | |
// direction := info["direction"].(string) | |
// line := info["data"].(string) | |
// var arrow string | |
// if direction == "in" { | |
// arrow = "<- " | |
// } else { | |
// arrow = " ->" | |
// } | |
// fmt.Println("IRC:", sc.Name, arrow, ircfmt.Escape(strings.Trim(line, "\r\n"))) | |
} | |
func main() { | |
// stores whether we're shutting down for whatever reason | |
var shuttingDown bool | |
// waitgroup, so we exit correctly | |
var wg sync.WaitGroup | |
// define irc things | |
reactor := gircclient.NewReactor() | |
server := reactor.CreateServer("srv") | |
// starting slack api | |
api := slack.New(slackAPIToken) | |
// If you set debugging, it will log all requests to the console | |
// Useful when encountering issues | |
// api.SetDebug(true) | |
groups, err := api.GetGroups(false) | |
if err != nil { | |
fmt.Printf("%s\n", err) | |
return | |
} | |
slackChannelID := "" | |
for _, group := range groups { | |
fmt.Printf("Slack Channel Listing: ID: %s, Name: %s\n", group.ID, group.Name) | |
if group.Name == slackChannel { | |
slackChannelID = group.ID | |
} | |
} | |
if slackChannelID == "" { | |
log.Fatalf("Could not find Slack channel named [%s]\n", slackChannel) | |
return | |
} | |
// start slack rtm stuff | |
rtm := api.NewRTM() | |
go rtm.ManageConnection() | |
// receiving slack messages | |
wg.Add(1) | |
go func() { | |
defer wg.Done() | |
defer func() { | |
shuttingDown = true | |
server.Shutdown("Closing Connection") | |
}() | |
for msg := range rtm.IncomingEvents { | |
if shuttingDown { | |
fmt.Println("SlackRTM: shuttingDown is true") | |
return | |
} | |
// fmt.Print("Event Received: ") | |
switch ev := msg.Data.(type) { | |
case *slack.HelloEvent: | |
// Ignore hello | |
case *slack.ConnectedEvent: | |
// fmt.Println("Infos:", ev.Info) | |
// fmt.Println("Connection counter:", ev.ConnectionCount) | |
case *slack.MessageEvent: | |
// fmt.Printf("Message: %v\n", ev) | |
// kill the bot | |
// we listen for this in all channels so it even happens in pm, etc | |
if strings.TrimSpace(ev.Text) == "!quit" { | |
fmt.Println("SlackRTM: !quit command received from Slack") | |
return | |
} | |
// only respond to proper cmds in the channel we're listening on | |
if ev.Channel != slackChannelID { | |
continue | |
} | |
// only forward slack messages that start with "!public " | |
if !strings.HasPrefix(ev.Text, "!public ") { | |
continue | |
} | |
t := strings.TrimPrefix(ev.Text, "!public ") | |
msg := fmt.Sprintf("[ID:%s] %s", ev.User, t) | |
u, err := api.GetUserInfo(ev.User) | |
if err == nil { | |
msg = fmt.Sprintf("[%s] %s", u.Name, t) | |
fmt.Println("SlackRTM: Sending message public:", msg) | |
rtm.SendMessage(rtm.NewOutgoingMessage(fmt.Sprintf("Sending message publicly: %s\n", msg), slackChannelID)) | |
server.Msg(nil, ircChannel, msg, false) | |
} else { | |
fmt.Println("SlackRTM: Could not send msg publicly:", msg, "-", err.Error()) | |
rtm.SendMessage(rtm.NewOutgoingMessage(fmt.Sprintf("Could not send message publicly: %s - %s\n", msg, err.Error()), slackChannelID)) | |
} | |
fmt.Println("Slack:", msg) | |
// case *slack.PresenceChangeEvent: | |
// fmt.Printf("Presence Change: %v\n", ev) | |
case *slack.LatencyReport: | |
fmt.Printf("SlackRTM: Current latency: %v\n", ev.Value) | |
case *slack.RTMError: | |
fmt.Printf("SlackRTM: Error: %s\n", ev.Error()) | |
return | |
case *slack.InvalidAuthEvent: | |
fmt.Printf("SlackRTM: Invalid credentials") | |
return | |
default: | |
// Ignore other events.. | |
// fmt.Printf("Unexpected: %v\n", msg.Data) | |
} | |
} | |
}() | |
// connect to irc | |
server.InitialNick = ircNick | |
server.InitialUser = ircUser | |
server.InitialRealName = ircRealName | |
server.JoinChannel(ircChannel, "", false) | |
// attach irc events | |
server.RegisterEvent("in", "PRIVMSG", func (event string, info eventmgr.InfoMap) { | |
sc := info["server"].(*gircclient.ServerConnection) | |
target, _ := ircmap.Casefold(sc.Casemapping, info["params"].([]string)[0]) | |
if target != ircChannel { | |
return | |
} | |
prefix := strings.Split(strings.Split(info["prefix"].(string), "!")[0], "@")[0] | |
sentMsg := ircfmt.Escape(info["params"].([]string)[1]) | |
msg := fmt.Sprintf("<%s> %s", prefix, sentMsg) | |
if strings.HasPrefix(sentMsg, ircActionPrefix) { | |
msg = fmt.Sprintf("*%s %s", prefix, strings.TrimSuffix(strings.TrimPrefix(sentMsg, ircActionPrefix), "\x01")) | |
} | |
msg = slackutilsx.EscapeMessage(msg) | |
if strings.Contains(msg, ircHereTag) { | |
msg = strings.Replace(msg, ircHereTag, "<!here>", -1) | |
} | |
rtm.PostMessage(slackChannelID, slack.MsgOptionText(msg, false)) | |
fmt.Println("IRC:", sc.Name, target, "<" + info["prefix"].(string) + ">", ircfmt.Escape(info["params"].([]string)[1])) | |
}, 0) | |
server.RegisterEvent("in", "raw", rawIRCHandler, 0) | |
server.RegisterEvent("out", "raw", rawIRCHandler, 0) | |
// connect | |
err = server.Connect(net.JoinHostPort(ircHost, strconv.Itoa(ircPort)), ircTLS, nil) | |
if err != nil { | |
log.Fatalln("IRC: Connection error:", err.Error()) | |
} | |
// start irc loop | |
wg.Add(1) | |
go func() { | |
defer wg.Done() | |
defer func() { shuttingDown = true }() | |
server.ReceiveLoop() | |
}() | |
// wait for everything to exit | |
wg.Wait() | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment