webhooks.go 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216
  1. package data
  2. import (
  3. "errors"
  4. "fmt"
  5. "strings"
  6. "time"
  7. "github.com/owncast/owncast/models"
  8. log "github.com/sirupsen/logrus"
  9. )
  10. func createWebhooksTable() {
  11. log.Traceln("Creating webhooks table...")
  12. createTableSQL := `CREATE TABLE IF NOT EXISTS webhooks (
  13. "id" INTEGER PRIMARY KEY AUTOINCREMENT,
  14. "url" string NOT NULL,
  15. "events" TEXT NOT NULL,
  16. "timestamp" DATETIME DEFAULT CURRENT_TIMESTAMP,
  17. "last_used" DATETIME
  18. );`
  19. stmt, err := _db.Prepare(createTableSQL)
  20. if err != nil {
  21. log.Fatal(err)
  22. }
  23. defer stmt.Close()
  24. if _, err = stmt.Exec(); err != nil {
  25. log.Warnln(err)
  26. }
  27. }
  28. // InsertWebhook will add a new webhook to the database.
  29. func InsertWebhook(url string, events []models.EventType) (int, error) {
  30. log.Traceln("Adding new webhook")
  31. eventsString := strings.Join(events, ",")
  32. tx, err := _db.Begin()
  33. if err != nil {
  34. return 0, err
  35. }
  36. stmt, err := tx.Prepare("INSERT INTO webhooks(url, events) values(?, ?)")
  37. if err != nil {
  38. return 0, err
  39. }
  40. defer stmt.Close()
  41. insertResult, err := stmt.Exec(url, eventsString)
  42. if err != nil {
  43. return 0, err
  44. }
  45. if err = tx.Commit(); err != nil {
  46. return 0, err
  47. }
  48. newID, err := insertResult.LastInsertId()
  49. if err != nil {
  50. return 0, err
  51. }
  52. return int(newID), err
  53. }
  54. // DeleteWebhook will delete a webhook from the database.
  55. func DeleteWebhook(id int) error {
  56. log.Traceln("Deleting webhook")
  57. tx, err := _db.Begin()
  58. if err != nil {
  59. return err
  60. }
  61. stmt, err := tx.Prepare("DELETE FROM webhooks WHERE id = ?")
  62. if err != nil {
  63. return err
  64. }
  65. defer stmt.Close()
  66. result, err := stmt.Exec(id)
  67. if err != nil {
  68. return err
  69. }
  70. if rowsDeleted, _ := result.RowsAffected(); rowsDeleted == 0 {
  71. _ = tx.Rollback()
  72. return errors.New(fmt.Sprint(id) + " not found")
  73. }
  74. if err = tx.Commit(); err != nil {
  75. return err
  76. }
  77. return nil
  78. }
  79. // GetWebhooksForEvent will return all of the webhooks that want to be notified about an event type.
  80. func GetWebhooksForEvent(event models.EventType) []models.Webhook {
  81. webhooks := make([]models.Webhook, 0)
  82. query := `SELECT * FROM (
  83. WITH RECURSIVE split(id, url, event, rest) AS (
  84. SELECT id, url, '', events || ',' FROM webhooks
  85. UNION ALL
  86. SELECT id, url,
  87. substr(rest, 0, instr(rest, ',')),
  88. substr(rest, instr(rest, ',')+1)
  89. FROM split
  90. WHERE rest <> '')
  91. SELECT id, url, event
  92. FROM split
  93. WHERE event <> ''
  94. ) AS webhook WHERE event IS "` + event + `"`
  95. rows, err := _db.Query(query)
  96. if err != nil || rows.Err() != nil {
  97. log.Fatal(err)
  98. }
  99. defer rows.Close()
  100. for rows.Next() {
  101. var id int
  102. var url string
  103. if err := rows.Scan(&id, &url, &event); err != nil {
  104. log.Debugln(err)
  105. log.Error("There is a problem with the database.")
  106. break
  107. }
  108. singleWebhook := models.Webhook{
  109. ID: id,
  110. URL: url,
  111. }
  112. webhooks = append(webhooks, singleWebhook)
  113. }
  114. return webhooks
  115. }
  116. // GetWebhooks will return all the webhooks.
  117. func GetWebhooks() ([]models.Webhook, error) { //nolint
  118. webhooks := make([]models.Webhook, 0)
  119. query := "SELECT * FROM webhooks"
  120. rows, err := _db.Query(query)
  121. if err != nil {
  122. return webhooks, err
  123. }
  124. defer rows.Close()
  125. for rows.Next() {
  126. var id int
  127. var url string
  128. var events string
  129. var timestampString string
  130. var lastUsedString *string
  131. if err := rows.Scan(&id, &url, &events, &timestampString, &lastUsedString); err != nil {
  132. log.Error("There is a problem reading the database.", err)
  133. return webhooks, err
  134. }
  135. timestamp, err := time.Parse(time.RFC3339, timestampString)
  136. if err != nil {
  137. return webhooks, err
  138. }
  139. var lastUsed *time.Time
  140. if lastUsedString != nil {
  141. lastUsedTime, _ := time.Parse(time.RFC3339, *lastUsedString)
  142. lastUsed = &lastUsedTime
  143. }
  144. singleWebhook := models.Webhook{
  145. ID: id,
  146. URL: url,
  147. Events: strings.Split(events, ","),
  148. Timestamp: timestamp,
  149. LastUsed: lastUsed,
  150. }
  151. webhooks = append(webhooks, singleWebhook)
  152. }
  153. if err := rows.Err(); err != nil {
  154. return webhooks, err
  155. }
  156. return webhooks, nil
  157. }
  158. // SetWebhookAsUsed will update the last used time for a webhook.
  159. func SetWebhookAsUsed(webhook models.Webhook) error {
  160. tx, err := _db.Begin()
  161. if err != nil {
  162. return err
  163. }
  164. stmt, err := tx.Prepare("UPDATE webhooks SET last_used = CURRENT_TIMESTAMP WHERE id = ?")
  165. if err != nil {
  166. return err
  167. }
  168. defer stmt.Close()
  169. if _, err := stmt.Exec(webhook.ID); err != nil {
  170. return err
  171. }
  172. if err = tx.Commit(); err != nil {
  173. return err
  174. }
  175. return nil
  176. }