task.go 9.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399
  1. package core
  2. import (
  3. "encoding/json"
  4. "fmt"
  5. "regexp"
  6. "sort"
  7. "time"
  8. "github.com/cdle/sillyplus/core/common"
  9. "github.com/cdle/sillyplus/core/storage"
  10. "github.com/cdle/sillyplus/utils"
  11. "github.com/gin-gonic/gin"
  12. "github.com/robfig/cron/v3"
  13. )
  14. var tasks = MakeBucket("tasks")
  15. type TasksResult struct {
  16. Success bool `json:"success"`
  17. Data []*Tasks `json:"data"`
  18. Page int `json:"page"`
  19. Total int `json:"total"`
  20. Time time.Time `json:"time"`
  21. }
  22. type Sender struct {
  23. ChatID string `json:"chat_id"`
  24. UserID string `json:"user_id"`
  25. Platfrom string `json:"platform"`
  26. BotID string `json:"bot_id"`
  27. }
  28. type Tasks struct {
  29. Index int `json:"id"` //编号 顺序编号
  30. ID string `json:"task_id"` //任务ID
  31. Title string `json:"title"` //任务名
  32. Schedule string `json:"schedule"` //计划时间
  33. Senders []Sender `json:"senders"` //发送人
  34. Command string `json:"command"` //消息指令
  35. Scripts []string `json:"scripts"` //触发脚本
  36. CronID int `json:"cron_id"`
  37. CreatedAt int `json:"created_at"` //创建时间戳(秒)转换成日期
  38. Remark string `json:"remark"`
  39. Enable bool `json:"enable"`
  40. Handle func() `json:"-"`
  41. Icons []interface{} `json:"icons"`
  42. }
  43. var pts = []*Tasks{}
  44. func RegistTasks(pt *Tasks) {
  45. pt.Handle = func() {
  46. content := pt.Command
  47. for _, meta := range pt.Senders {
  48. adapter, _ := GetAdapter(meta.Platfrom, meta.BotID)
  49. if adapter != nil {
  50. sender := adapter.Sender2(nil)
  51. sender.SetFsps(&common.FakerSenderParams{
  52. Content: content,
  53. ChatID: meta.ChatID,
  54. UserID: meta.UserID,
  55. })
  56. for _, script := range pt.Scripts {
  57. for _, function := range Functions {
  58. if function.UUID == script {
  59. for i := range function.Rules {
  60. reg, err := regexp.Compile(function.Rules[i])
  61. if err == nil {
  62. if res := reg.FindStringSubmatch(content); len(res) > 0 {
  63. sender.SetMatch(res[1:])
  64. sender.SetParams(function.Params[i])
  65. }
  66. }
  67. }
  68. function.Handle(sender, nil)
  69. break
  70. }
  71. }
  72. }
  73. }
  74. }
  75. }
  76. cid, _ := CRON.AddFunc(pt.Schedule, pt.Handle)
  77. pt.CronID = int(cid)
  78. // console.Debug("已添加计划任务:%s(%v)", pt.Title, pt.CronID)
  79. }
  80. func init() {
  81. tasks.Foreach(func(b1, b2 []byte) error {
  82. pt := Tasks{}
  83. err := json.Unmarshal(b2, &pt)
  84. if err != nil {
  85. return nil
  86. }
  87. RegistTasks(&pt)
  88. pts = append(pts, &pt)
  89. return nil
  90. })
  91. sort.Sort(byCreatedAt2(pts))
  92. for i := range pts {
  93. pts[i].Index = i + 1
  94. }
  95. storage.Watch(tasks, nil, func(old, new, key string) *storage.Final {
  96. console.Log("已更新计划任务")
  97. ocg := Tasks{}
  98. ncg := Tasks{}
  99. json.Unmarshal([]byte(old), &ocg)
  100. json.Unmarshal([]byte(new), &ncg)
  101. tmp := pts
  102. if old != "" {
  103. if new == "" { // 删除
  104. if ocg.ID != "" {
  105. for i, cg := range tmp {
  106. if cg.ID == ocg.ID {
  107. CRON.Remove(cron.EntryID(tmp[i].CronID))
  108. tmp = append(tmp[:i], tmp[i+1:]...)
  109. break
  110. }
  111. }
  112. } else {
  113. return nil
  114. }
  115. } else { // 修改
  116. if ocg.ID != "" {
  117. for i, cg := range tmp {
  118. if cg.ID == ocg.ID {
  119. CRON.Remove(cron.EntryID(tmp[i].CronID))
  120. tmp[i] = &ncg
  121. RegistTasks(&ncg)
  122. //todo 增
  123. break
  124. }
  125. }
  126. } else {
  127. return nil
  128. }
  129. }
  130. } else { //创建
  131. if ncg.ID != "" {
  132. tmp = append(tmp, &ncg)
  133. RegistTasks(&ncg)
  134. //todo 增
  135. } else {
  136. return nil
  137. }
  138. }
  139. sort.Sort(byCreatedAt2(pts))
  140. for i := range tmp {
  141. tmp[i].Index = i + 1
  142. }
  143. pts = tmp
  144. return nil
  145. })
  146. GinApi(GET, "/api/tasks", RequireAuth, func(ctx *gin.Context) {
  147. current := utils.Int(ctx.Query("current"))
  148. pageSize := utils.Int(ctx.Query("pageSize"))
  149. rr := TasksResult{
  150. Success: true,
  151. }
  152. pts := pts
  153. rr.Total = len(pts)
  154. if current == 0 {
  155. current = 1
  156. }
  157. if pageSize == 0 {
  158. pageSize = 20
  159. }
  160. begin := (current - 1) * pageSize
  161. end := (current) * pageSize
  162. if end > rr.Total {
  163. end = rr.Total
  164. }
  165. if begin > end {
  166. begin = end
  167. }
  168. rr.Data = pts[begin:end]
  169. for i := range rr.Data {
  170. rr.Data[i].Icons = []interface{}{}
  171. for _, script := range rr.Data[i].Scripts {
  172. for _, f := range Functions {
  173. if f.UUID == script {
  174. if f.Icon != "" {
  175. rr.Data[i].Icons = append(rr.Data[i].Icons, map[string]interface{}{
  176. "link": f.Icon,
  177. "title": f.Title,
  178. })
  179. break
  180. }
  181. }
  182. }
  183. }
  184. }
  185. ctx.JSON(200, rr)
  186. })
  187. GinApi(POST, "/api/tasks", RequireAuth, func(ctx *gin.Context) {
  188. // 将请求的 JSON 数据解析为一个 map[string]interface{} 类型的变量
  189. var updateData map[string]interface{}
  190. err := ctx.BindJSON(&updateData)
  191. if err != nil {
  192. ctx.JSON(200, map[string]interface{}{
  193. "success": false,
  194. "errorMessage": err.Error(),
  195. })
  196. return
  197. }
  198. v, ok := updateData["task_id"]
  199. if !ok {
  200. ctx.JSON(200, map[string]interface{}{
  201. "success": false,
  202. "errorMessage": "任务ID不能为空",
  203. })
  204. return
  205. }
  206. task_id := v.(string)
  207. var tp = Tasks{
  208. ID: task_id,
  209. }
  210. tasks.First(&tp)
  211. for key, value := range updateData {
  212. switch key {
  213. case "title":
  214. if v, ok := value.(string); ok {
  215. tp.Title = v
  216. }
  217. case "remark":
  218. if v, ok := value.(string); ok {
  219. tp.Remark = v
  220. }
  221. case "schedule":
  222. if v, ok := value.(string); ok {
  223. tp.Schedule = v
  224. id, err := CRON.AddFunc(tp.Schedule, func() {})
  225. if err != nil {
  226. ctx.JSON(200, map[string]interface{}{
  227. "success": false,
  228. "errorMessage": "Cron表达式错误:" + err.Error(),
  229. })
  230. return
  231. }
  232. CRON.Remove(id)
  233. }
  234. case "senders":
  235. ss := []Sender{}
  236. err := json.Unmarshal(utils.JsonMarshal(value), &ss)
  237. if err != nil {
  238. ctx.JSON(200, map[string]interface{}{
  239. "success": false,
  240. "errorMessage": "Senders错误:" + err.Error(),
  241. })
  242. return
  243. }
  244. tp.Senders = ss
  245. case "command":
  246. if v, ok := value.(string); ok {
  247. tp.Command = v
  248. }
  249. case "scripts":
  250. if v, ok := value.([]interface{}); ok {
  251. tp.Scripts = toStringSlice(v)
  252. }
  253. case "enable":
  254. if v, ok := value.(bool); ok {
  255. tp.Enable = v
  256. }
  257. }
  258. }
  259. if tp.CreatedAt == 0 {
  260. tp.CreatedAt = int(time.Now().Unix())
  261. }
  262. tasks.Set(task_id, utils.JsonMarshal(tp))
  263. if err != nil {
  264. ctx.JSON(200, map[string]interface{}{
  265. "success": false,
  266. "errorMessage": err.Error(),
  267. })
  268. return
  269. }
  270. ctx.JSON(200, map[string]interface{}{
  271. "success": true,
  272. })
  273. })
  274. GinApi(DELETE, "/api/tasks", RequireAuth, func(ctx *gin.Context) {
  275. pt := &Tasks{}
  276. err := ctx.BindJSON(pt)
  277. if err != nil {
  278. ctx.JSON(200, map[string]interface{}{
  279. "success": false,
  280. "errorMessage": err.Error(),
  281. })
  282. return
  283. }
  284. if pt.ID == "" {
  285. ctx.JSON(200, map[string]interface{}{
  286. "success": false,
  287. "errorMessage": "任务ID不为空",
  288. })
  289. return
  290. }
  291. tasks.Set(pt.ID, "")
  292. ctx.JSON(200, map[string]interface{}{
  293. "success": true,
  294. })
  295. })
  296. GinApi(GET, "/api/task/selects", RequireAuth, func(ctx *gin.Context) {
  297. var scripts = map[string]string{}
  298. var task_id = ctx.Query("task_id")
  299. var pts = pts
  300. var chat_ids = []string{}
  301. var user_ids = []string{}
  302. for _, pt := range pts {
  303. if pt.ID == task_id {
  304. for _, s := range pt.Senders {
  305. if s.ChatID != "" {
  306. chat_ids = append(chat_ids, s.ChatID)
  307. }
  308. if s.UserID != "" {
  309. user_ids = append(user_ids, s.UserID)
  310. }
  311. }
  312. break
  313. }
  314. }
  315. functions := Functions
  316. for _, function := range functions {
  317. if function.UUID != "" {
  318. scripts[function.UUID] = function.Title + function.Suffix
  319. }
  320. }
  321. var user_names = []NicklabeL{}
  322. var group_names = []NicklabeL{{
  323. Label: "私聊",
  324. Value: "",
  325. }}
  326. nickname.Foreach(func(b1, b2 []byte) error {
  327. v := &Nickname{}
  328. code := string(b1)
  329. err := json.Unmarshal(b2, v)
  330. if err == nil {
  331. if v.Group {
  332. if Contains(chat_ids, code) {
  333. group_names = append(group_names, NicklabeL{
  334. Label: fmt.Sprintf("%s(%s)", v.Value, code),
  335. Value: code,
  336. })
  337. }
  338. } else {
  339. if Contains(user_ids, code) {
  340. user_names = append(user_names, NicklabeL{
  341. Label: fmt.Sprintf("%s(%s)", v.Value, code),
  342. Value: code,
  343. })
  344. }
  345. }
  346. }
  347. return nil
  348. })
  349. platforms := map[string][]string{}
  350. for _, plt := range getPltsArray() {
  351. platforms[plt] = GetAdapterBotsID(plt)
  352. }
  353. ctx.JSON(200, map[string]interface{}{
  354. "success": true,
  355. "data": map[string]interface{}{
  356. "scripts": scripts,
  357. "platforms": platforms,
  358. "user_names": user_names,
  359. "group_names": group_names,
  360. },
  361. })
  362. })
  363. GinApi(GET, "/api/tasks/run", RequireAuth, func(ctx *gin.Context) {
  364. var task_id = ctx.Query("task_id")
  365. for _, pt := range pts {
  366. if pt.ID == task_id {
  367. pt.Handle()
  368. }
  369. }
  370. ctx.JSON(200, map[string]interface{}{
  371. "success": true,
  372. })
  373. })
  374. }
  375. type byCreatedAt2 []*Tasks
  376. func (s byCreatedAt2) Len() int {
  377. return len(s)
  378. }
  379. func (s byCreatedAt2) Less(i, j int) bool {
  380. return s[i].CreatedAt > s[j].CreatedAt
  381. }
  382. func (s byCreatedAt2) Swap(i, j int) {
  383. s[i], s[j] = s[j], s[i]
  384. }