webhook.go 5.6 KB

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