需求

通过 Slack 命令模式,调用操作远程服务器。
服务端需要跟一个http服务来解析slash调过来的命令。

准备

准备以下步骤:

  1. 创建Slash conmand
  2. 开发服务端应用

添加 Slash Conmand

添加App

先到官网地址:https://api.slack.com/ 创建一个App

官网

createApp

Slash Conmand

slashCommand

createCommand

输出一个自定义命令

createNewCommand

到这就创建完成了,接下来开发服务端。

实现

创建 go 项目slacktool,添加:

  1. main.go 文件
  2. go.mod 文件
  3. environment.env 文件

项目结构

1
2
3
4
slacktool
|---main.go
|---go.mod
|---environment.env

添加 go.mod 依赖

添加两个依赖:
godotenvslack

1
2
3
4
5
6
7
8
module github.com/forfreeday/slacktool

go 1.17

require (
github.com/joho/godotenv v1.4.0
github.com/nlopes/slack v0.6.0
)

添加后执行:

1
go mod tidy

编辑 main.go

下面的功能包括:

  1. 运行一个http服务端
  2. runConmand 运行逻辑
  3. exec 执行shell命令
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
package main

import (
"fmt"
"log"
"net/http"
"os"
"os/exec"

"github.com/joho/godotenv"
"github.com/nlopes/slack"
)

func main() {
// 读取环境变量配置
err := godotenv.Load("environment.env")
if err != nil {
log.Fatal("Error loading .env file")
}
// 具体处理逻辑
http.HandleFunc("/deploy-test", slashCommandHandler)
fmt.Println("[INFO] Server listening")
// 启动 http
http.ListenAndServe(":10001", nil)
}

func slashCommandHandler(w http.ResponseWriter, r *http.Request) {
s, err := slack.SlashCommandParse(r)
if err != nil {
w.WriteHeader(http.StatusInternalServerError)
return
}
fmt.Println("for test: invoke msg")
if !s.ValidateToken(os.Getenv("SLACK_VERIFICATION_TOKEN")) {
w.WriteHeader(http.StatusUnauthorized)
return
}

switch s.Command {
case "/deploy-test":
params := &slack.Msg{Text: s.Text}
response := fmt.Sprintf("Command params : %v", params.Text)
// 开启协程,否则如果执行太久,slack端会返回 timeout
go runConmand(params, w)
w.Write([]byte(response))
default:
w.WriteHeader(http.StatusInternalServerError)
return
}
}

// 执行命令
func runConmand(param *slack.Msg, w http.ResponseWriter) {
switch param.Text {
case "--restartAll":
fmt.Println("restart All node")
cmd := exec.Command("deploy-test", param.Text)
_, err := cmd.CombinedOutput()
if err != nil {
log.Fatalf("cmd.Run() failed with %s\n", err)
}
case "--develop":
fmt.Println("develop code")
default:
w.WriteHeader(http.StatusInternalServerError)
return
}
}

服务端行一下,服务端可以多加一些日志,查看效果。

slash执行效果

总结

比较简单,上面的代码最终调了一个系统命令deploy-test,这个实际写的另一个命令,写文章举个例子。