This repository has been archived on 2018-03-03. You can view files and clone it. You cannot open issues or pull requests or push a commit.
Files
SlackTSBot/slacktsbot.go
T
2016-04-14 17:45:39 +02:00

195 lines
4.6 KiB
Go

// slacktsbot by Daniel Aberger
package main
import (
"bufio"
"bytes"
"encoding/json"
"flag"
"fmt"
"log"
"net"
"net/http"
"regexp"
"strings"
"time"
)
type Payload struct {
Channel string `json:"channel"`
IconEmoji string `json:"icon_emoji"`
Text string `json:"text"`
Username string `json:"username"`
}
var (
users = map[string]bool{}
port *string = flag.String("port", "12345", "teamspeak 3 query port number")
host *string = flag.String("host", "your.ts-server.com", "teamspeak 3 server host")
user *string = flag.String("user", "youradminuser", "teamspeak 3 server admin user")
pass *string = flag.String("password", "yourpassword", "teamspeak 3 server admin user password")
slackhookurl *string = flag.String("slack", "https://hooks.slack.com/services/YOURSLACKWEBHOOKURL", "slack webhook url")
slackchannel *string = flag.String("slackchan", "#yourslackchannel", "slack channel name")
)
func init() {
// ./slacktsbot -port=12345 -host=your.ts-server.com -user=yourusername -pass=yourpassword
flag.Parse()
}
func main() {
for {
var err error
users, err = getUsers()
if err != nil {
log.Println(err)
log.Println("Trying again in 60 seconds.")
time.Sleep(60 * time.Second)
} else {
break
}
}
for {
neu, err := getUsers()
if err != nil {
log.Println(err)
time.Sleep(50 * time.Second)
} else {
for i, _ := range neu {
if users[i] != neu[i] {
generateAndSendPayload(i, "join")
}
}
for i, _ := range users {
if users[i] != neu[i] {
generateAndSendPayload(i, "leave")
}
}
users = neu
}
time.Sleep(10 * time.Second)
}
}
func generateAndSendPayload(user string, action string) {
payload := Payload{
Channel: *slackchannel,
IconEmoji: ":poop:",
Text: "",
Username: "TS3 Bot",
}
var actiontext string
if action == "join" {
actiontext = " joined TS3."
}
if action == "leave" {
actiontext = " left TS3."
}
timestamp := time.Now().Format(time.RFC822)
payload.Text = timestamp + " " + user + actiontext
b, err := json.Marshal(payload)
if err != nil {
fmt.Println("error:", err)
} else {
sendToSlack(b)
}
}
func sendToSlack(json []byte) {
url := *slackhookurl
log.Println("URL:>", url)
var jsonStr = json
req, err := http.NewRequest("POST", url, bytes.NewBuffer(jsonStr))
req.Header.Set("X-Custom-Header", "myvalue")
req.Header.Set("Content-Type", "application/json")
client := &http.Client{}
resp, err := client.Do(req)
if err != nil {
panic(err)
}
defer resp.Body.Close()
log.Println("response Status:", resp.Status)
//log.Println("response Headers:", resp.Header)
//body, _ := ioutil.ReadAll(resp.Body)
//log.Println("response Body:", string(body))
}
func getUsers() (u map[string]bool, e error) {
log.Println("Querying Teamspeak 3 server '" + *host + ":" + *port + "'...")
conn, err := net.Dial("tcp", *host+":"+*port)
if err != nil {
return nil, err
}
reader := bufio.NewReader(conn)
writer := bufio.NewWriter(conn)
for i := 0; i < 2; i++ { // get rid of banner
_, _, err := reader.ReadLine()
if err != nil {
if err.Error() == "EOF" {
log.Println("Connection closed by foreign host.")
}
return nil, err
}
}
writer.WriteString("login " + *user + " " + *pass + "\n")
writer.Flush()
_, _, err = reader.ReadLine() // get rid of "OK" message
if err != nil {
if err.Error() == "EOF" {
log.Println("Connection closed by foreign host.")
}
return nil, err
}
writer.WriteString("use sid=1\n")
writer.Flush()
_, _, err = reader.ReadLine() // get rid of "OK" message
if err != nil {
if err.Error() == "EOF" {
log.Println("Connection closed by foreign host.")
}
return nil, err
}
writer.WriteString("clientlist\n")
writer.Flush()
line, _, err := reader.ReadLine() // get rid of "OK" message
if err != nil {
if err.Error() == "EOF" {
log.Println("Connection closed by foreign host.")
}
return nil, err
}
users_raw := string(line)
re := regexp.MustCompile("client_nickname=(.*?) ")
users_still_raw := re.FindAllString(users_raw, -1)
for i := range users_still_raw {
users_still_raw[i] = strings.Trim(users_still_raw[i], " ")
users_still_raw[i] = strings.Replace(users_still_raw[i], "client_nickname=", "", 1)
users_still_raw[i] = strings.Replace(users_still_raw[i], "\\s", " ", -1)
}
users := make([]string, 0)
for i := range users_still_raw {
if !strings.HasPrefix(users_still_raw[i], "serveradmin from") {
users = append(users, users_still_raw[i])
}
}
result := make(map[string]bool)
for i := range users {
result[users[i]] = true
}
conn.Close()
return result, nil
}