x
This commit is contained in:
+375
@@ -0,0 +1,375 @@
|
||||
package core
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"regexp"
|
||||
"sort"
|
||||
"time"
|
||||
|
||||
"github.com/cdle/sillyplus/core/common"
|
||||
"github.com/cdle/sillyplus/core/storage"
|
||||
"github.com/cdle/sillyplus/utils"
|
||||
"github.com/gin-gonic/gin"
|
||||
"github.com/robfig/cron/v3"
|
||||
)
|
||||
|
||||
var tasks = MakeBucket("tasks")
|
||||
|
||||
type TasksResult struct {
|
||||
Success bool `json:"success"`
|
||||
Data []*Tasks `json:"data"`
|
||||
Page int `json:"page"`
|
||||
Total int `json:"total"`
|
||||
Time time.Time `json:"time"`
|
||||
}
|
||||
|
||||
type Sender struct {
|
||||
ChatID string `json:"chat_id"`
|
||||
UserID string `json:"user_id"`
|
||||
Platfrom string `json:"platform"`
|
||||
}
|
||||
|
||||
type Tasks struct {
|
||||
Index int `json:"id"` //编号 顺序编号
|
||||
ID string `json:"task_id"` //任务ID
|
||||
Title string `json:"title"` //任务名
|
||||
Schedule string `json:"schedule"` //计划时间
|
||||
Senders []Sender `json:"senders"` //发送人
|
||||
Command string `json:"command"` //消息指令
|
||||
Scripts []string `json:"scripts"` //触发脚本
|
||||
CronID int `json:"cron_id"`
|
||||
CreatedAt int `json:"created_at"` //创建时间戳(秒)转换成日期
|
||||
Remark string `json:"remark"`
|
||||
Enable bool `json:"enable"`
|
||||
Handle func() `json:"-"`
|
||||
}
|
||||
|
||||
var pts = []*Tasks{}
|
||||
|
||||
func RegistTasks(pt *Tasks) {
|
||||
pt.Handle = func() {
|
||||
content := pt.Command
|
||||
for _, meta := range pt.Senders {
|
||||
adapter, _ := GetAdapter(meta.Platfrom, "")
|
||||
if adapter != nil {
|
||||
sender := adapter.Sender()
|
||||
sender.SetFsps(&common.FakerSenderParams{
|
||||
Content: content,
|
||||
ChatID: meta.ChatID,
|
||||
UserID: meta.UserID,
|
||||
})
|
||||
for _, script := range pt.Scripts {
|
||||
for _, function := range Functions {
|
||||
if function.UUID == script {
|
||||
for i := range function.Rules {
|
||||
reg, err := regexp.Compile(function.Rules[i])
|
||||
if err == nil {
|
||||
if res := reg.FindStringSubmatch(content); len(res) > 0 {
|
||||
sender.SetMatch(res[1:])
|
||||
sender.SetParams(function.Params[i])
|
||||
}
|
||||
}
|
||||
}
|
||||
function.Handle(sender, nil)
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
cid, _ := CRON.AddFunc(pt.Schedule, pt.Handle)
|
||||
pt.CronID = int(cid)
|
||||
console.Debug("已添加计划任务:%s(%v)", pt.Title, pt.CronID)
|
||||
}
|
||||
|
||||
func init() {
|
||||
tasks.Foreach(func(b1, b2 []byte) error {
|
||||
pt := Tasks{}
|
||||
err := json.Unmarshal(b2, &pt)
|
||||
if err != nil {
|
||||
return nil
|
||||
}
|
||||
RegistTasks(&pt)
|
||||
pts = append(pts, &pt)
|
||||
return nil
|
||||
})
|
||||
sort.Sort(byCreatedAt2(pts))
|
||||
for i := range cgs {
|
||||
cgs[i].Index = i + 1
|
||||
}
|
||||
storage.Watch(tasks, nil, func(old, new, key string) *storage.Final {
|
||||
console.Log("已更新计划任务")
|
||||
ocg := Tasks{}
|
||||
ncg := Tasks{}
|
||||
json.Unmarshal([]byte(old), &ocg)
|
||||
json.Unmarshal([]byte(new), &ncg)
|
||||
tmp := pts
|
||||
if old != "" {
|
||||
if new == "" { // 删除
|
||||
if ocg.ID != "" {
|
||||
for i, cg := range tmp {
|
||||
if cg.ID == ocg.ID {
|
||||
CRON.Remove(cron.EntryID(tmp[i].CronID))
|
||||
tmp = append(tmp[:i], tmp[i+1:]...)
|
||||
break
|
||||
}
|
||||
}
|
||||
} else {
|
||||
return nil
|
||||
}
|
||||
} else { // 修改
|
||||
if ocg.ID != "" {
|
||||
for i, cg := range tmp {
|
||||
if cg.ID == ocg.ID {
|
||||
CRON.Remove(cron.EntryID(tmp[i].CronID))
|
||||
tmp[i] = &ncg
|
||||
RegistTasks(&ncg)
|
||||
//todo 增
|
||||
break
|
||||
}
|
||||
}
|
||||
} else {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
} else { //创建
|
||||
if ncg.ID != "" {
|
||||
tmp = append(tmp, &ncg)
|
||||
RegistTasks(&ncg)
|
||||
//todo 增
|
||||
} else {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
sort.Sort(byCreatedAt2(pts))
|
||||
for i := range tmp {
|
||||
tmp[i].Index = i + 1
|
||||
}
|
||||
pts = tmp
|
||||
return nil
|
||||
})
|
||||
GinApi(GET, "/api/tasks", RequireAuth, func(ctx *gin.Context) {
|
||||
current := utils.Int(ctx.Query("current"))
|
||||
pageSize := utils.Int(ctx.Query("pageSize"))
|
||||
rr := TasksResult{
|
||||
Success: true,
|
||||
}
|
||||
pts := pts
|
||||
rr.Total = len(pts)
|
||||
if current == 0 {
|
||||
current = 1
|
||||
}
|
||||
if pageSize == 0 {
|
||||
pageSize = 20
|
||||
}
|
||||
begin := (current - 1) * pageSize
|
||||
end := (current) * pageSize
|
||||
if end > rr.Total {
|
||||
end = rr.Total
|
||||
}
|
||||
if begin > end {
|
||||
begin = end
|
||||
}
|
||||
rr.Data = pts[begin:end]
|
||||
ctx.JSON(200, rr)
|
||||
})
|
||||
GinApi(POST, "/api/tasks", RequireAuth, func(ctx *gin.Context) {
|
||||
// 将请求的 JSON 数据解析为一个 map[string]interface{} 类型的变量
|
||||
var updateData map[string]interface{}
|
||||
err := ctx.BindJSON(&updateData)
|
||||
if err != nil {
|
||||
ctx.JSON(200, map[string]interface{}{
|
||||
"success": false,
|
||||
"errorMessage": err.Error(),
|
||||
})
|
||||
return
|
||||
}
|
||||
v, ok := updateData["task_id"]
|
||||
if !ok {
|
||||
ctx.JSON(200, map[string]interface{}{
|
||||
"success": false,
|
||||
"errorMessage": "任务ID不能为空",
|
||||
})
|
||||
return
|
||||
}
|
||||
task_id := v.(string)
|
||||
var tp = Tasks{
|
||||
ID: task_id,
|
||||
}
|
||||
tasks.First(&tp)
|
||||
for key, value := range updateData {
|
||||
switch key {
|
||||
case "title":
|
||||
if v, ok := value.(string); ok {
|
||||
tp.Title = v
|
||||
}
|
||||
case "remark":
|
||||
if v, ok := value.(string); ok {
|
||||
tp.Remark = v
|
||||
}
|
||||
case "schedule":
|
||||
if v, ok := value.(string); ok {
|
||||
tp.Schedule = v
|
||||
id, err := CRON.AddFunc(tp.Schedule, func() {})
|
||||
if err != nil {
|
||||
ctx.JSON(200, map[string]interface{}{
|
||||
"success": false,
|
||||
"errorMessage": "Cron表达式错误:" + err.Error(),
|
||||
})
|
||||
return
|
||||
}
|
||||
CRON.Remove(id)
|
||||
}
|
||||
case "senders":
|
||||
ss := []Sender{}
|
||||
err := json.Unmarshal(utils.JsonMarshal(value), &ss)
|
||||
if err != nil {
|
||||
ctx.JSON(200, map[string]interface{}{
|
||||
"success": false,
|
||||
"errorMessage": "Senders错误:" + err.Error(),
|
||||
})
|
||||
}
|
||||
tp.Senders = ss
|
||||
case "command":
|
||||
if v, ok := value.(string); ok {
|
||||
tp.Command = v
|
||||
}
|
||||
case "scripts":
|
||||
if v, ok := value.([]interface{}); ok {
|
||||
tp.Scripts = toStringSlice(v)
|
||||
}
|
||||
case "enable":
|
||||
if v, ok := value.(bool); ok {
|
||||
tp.Enable = v
|
||||
}
|
||||
}
|
||||
}
|
||||
if tp.CreatedAt == 0 {
|
||||
tp.CreatedAt = int(time.Now().Unix())
|
||||
}
|
||||
tasks.Set(task_id, utils.JsonMarshal(tp))
|
||||
if err != nil {
|
||||
ctx.JSON(200, map[string]interface{}{
|
||||
"success": false,
|
||||
"errorMessage": err.Error(),
|
||||
})
|
||||
return
|
||||
}
|
||||
ctx.JSON(200, map[string]interface{}{
|
||||
"success": true,
|
||||
})
|
||||
})
|
||||
GinApi(DELETE, "/api/tasks", RequireAuth, func(ctx *gin.Context) {
|
||||
pt := &Tasks{}
|
||||
err := ctx.BindJSON(pt)
|
||||
if err != nil {
|
||||
ctx.JSON(200, map[string]interface{}{
|
||||
"success": false,
|
||||
"errorMessage": err.Error(),
|
||||
})
|
||||
return
|
||||
}
|
||||
if pt.ID == "" {
|
||||
ctx.JSON(200, map[string]interface{}{
|
||||
"success": false,
|
||||
"errorMessage": "任务ID不为空",
|
||||
})
|
||||
return
|
||||
}
|
||||
tasks.Set(pt.ID, "")
|
||||
ctx.JSON(200, map[string]interface{}{
|
||||
"success": true,
|
||||
})
|
||||
})
|
||||
GinApi(GET, "/api/task/selects", RequireAuth, func(ctx *gin.Context) {
|
||||
var scripts = map[string]string{}
|
||||
var task_id = ctx.Query("task_id")
|
||||
var pts = pts
|
||||
var chat_ids = []string{}
|
||||
var user_ids = []string{}
|
||||
for _, pt := range pts {
|
||||
if pt.ID == task_id {
|
||||
for _, s := range pt.Senders {
|
||||
if s.ChatID != "" {
|
||||
chat_ids = append(chat_ids, s.ChatID)
|
||||
}
|
||||
if s.UserID != "" {
|
||||
user_ids = append(user_ids, s.UserID)
|
||||
}
|
||||
}
|
||||
break
|
||||
}
|
||||
}
|
||||
functions := Functions
|
||||
for _, function := range functions {
|
||||
if function.UUID != "" {
|
||||
scripts[function.UUID] = function.Title + ".js"
|
||||
}
|
||||
}
|
||||
var user_names = []NicklabeL{}
|
||||
var group_names = []NicklabeL{{
|
||||
Label: "私聊",
|
||||
Value: "",
|
||||
}}
|
||||
nickname.Foreach(func(b1, b2 []byte) error {
|
||||
v := &Nickname{}
|
||||
code := string(b1)
|
||||
err := json.Unmarshal(b2, v)
|
||||
if err == nil {
|
||||
if v.Group {
|
||||
if Contains(user_ids, code) {
|
||||
user_names = append(user_names, NicklabeL{
|
||||
Label: fmt.Sprintf("%s(%s)", v.Value, code),
|
||||
Value: code,
|
||||
})
|
||||
}
|
||||
} else {
|
||||
if Contains(chat_ids, code) {
|
||||
group_names = append(group_names, NicklabeL{
|
||||
Label: fmt.Sprintf("%s(%s)", v.Value, code),
|
||||
Value: code,
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
return nil
|
||||
})
|
||||
ctx.JSON(200, map[string]interface{}{
|
||||
"success": true,
|
||||
"data": map[string]interface{}{
|
||||
"scripts": scripts,
|
||||
"platforms": getPltsArray(),
|
||||
"user_names": user_names,
|
||||
"group_names": group_names,
|
||||
},
|
||||
})
|
||||
})
|
||||
GinApi(GET, "/api/tasks/run", RequireAuth, func(ctx *gin.Context) {
|
||||
var task_id = ctx.Query("task_id")
|
||||
for _, pt := range pts {
|
||||
if pt.ID == task_id {
|
||||
pt.Handle()
|
||||
}
|
||||
}
|
||||
ctx.JSON(200, map[string]interface{}{
|
||||
"success": true,
|
||||
})
|
||||
})
|
||||
|
||||
}
|
||||
|
||||
type byCreatedAt2 []*Tasks
|
||||
|
||||
func (s byCreatedAt2) Len() int {
|
||||
return len(s)
|
||||
}
|
||||
|
||||
func (s byCreatedAt2) Less(i, j int) bool {
|
||||
return s[i].CreatedAt > s[j].CreatedAt
|
||||
}
|
||||
|
||||
func (s byCreatedAt2) Swap(i, j int) {
|
||||
s[i], s[j] = s[j], s[i]
|
||||
}
|
||||
Reference in New Issue
Block a user