chat.go 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368
  1. package admin
  2. // this is endpoint logic
  3. import (
  4. "encoding/json"
  5. "errors"
  6. "fmt"
  7. "net/http"
  8. "strconv"
  9. "github.com/owncast/owncast/controllers"
  10. "github.com/owncast/owncast/core/chat"
  11. "github.com/owncast/owncast/core/chat/events"
  12. "github.com/owncast/owncast/core/data"
  13. "github.com/owncast/owncast/core/user"
  14. "github.com/owncast/owncast/utils"
  15. log "github.com/sirupsen/logrus"
  16. )
  17. // ExternalUpdateMessageVisibility updates an array of message IDs to have the same visiblity.
  18. func ExternalUpdateMessageVisibility(integration user.ExternalAPIUser, w http.ResponseWriter, r *http.Request) {
  19. UpdateMessageVisibility(w, r)
  20. }
  21. // UpdateMessageVisibility updates an array of message IDs to have the same visiblity.
  22. func UpdateMessageVisibility(w http.ResponseWriter, r *http.Request) {
  23. type messageVisibilityUpdateRequest struct {
  24. IDArray []string `json:"idArray"`
  25. Visible bool `json:"visible"`
  26. }
  27. if r.Method != controllers.POST {
  28. controllers.WriteSimpleResponse(w, false, r.Method+" not supported")
  29. return
  30. }
  31. decoder := json.NewDecoder(r.Body)
  32. var request messageVisibilityUpdateRequest
  33. if err := decoder.Decode(&request); err != nil {
  34. log.Errorln(err)
  35. controllers.WriteSimpleResponse(w, false, "")
  36. return
  37. }
  38. if err := chat.SetMessagesVisibility(request.IDArray, request.Visible); err != nil {
  39. controllers.WriteSimpleResponse(w, false, err.Error())
  40. return
  41. }
  42. controllers.WriteSimpleResponse(w, true, "changed")
  43. }
  44. // BanIPAddress will manually ban an IP address.
  45. func BanIPAddress(w http.ResponseWriter, r *http.Request) {
  46. if !requirePOST(w, r) {
  47. return
  48. }
  49. configValue, success := getValueFromRequest(w, r)
  50. if !success {
  51. controllers.WriteSimpleResponse(w, false, "unable to ban IP address")
  52. return
  53. }
  54. if err := data.BanIPAddress(configValue.Value.(string), "manually added"); err != nil {
  55. controllers.WriteSimpleResponse(w, false, "error saving IP address ban")
  56. return
  57. }
  58. controllers.WriteSimpleResponse(w, true, "IP address banned")
  59. }
  60. // UnBanIPAddress will remove an IP address ban.
  61. func UnBanIPAddress(w http.ResponseWriter, r *http.Request) {
  62. if !requirePOST(w, r) {
  63. return
  64. }
  65. configValue, success := getValueFromRequest(w, r)
  66. if !success {
  67. controllers.WriteSimpleResponse(w, false, "unable to unban IP address")
  68. return
  69. }
  70. if err := data.RemoveIPAddressBan(configValue.Value.(string)); err != nil {
  71. controllers.WriteSimpleResponse(w, false, "error removing IP address ban")
  72. return
  73. }
  74. controllers.WriteSimpleResponse(w, true, "IP address unbanned")
  75. }
  76. // GetIPAddressBans will return all the banned IP addresses.
  77. func GetIPAddressBans(w http.ResponseWriter, r *http.Request) {
  78. bans, err := data.GetIPAddressBans()
  79. if err != nil {
  80. controllers.WriteSimpleResponse(w, false, err.Error())
  81. }
  82. controllers.WriteResponse(w, bans)
  83. }
  84. // UpdateUserEnabled enable or disable a single user by ID.
  85. func UpdateUserEnabled(w http.ResponseWriter, r *http.Request) {
  86. type blockUserRequest struct {
  87. UserID string `json:"userId"`
  88. Enabled bool `json:"enabled"`
  89. }
  90. if r.Method != controllers.POST {
  91. controllers.WriteSimpleResponse(w, false, r.Method+" not supported")
  92. return
  93. }
  94. decoder := json.NewDecoder(r.Body)
  95. var request blockUserRequest
  96. if err := decoder.Decode(&request); err != nil {
  97. log.Errorln(err)
  98. controllers.WriteSimpleResponse(w, false, err.Error())
  99. return
  100. }
  101. if request.UserID == "" {
  102. controllers.WriteSimpleResponse(w, false, "must provide userId")
  103. return
  104. }
  105. // Disable/enable the user
  106. if err := user.SetEnabled(request.UserID, request.Enabled); err != nil {
  107. log.Errorln("error changing user enabled status", err)
  108. controllers.WriteSimpleResponse(w, false, err.Error())
  109. return
  110. }
  111. // Hide/show the user's chat messages if disabling.
  112. // Leave hidden messages hidden to be safe.
  113. if !request.Enabled {
  114. if err := chat.SetMessageVisibilityForUserID(request.UserID, request.Enabled); err != nil {
  115. log.Errorln("error changing user messages visibility", err)
  116. controllers.WriteSimpleResponse(w, false, err.Error())
  117. return
  118. }
  119. }
  120. // Forcefully disconnect the user from the chat
  121. if !request.Enabled {
  122. clients, err := chat.GetClientsForUser(request.UserID)
  123. if len(clients) == 0 {
  124. // Nothing to do
  125. return
  126. }
  127. if err != nil {
  128. log.Errorln("error fetching clients for user: ", err)
  129. controllers.WriteSimpleResponse(w, false, err.Error())
  130. return
  131. }
  132. chat.DisconnectClients(clients)
  133. disconnectedUser := user.GetUserByID(request.UserID)
  134. _ = chat.SendSystemAction(fmt.Sprintf("**%s** has been removed from chat.", disconnectedUser.DisplayName), true)
  135. // Ban this user's IP address.
  136. for _, client := range clients {
  137. ipAddress := client.IPAddress
  138. reason := fmt.Sprintf("Banning of %s", disconnectedUser.DisplayName)
  139. if err := data.BanIPAddress(ipAddress, reason); err != nil {
  140. log.Errorln("error banning IP address: ", err)
  141. }
  142. }
  143. }
  144. controllers.WriteSimpleResponse(w, true, fmt.Sprintf("%s enabled: %t", request.UserID, request.Enabled))
  145. }
  146. // GetDisabledUsers will return all the disabled users.
  147. func GetDisabledUsers(w http.ResponseWriter, r *http.Request) {
  148. w.Header().Set("Content-Type", "application/json")
  149. users := user.GetDisabledUsers()
  150. controllers.WriteResponse(w, users)
  151. }
  152. // UpdateUserModerator will set the moderator status for a user ID.
  153. func UpdateUserModerator(w http.ResponseWriter, r *http.Request) {
  154. type request struct {
  155. UserID string `json:"userId"`
  156. IsModerator bool `json:"isModerator"`
  157. }
  158. if r.Method != controllers.POST {
  159. controllers.WriteSimpleResponse(w, false, r.Method+" not supported")
  160. return
  161. }
  162. decoder := json.NewDecoder(r.Body)
  163. var req request
  164. if err := decoder.Decode(&req); err != nil {
  165. controllers.WriteSimpleResponse(w, false, "")
  166. return
  167. }
  168. // Update the user object with new moderation access.
  169. if err := user.SetModerator(req.UserID, req.IsModerator); err != nil {
  170. controllers.WriteSimpleResponse(w, false, err.Error())
  171. return
  172. }
  173. // Update the clients for this user to know about the moderator access change.
  174. if err := chat.SendConnectedClientInfoToUser(req.UserID); err != nil {
  175. log.Debugln(err)
  176. }
  177. controllers.WriteSimpleResponse(w, true, fmt.Sprintf("%s is moderator: %t", req.UserID, req.IsModerator))
  178. }
  179. // GetModerators will return a list of moderator users.
  180. func GetModerators(w http.ResponseWriter, r *http.Request) {
  181. w.Header().Set("Content-Type", "application/json")
  182. users := user.GetModeratorUsers()
  183. controllers.WriteResponse(w, users)
  184. }
  185. // GetChatMessages returns all of the chat messages, unfiltered.
  186. func GetChatMessages(w http.ResponseWriter, r *http.Request) {
  187. w.Header().Set("Content-Type", "application/json")
  188. messages := chat.GetChatModerationHistory()
  189. controllers.WriteResponse(w, messages)
  190. }
  191. // SendSystemMessage will send an official "SYSTEM" message to chat on behalf of your server.
  192. func SendSystemMessage(integration user.ExternalAPIUser, w http.ResponseWriter, r *http.Request) {
  193. w.Header().Set("Content-Type", "application/json")
  194. var message events.SystemMessageEvent
  195. if err := json.NewDecoder(r.Body).Decode(&message); err != nil {
  196. controllers.InternalErrorHandler(w, err)
  197. return
  198. }
  199. if err := chat.SendSystemMessage(message.Body, false); err != nil {
  200. controllers.BadRequestHandler(w, err)
  201. }
  202. controllers.WriteSimpleResponse(w, true, "sent")
  203. }
  204. // SendSystemMessageToConnectedClient will handle incoming requests to send a single message to a single connected client by ID.
  205. func SendSystemMessageToConnectedClient(integration user.ExternalAPIUser, w http.ResponseWriter, r *http.Request) {
  206. w.Header().Set("Content-Type", "application/json")
  207. clientIDText, err := utils.ReadRestURLParameter(r, "clientId")
  208. if err != nil {
  209. controllers.BadRequestHandler(w, err)
  210. return
  211. }
  212. clientIDNumeric, err := strconv.ParseUint(clientIDText, 10, 32)
  213. if err != nil {
  214. controllers.BadRequestHandler(w, err)
  215. return
  216. }
  217. var message events.SystemMessageEvent
  218. if err := json.NewDecoder(r.Body).Decode(&message); err != nil {
  219. controllers.InternalErrorHandler(w, err)
  220. return
  221. }
  222. chat.SendSystemMessageToClient(uint(clientIDNumeric), message.Body)
  223. controllers.WriteSimpleResponse(w, true, "sent")
  224. }
  225. // SendUserMessage will send a message to chat on behalf of a user. *Depreciated*.
  226. func SendUserMessage(integration user.ExternalAPIUser, w http.ResponseWriter, r *http.Request) {
  227. w.Header().Set("Content-Type", "application/json")
  228. controllers.BadRequestHandler(w, errors.New("no longer supported. see /api/integrations/chat/send"))
  229. }
  230. // SendIntegrationChatMessage will send a chat message on behalf of an external chat integration.
  231. func SendIntegrationChatMessage(integration user.ExternalAPIUser, w http.ResponseWriter, r *http.Request) {
  232. w.Header().Set("Content-Type", "application/json")
  233. name := integration.DisplayName
  234. if name == "" {
  235. controllers.BadRequestHandler(w, errors.New("unknown integration for provided access token"))
  236. return
  237. }
  238. var event events.UserMessageEvent
  239. if err := json.NewDecoder(r.Body).Decode(&event); err != nil {
  240. controllers.InternalErrorHandler(w, err)
  241. return
  242. }
  243. event.SetDefaults()
  244. event.RenderBody()
  245. event.Type = "CHAT"
  246. if event.Empty() {
  247. controllers.BadRequestHandler(w, errors.New("invalid message"))
  248. return
  249. }
  250. event.User = &user.User{
  251. ID: integration.ID,
  252. DisplayName: name,
  253. DisplayColor: integration.DisplayColor,
  254. CreatedAt: integration.CreatedAt,
  255. IsBot: true,
  256. }
  257. if err := chat.Broadcast(&event); err != nil {
  258. controllers.BadRequestHandler(w, err)
  259. return
  260. }
  261. chat.SaveUserMessage(event)
  262. controllers.WriteSimpleResponse(w, true, "sent")
  263. }
  264. // SendChatAction will send a generic chat action.
  265. func SendChatAction(integration user.ExternalAPIUser, w http.ResponseWriter, r *http.Request) {
  266. w.Header().Set("Content-Type", "application/json")
  267. var message events.SystemActionEvent
  268. if err := json.NewDecoder(r.Body).Decode(&message); err != nil {
  269. controllers.InternalErrorHandler(w, err)
  270. return
  271. }
  272. message.SetDefaults()
  273. message.RenderBody()
  274. if err := chat.SendSystemAction(message.Body, false); err != nil {
  275. controllers.BadRequestHandler(w, err)
  276. return
  277. }
  278. controllers.WriteSimpleResponse(w, true, "sent")
  279. }
  280. // SetEnableEstablishedChatUserMode sets the requirement for a chat user
  281. // to be "established" for some time before taking part in chat.
  282. func SetEnableEstablishedChatUserMode(w http.ResponseWriter, r *http.Request) {
  283. if !requirePOST(w, r) {
  284. return
  285. }
  286. configValue, success := getValueFromRequest(w, r)
  287. if !success {
  288. controllers.WriteSimpleResponse(w, false, "unable to update chat established user only mode")
  289. return
  290. }
  291. if err := data.SetChatEstablishedUsersOnlyMode(configValue.Value.(bool)); err != nil {
  292. controllers.WriteSimpleResponse(w, false, err.Error())
  293. return
  294. }
  295. controllers.WriteSimpleResponse(w, true, "chat established users only mode updated")
  296. }