webhook.go 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262
  1. package controller
  2. import (
  3. "encoding/json"
  4. "github.com/gin-gonic/gin"
  5. "github.com/tidwall/gjson"
  6. "io"
  7. "message-pusher/common"
  8. "message-pusher/model"
  9. "net/http"
  10. "strconv"
  11. "strings"
  12. )
  13. func GetAllWebhooks(c *gin.Context) {
  14. userId := c.GetInt("id")
  15. p, _ := strconv.Atoi(c.Query("p"))
  16. if p < 0 {
  17. p = 0
  18. }
  19. webhooks, err := model.GetWebhooksByUserId(userId, p*common.ItemsPerPage, common.ItemsPerPage)
  20. if err != nil {
  21. c.JSON(http.StatusOK, gin.H{
  22. "success": false,
  23. "message": err.Error(),
  24. })
  25. return
  26. }
  27. c.JSON(http.StatusOK, gin.H{
  28. "success": true,
  29. "message": "",
  30. "data": webhooks,
  31. })
  32. return
  33. }
  34. func SearchWebhooks(c *gin.Context) {
  35. userId := c.GetInt("id")
  36. keyword := c.Query("keyword")
  37. if strings.HasPrefix(keyword, common.ServerAddress+"/webhook/") {
  38. keyword = strings.TrimPrefix(keyword, common.ServerAddress+"/webhook/")
  39. }
  40. webhooks, err := model.SearchWebhooks(userId, keyword)
  41. if err != nil {
  42. c.JSON(http.StatusOK, gin.H{
  43. "success": false,
  44. "message": err.Error(),
  45. })
  46. return
  47. }
  48. c.JSON(http.StatusOK, gin.H{
  49. "success": true,
  50. "message": "",
  51. "data": webhooks,
  52. })
  53. return
  54. }
  55. func GetWebhook(c *gin.Context) {
  56. id, err := strconv.Atoi(c.Param("id"))
  57. userId := c.GetInt("id")
  58. if err != nil {
  59. c.JSON(http.StatusOK, gin.H{
  60. "success": false,
  61. "message": err.Error(),
  62. })
  63. return
  64. }
  65. webhook_, err := model.GetWebhookById(id, userId)
  66. if err != nil {
  67. c.JSON(http.StatusOK, gin.H{
  68. "success": false,
  69. "message": err.Error(),
  70. })
  71. return
  72. }
  73. c.JSON(http.StatusOK, gin.H{
  74. "success": true,
  75. "message": "",
  76. "data": webhook_,
  77. })
  78. return
  79. }
  80. func AddWebhook(c *gin.Context) {
  81. webhook_ := model.Webhook{}
  82. err := c.ShouldBindJSON(&webhook_)
  83. if err != nil {
  84. c.JSON(http.StatusOK, gin.H{
  85. "success": false,
  86. "message": err.Error(),
  87. })
  88. return
  89. }
  90. if len(webhook_.Name) == 0 || len(webhook_.Name) > 20 {
  91. c.JSON(http.StatusOK, gin.H{
  92. "success": false,
  93. "message": "通道名称长度必须在1-20之间",
  94. })
  95. return
  96. }
  97. cleanWebhook := model.Webhook{
  98. UserId: c.GetInt("id"),
  99. Name: webhook_.Name,
  100. Status: common.WebhookStatusEnabled,
  101. Link: common.GetUUID(),
  102. CreatedTime: common.GetTimestamp(),
  103. Channel: webhook_.Channel,
  104. ExtractRule: webhook_.ExtractRule,
  105. ConstructRule: webhook_.ConstructRule,
  106. }
  107. err = cleanWebhook.Insert()
  108. if err != nil {
  109. c.JSON(http.StatusOK, gin.H{
  110. "success": false,
  111. "message": err.Error(),
  112. })
  113. return
  114. }
  115. c.JSON(http.StatusOK, gin.H{
  116. "success": true,
  117. "message": "",
  118. })
  119. return
  120. }
  121. func DeleteWebhook(c *gin.Context) {
  122. id, _ := strconv.Atoi(c.Param("id"))
  123. userId := c.GetInt("id")
  124. _, err := model.DeleteWebhookById(id, userId)
  125. if err != nil {
  126. c.JSON(http.StatusOK, gin.H{
  127. "success": false,
  128. "message": err.Error(),
  129. })
  130. return
  131. }
  132. c.JSON(http.StatusOK, gin.H{
  133. "success": true,
  134. "message": "",
  135. })
  136. return
  137. }
  138. func UpdateWebhook(c *gin.Context) {
  139. userId := c.GetInt("id")
  140. statusOnly := c.Query("status_only")
  141. webhook_ := model.Webhook{}
  142. err := c.ShouldBindJSON(&webhook_)
  143. if err != nil {
  144. c.JSON(http.StatusOK, gin.H{
  145. "success": false,
  146. "message": err.Error(),
  147. })
  148. return
  149. }
  150. oldWebhook, err := model.GetWebhookById(webhook_.Id, userId)
  151. if err != nil {
  152. c.JSON(http.StatusOK, gin.H{
  153. "success": false,
  154. "message": err.Error(),
  155. })
  156. return
  157. }
  158. cleanWebhook := *oldWebhook
  159. if statusOnly != "" {
  160. cleanWebhook.Status = webhook_.Status
  161. } else {
  162. // If you add more fields, please also update webhook_.Update()
  163. cleanWebhook.Name = webhook_.Name
  164. cleanWebhook.ExtractRule = webhook_.ExtractRule
  165. cleanWebhook.ConstructRule = webhook_.ConstructRule
  166. cleanWebhook.Channel = webhook_.Channel
  167. }
  168. err = cleanWebhook.Update()
  169. if err != nil {
  170. c.JSON(http.StatusOK, gin.H{
  171. "success": false,
  172. "message": err.Error(),
  173. })
  174. return
  175. }
  176. c.JSON(http.StatusOK, gin.H{
  177. "success": true,
  178. "message": "",
  179. "data": cleanWebhook,
  180. })
  181. return
  182. }
  183. func TriggerWebhook(c *gin.Context) {
  184. jsonData, err := io.ReadAll(c.Request.Body)
  185. if err != nil {
  186. c.JSON(http.StatusBadRequest, gin.H{
  187. "success": false,
  188. "message": err.Error(),
  189. })
  190. return
  191. }
  192. reqText := string(jsonData)
  193. link := c.Param("link")
  194. webhook, err := model.GetWebhookByLink(link)
  195. if err != nil {
  196. c.JSON(http.StatusNotFound, gin.H{
  197. "success": false,
  198. "message": "Webhook 不存在",
  199. })
  200. return
  201. }
  202. if webhook.Status != common.WebhookStatusEnabled {
  203. c.JSON(http.StatusForbidden, gin.H{
  204. "success": false,
  205. "message": "Webhook 未启用",
  206. })
  207. return
  208. }
  209. user, err := model.GetUserById(webhook.UserId, false)
  210. if err != nil {
  211. c.JSON(http.StatusNotFound, gin.H{
  212. "success": false,
  213. "message": "用户不存在",
  214. })
  215. return
  216. }
  217. if user.Status != common.UserStatusEnabled {
  218. c.JSON(http.StatusForbidden, gin.H{
  219. "success": false,
  220. "message": "用户已被封禁",
  221. })
  222. return
  223. }
  224. extractRule := make(map[string]string)
  225. err = json.Unmarshal([]byte(webhook.ExtractRule), &extractRule)
  226. if err != nil {
  227. c.JSON(http.StatusInternalServerError, gin.H{
  228. "success": false,
  229. "message": "Webhook 提取规则解析失败",
  230. })
  231. return
  232. }
  233. for key, value := range extractRule {
  234. variableValue := gjson.Get(reqText, value).String()
  235. webhook.ConstructRule = common.Replace(webhook.ConstructRule, "$"+key, variableValue, -1)
  236. }
  237. constructRule := model.WebhookConstructRule{}
  238. err = json.Unmarshal([]byte(webhook.ConstructRule), &constructRule)
  239. if err != nil {
  240. c.JSON(http.StatusOK, gin.H{
  241. "success": false,
  242. "message": "Webhook 构建规则解析失败",
  243. })
  244. return
  245. }
  246. message := &model.Message{
  247. Channel: webhook.Channel,
  248. Title: constructRule.Title,
  249. Description: constructRule.Description,
  250. Content: constructRule.Content,
  251. URL: constructRule.URL,
  252. }
  253. processMessage(c, message, user, false)
  254. }