-
Notifications
You must be signed in to change notification settings - Fork 21
/
webapi.go
198 lines (178 loc) · 6.08 KB
/
webapi.go
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
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
// web 服务相关
package main
import (
"context"
"fmt"
"log"
"net/http"
"strconv"
"time"
"github.com/gorilla/mux"
"github.com/rs/cors"
)
// web 服务帮助信息
const webHelp = `/listlive:列出正在直播的主播
/listrecord:列出正在下载的直播视频
/listdanmu:列出正在下载的直播弹幕
/startwebui:启动 web UI 服务器
/stopwebui:停止 web UI 服务器
/liststreamer:列出设置了开播提醒或自动下载直播的主播
/startmirai:利用 Mirai 发送直播通知到指定 QQ 或 QQ 群
/addnotifyon/uid:订阅指定主播的开播提醒,uid 在主播的网页版个人主页查看
/delnotifyon/uid:取消订阅指定主播的开播提醒
/addnotifyoff/uid:订阅指定主播的下播提醒
/delnotifyoff/uid:取消订阅指定主播的下播提醒
/addnotifyrecord/uid:通知指定主播的直播视频下载
/delnotifyrecord/uid:取消通知指定主播的直播视频下载
/addnotifydanmu/uid:通知指定主播的直播弹幕下载
/delnotifydanmu/uid:取消通知指定主播的直播弹幕下载
/addrecord/uid:自动下载指定主播的直播视频
/delrecord/uid:取消自动下载指定主播的直播视频
/adddanmu/uid:自动下载指定主播的直播弹幕
/deldanmu/uid:取消自动下载指定主播的直播弹幕
/addkeeponline/uid:指定主播直播时在其直播间挂机
/delkeeponline/uid:取消在指定主播直播时在其直播间挂机
/delconfig/uid:删除指定主播的所有设置
/getdlurl/uid:查看指定主播是否在直播,如在直播输出其直播源地址
/addqq/uid/QQ号:设置将指定主播的开播提醒发送到指定QQ号
/delqq/uid:取消设置将指定主播的开播提醒发送到QQ
/addqqgroup/uid/QQ群号:设置将指定主播的开播提醒发送到指定QQ群号
/delqqgroup/uid:取消设置将指定主播的开播提醒发送到QQ群号
/startrecord/uid:临时下载指定主播的直播视频,如果没有设置自动下载该主播的直播视频,这次为一次性的下载
/stoprecord/uid:正在下载指定主播的直播视频时取消下载
/startdanmu/uid:临时下载指定主播的直播弹幕,如果没有设置自动下载该主播的直播弹幕,这次为一次性的下载
/stopdanmu/uid:正在下载指定主播的直播弹幕时取消下载
/startrecdan/uid:临时下载指定主播的直播视频和弹幕,如果没有设置自动下载该主播的直播视频和弹幕,这次为一次性的下载
/stoprecdan/uid:正在下载指定主播的直播视频和弹幕时取消下载
/log:查看 log
/quit:退出本程序,退出需要等待半分钟左右
/help:本帮助信息`
var apiSrv *http.Server
// 返回 localhost 地址和端口
func address(port int) string {
return fmt.Sprintf("http://localhost:%d", port)
}
// 处理 "/cmd"
func cmdHandler(w http.ResponseWriter, r *http.Request) {
vars := mux.Vars(r)
cmd := vars["cmd"]
w.Header().Set("Content-Type", "application/json")
if s := handleCmd(cmd); s != "" {
fmt.Fprint(w, s)
} else {
fmt.Fprint(w, "null")
}
}
// 处理 "/cmd/uid"
func cmdUIDHandler(w http.ResponseWriter, r *http.Request) {
vars := mux.Vars(r)
cmd := vars["cmd"]
uid, err := atoi(vars["uid"])
checkErr(err)
w.Header().Set("Content-Type", "application/json")
if s := handleCmdUID(cmd, uid); s != "" {
fmt.Fprint(w, s)
} else {
fmt.Fprint(w, "null")
}
}
// 处理 "/cmd/uid/qq"
func cmdQQHandler(w http.ResponseWriter, r *http.Request) {
vars := mux.Vars(r)
cmd := vars["cmd"]
uid, err := strconv.ParseUint(vars["uid"], 10, 64)
checkErr(err)
qq, err := strconv.ParseUint(vars["qq"], 10, 64)
checkErr(err)
w.Header().Set("Content-Type", "application/json")
if s := handleCmdQQ(cmd, int(uid), int64(qq)); s != "" {
fmt.Fprint(w, s)
} else {
fmt.Fprint(w, "null")
}
}
// 显示 favicon
func faviconHandler(w http.ResponseWriter, r *http.Request) {
http.ServeFile(w, r, logoFile)
}
// 打印日志
func logHandler(w http.ResponseWriter, r *http.Request) {
logString.Lock()
defer logString.Unlock()
fmt.Fprint(w, logString.str.String())
}
// 打印帮助
func helpHandler(w http.ResponseWriter, r *http.Request) {
fmt.Fprint(w, webHelp)
}
// 打印 web 请求
func printRequestURI(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
if *isNoGUI {
log.Println("处理 web 请求:" + r.RequestURI)
}
next.ServeHTTP(w, r)
})
}
// web API 服务器
func webAPI() {
defer func() {
if err := recover(); err != nil {
lPrintErr("Recovering from panic in webAPI(), the error is:", err)
lPrintErr("web API 服务器发生错误,尝试重启 web API 服务器")
time.Sleep(2 * time.Second)
go webAPI()
}
}()
lPrintln("启动 web API 服务器,现在可以通过 " + address(config.WebPort) + " 来查看状态和发送命令")
r := mux.NewRouter()
r.HandleFunc("/favicon.ico", faviconHandler)
r.HandleFunc("/log", logHandler)
r.HandleFunc("/help", helpHandler)
r.HandleFunc("/", helpHandler)
r.HandleFunc("/{cmd}", cmdHandler)
r.HandleFunc("/{cmd}/{uid:[1-9][0-9]*}", cmdUIDHandler)
r.HandleFunc("/{cmd}/{uid:[1-9][0-9]*}/{qq:[1-9][0-9]*}", cmdQQHandler)
r.Use(printRequestURI)
// 跨域处理
handler := cors.Default().Handler(r)
apiSrv = &http.Server{
Addr: fmt.Sprintf(":%d", config.WebPort),
WriteTimeout: 15 * time.Second,
ReadTimeout: 15 * time.Second,
IdleTimeout: 60 * time.Second,
Handler: handler,
}
err := apiSrv.ListenAndServe()
if err != http.ErrServerClosed {
lPrintln(err)
panic(err)
}
}
// 启动 web API server
func startWebAPI() bool {
if *isWebAPI {
lPrintWarn("已经启动过 web API 服务器")
} else {
*isWebAPI = true
go webAPI()
}
return true
}
// 停止 web API server
func stopWebAPI() bool {
if *isWebAPI {
*isWebAPI = false
lPrintln("停止 web API 服务器")
ctx, cancel := context.WithCancel(mainCtx)
defer cancel()
if err := apiSrv.Shutdown(ctx); err != nil {
lPrintErr("web API 服务器关闭错误:", err)
lPrintWarn("强行关闭 web API 服务器")
cancel()
}
} else {
lPrintWarn("没有启动 web API 服务器")
}
return true
}