notifier.go 2.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103
  1. // Package websocket provides WebSocket hub for real-time updates and notifications.
  2. package websocket
  3. import (
  4. "github.com/mhsanaei/3x-ui/v2/logger"
  5. "github.com/mhsanaei/3x-ui/v2/web/global"
  6. )
  7. // GetHub returns the global WebSocket hub instance
  8. func GetHub() *Hub {
  9. webServer := global.GetWebServer()
  10. if webServer == nil {
  11. return nil
  12. }
  13. hub := webServer.GetWSHub()
  14. if hub == nil {
  15. return nil
  16. }
  17. wsHub, ok := hub.(*Hub)
  18. if !ok {
  19. logger.Warning("WebSocket hub type assertion failed")
  20. return nil
  21. }
  22. return wsHub
  23. }
  24. // HasClients returns true if there are any WebSocket clients connected.
  25. // Use this to skip expensive work (DB queries, serialization) when no browser is open.
  26. func HasClients() bool {
  27. hub := GetHub()
  28. if hub == nil {
  29. return false
  30. }
  31. return hub.GetClientCount() > 0
  32. }
  33. // BroadcastStatus broadcasts server status update to all connected clients
  34. func BroadcastStatus(status any) {
  35. hub := GetHub()
  36. if hub != nil {
  37. hub.Broadcast(MessageTypeStatus, status)
  38. }
  39. }
  40. // BroadcastTraffic broadcasts traffic statistics update to all connected clients
  41. func BroadcastTraffic(traffic any) {
  42. hub := GetHub()
  43. if hub != nil {
  44. hub.Broadcast(MessageTypeTraffic, traffic)
  45. }
  46. }
  47. // BroadcastInbounds broadcasts inbounds list update to all connected clients
  48. func BroadcastInbounds(inbounds any) {
  49. hub := GetHub()
  50. if hub != nil {
  51. hub.Broadcast(MessageTypeInbounds, inbounds)
  52. }
  53. }
  54. // BroadcastOutbounds broadcasts outbounds list update to all connected clients
  55. func BroadcastOutbounds(outbounds any) {
  56. hub := GetHub()
  57. if hub != nil {
  58. hub.Broadcast(MessageTypeOutbounds, outbounds)
  59. }
  60. }
  61. // BroadcastNotification broadcasts a system notification to all connected clients
  62. func BroadcastNotification(title, message, level string) {
  63. hub := GetHub()
  64. if hub != nil {
  65. notification := map[string]string{
  66. "title": title,
  67. "message": message,
  68. "level": level, // info, warning, error, success
  69. }
  70. hub.Broadcast(MessageTypeNotification, notification)
  71. }
  72. }
  73. // BroadcastXrayState broadcasts Xray state change to all connected clients
  74. func BroadcastXrayState(state string, errorMsg string) {
  75. hub := GetHub()
  76. if hub != nil {
  77. stateUpdate := map[string]string{
  78. "state": state,
  79. "errorMsg": errorMsg,
  80. }
  81. hub.Broadcast(MessageTypeXrayState, stateUpdate)
  82. }
  83. }
  84. // BroadcastInvalidate sends a lightweight invalidate signal for the given data type,
  85. // telling connected frontends to re-fetch data via REST API.
  86. // Use this instead of BroadcastInbounds/BroadcastOutbounds when you know the payload
  87. // will be too large, to avoid wasting resources on serialization.
  88. func BroadcastInvalidate(dataType MessageType) {
  89. hub := GetHub()
  90. if hub != nil {
  91. hub.broadcastInvalidate(dataType)
  92. }
  93. }