/
service.go
119 lines (98 loc) · 3.79 KB
/
service.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
package service
import (
"github.com/go-park-mail-ru/2023_1_PracticalDev/internal/models"
"github.com/go-park-mail-ru/2023_1_PracticalDev/internal/notifications"
"github.com/go-park-mail-ru/2023_1_PracticalDev/internal/pkg/connectionservice"
"github.com/go-park-mail-ru/2023_1_PracticalDev/internal/pkg/constants"
"github.com/go-park-mail-ru/2023_1_PracticalDev/internal/pkg/xss"
ws "github.com/gorilla/websocket"
"go.uber.org/zap"
)
type service struct {
rep notifications.Repository
connService *connectionservice.Service
log *zap.Logger
}
func NewService(rep notifications.Repository, logger *zap.Logger) notifications.Service {
return &service{rep: rep, connService: connectionservice.NewService(logger), log: logger}
}
func (serv *service) HandleConnection(userID int, conn *ws.Conn) error {
serv.connService.AddConnection(userID, conn)
for {
_, message, err := conn.ReadMessage()
if err != nil {
serv.log.Debug("Read from connection error", zap.Error(err), zap.Int("user_id", userID),
zap.String("remote_addr", conn.RemoteAddr().String()))
serv.connService.RemoveConnection(userID, conn)
return nil
}
var req Request
err = req.UnmarshalJSON(message)
if err != nil {
serv.log.Debug("Failed to unmarshal message", zap.Error(err), zap.Int("user_id", userID),
zap.String("remote_addr", conn.RemoteAddr().String()))
msg := Message{Type: "response", Content: ResponseContent{Message: "json unmarshal error", Code: 40}}
data, err := msg.MarshalJSON()
if err != nil {
serv.log.Error("Marshal json failed", zap.Error(err), zap.Int("user_id", userID),
zap.String("remote_addr", conn.RemoteAddr().String()), zap.Any("message", msg))
serv.connService.RemoveConnection(userID, conn)
return nil
}
err = conn.WriteMessage(ws.TextMessage, data)
if err != nil {
serv.log.Debug("Write json failed", zap.Error(err), zap.Int("user_id", userID),
zap.String("remote_addr", conn.RemoteAddr().String()), zap.Any("message", msg))
serv.connService.RemoveConnection(userID, conn)
return nil
}
continue
}
serv.log.Debug("Got message", zap.Int("user_id", userID),
zap.String("remote_addr", conn.RemoteAddr().String()), zap.Any("message", req))
var msg Message
err = serv.rep.MarkAsRead(req.ID)
if err != nil {
msg = Message{Type: "response", Content: ResponseContent{Message: "mark as read error", Code: 50}}
} else {
msg = Message{Type: "response", Content: ResponseContent{
Message: "notification mark as read successfully",
Code: 20,
}}
}
data, err := msg.MarshalJSON()
if err != nil {
serv.log.Debug("Marshal json failed", zap.Error(err), zap.Int("user_id", userID),
zap.String("remote_addr", conn.RemoteAddr().String()), zap.Any("message", msg))
serv.connService.RemoveConnection(userID, conn)
return nil
}
err = conn.WriteMessage(ws.TextMessage, data)
if err != nil {
serv.log.Debug("Write json failed", zap.Error(err), zap.Int("user_id", userID),
zap.String("remote_addr", conn.RemoteAddr().String()), zap.Any("message", msg))
serv.connService.RemoveConnection(userID, conn)
return nil
}
}
}
func (serv *service) Create(userID int, notificationType string, data interface{}) error {
notificationID, err := serv.rep.Create(userID, notificationType, data)
if err != nil {
return err
}
notification, err := serv.rep.Get(notificationID)
if err != nil {
return err
}
if notification.Type == constants.NewComment {
nc := notification.Data.(models.NewCommentNotification)
nc.Text = xss.Sanitize(nc.Text)
notification.Data = nc
}
msg := Message{Type: "notification", Content: notification}
return serv.connService.Broadcast(msg, userID)
}
func (serv *service) ListUnreadByUser(userID int) ([]models.Notification, error) {
return serv.rep.ListUnreadByUser(userID)
}