From bd668c3ae62867fe5fa8c56989e41d8ce3868470 Mon Sep 17 00:00:00 2001 From: junleea <354425203@qq.com> Date: Sun, 4 Aug 2024 21:01:06 +0800 Subject: [PATCH] =?UTF-8?q?=E6=B7=BB=E5=8A=A0=E7=94=A8=E6=88=B7=E8=81=8A?= =?UTF-8?q?=E5=A4=A9=E5=8A=9F=E8=83=BD=EF=BC=8C=E7=BE=A4=E7=BB=84=E6=9C=AA?= =?UTF-8?q?=E5=AE=8C=E6=88=90?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- dao/db.go | 1 + dao/im.go | 64 +++++++++++++++++++++++---------- handler/im.go | 57 +++++++++++++++++++++++++---- proto/conf.go | 9 ++--- service/imService.go | 85 ++++++++++++++++++++++++++++++++++++++------ 5 files changed, 178 insertions(+), 38 deletions(-) diff --git a/dao/db.go b/dao/db.go index 13b1e58..b25d46a 100644 --- a/dao/db.go +++ b/dao/db.go @@ -15,6 +15,7 @@ func Init() error { db, err := gorm.Open(mysql.Open(dsn), &gorm.Config{}) if err != nil { panic("failed to connect database") + return err } err = db.AutoMigrate(&User{}) if err != nil { diff --git a/dao/im.go b/dao/im.go index dd6c42e..1e83c43 100644 --- a/dao/im.go +++ b/dao/im.go @@ -12,7 +12,7 @@ type Message struct { GroupID int `gorm:"column:group_id"` Msg string `gorm:"column:msg"` Status int `gorm:"column:status"` //单聊时才有0,已读,2未读 - Type int `gorm:"column:type"` //1为单聊,2为群聊,3为系统消息 + Type int `gorm:"column:type"` //1为单聊,2为群聊,3为系统消息,4为好友请求,5为加入群聊请求 } type Group struct { @@ -37,22 +37,37 @@ type Friend struct { } // 创建单聊消息 -func CreateSimpleMessage(from_user_id, to_user_id int, message string) error { +func CreateSimpleMessage(from_user_id, to_user_id int, message string) (error, uint) { msg := Message{FromUserID: from_user_id, ToUserID: to_user_id, Msg: message, Type: proto.MSG_TYPE_SIMPLE, Status: proto.MSG_STATUS_UNREAD} - res := DB.Debug().Create(msg) - return res.Error + res := DB.Debug().Create(&msg) + return res.Error, msg.ID } -func CreateGeneralMessage(from_user_id, to_user_id, msg_type, status int, message string) error { - msg := Message{FromUserID: from_user_id, ToUserID: to_user_id, Msg: message, Type: msg_type, Status: status} - res := DB.Debug().Create(msg) - return res.Error +func CreateGeneralMessage(from_user_id, to_user_id, msg_type, status, group_id int, message string) (error error, id uint) { + msg := Message{FromUserID: from_user_id, ToUserID: to_user_id, Msg: message, Type: msg_type, Status: status, GroupID: group_id} + res := DB.Debug().Create(&msg) + return res.Error, msg.ID } // 每20个消息一组,请求index*20 -func GetMsgUserByIndex(from_user_id, to_user_id, msg_type, index int) ([]Message, error) { +func GetMsgUserByIndex(from_user_id, to_user_id, msg_type, index, status int) ([]Message, error) { var msgs []Message - res := DB.Debug().Where("from_user_id = ? and to_user_id = ? and type = ?", from_user_id, to_user_id, msg_type).Find(&msgs).Order("order by createAt DESC").Limit(20 * index) + var res *gorm.DB + if msg_type == 4 { + res = DB.Debug().Where("from_user_id = ? and to_user_id = ? and type = ? and status = ? ", from_user_id, to_user_id, msg_type, status).Find(&msgs).Order("created_at DESC").Limit(20 * index) + } else if msg_type == 1 { + //单聊,只有两个人的消息 + res = DB.Debug().Where("((from_user_id = ? and to_user_id = ?) or (from_user_id = ? and to_user_id = ?)) and type = ? ", from_user_id, to_user_id, to_user_id, from_user_id, msg_type).Find(&msgs).Order("created_at DESC").Limit(20 * index) + } else { + res = DB.Debug().Where("from_user_id = ? and to_user_id = ? and type = ? ", from_user_id, to_user_id, msg_type).Find(&msgs).Order("created_at DESC").Limit(20 * index) + } + return msgs, res.Error +} + +// 获取邀请消息 +func GetFriendGroupReq(user_id int) ([]Message, error) { + var msgs []Message + res := DB.Debug().Where("to_user_id = ? and type = ?", user_id, proto.MSG_TYPE_FRIEND).Find(&msgs) return msgs, res.Error } @@ -105,7 +120,7 @@ func DeleteFriend(user_id, friend_id int) error { // 通过id查找消息 func FindMessageByID(id uint) []Message { var msgs []Message - DB.Debug().Where("id = ?", id).Find(msgs) + DB.Debug().Where("id = ?", id).Find(&msgs) return msgs } @@ -116,24 +131,31 @@ func UpdateMessageStatus(id uint, status int) error { } // 创建群聊,需要事务 -func CreateGroup(group_name string, master_user_id int) uint { - group := Group{GroupName: group_name} +func CreateGroup(groupName, groupInfo, groupType, groupIcon string, user_id int) (error, uint) { + group := Group{GroupName: groupName, GroupInfo: groupInfo, GroupType: proto.MSG_TYPE_GROUP, GroupIcon: groupIcon} //开启事务 tx := DB.Begin() if err := tx.Create(&group); err.Error != nil { tx.Rollback() - return 0 + return err.Error, 0 } - groupUser := GroupUser{GroupID: int(group.ID), UserID: master_user_id, IsMaster: true} + groupUser := GroupUser{GroupID: int(group.ID), UserID: user_id, IsMaster: true} if err := tx.Create(&groupUser); err.Error != nil { tx.Rollback() - return 0 + return err.Error, 0 } //提交事务 if err := tx.Commit().Error; err != nil { - return 0 + return err, 0 } - return group.ID + return nil, group.ID +} + +// 查找用户是否在群聊 +func FindGroupUser(user_id, group_id int) []GroupUser { + var groupUsers []GroupUser + DB.Debug().Where("user_id = ? and group_id = ?", user_id, group_id).Find(&groupUsers) + return groupUsers } // 加入群聊 @@ -148,3 +170,9 @@ func QuitGroup(group_id, user_id int) error { res := DB.Debug().Delete(&GroupUser{}, "group_id = ? and user_id = ?", group_id, user_id) return res.Error } + +func FindFriend(from_user_id, to_user_id int) []Friend { + var friends []Friend + DB.Debug().Where("user_id = ? and friend_id = ?", from_user_id, to_user_id).Find(&friends) + return friends +} diff --git a/handler/im.go b/handler/im.go index 926774e..0089b9e 100644 --- a/handler/im.go +++ b/handler/im.go @@ -18,18 +18,26 @@ import ( ) type SMessage struct { - To_user_id int `json:"to_user_id" form:"to_user_id" binding:"required"` - Type int `json:"type" form:"type" binding:"required"` - Msg string `json:"msg" form:"msg" binding:"required"` + To_user_id int `json:"to_user_id" form:"to_user_id"` + Type int `json:"type" form:"type"` + Msg string `json:"msg" form:"msg"` } type Message struct { + ID int `json:"id"` To_user_id int `json:"to_user_id"` From_user_id int `json:"from_user_id"` Index int `json:"index"` Type int `json:"type"` } +type CGroup struct { + Group_name string `json:"group_name" form:"group_name"` + Group_info string `json:"group_info" form:"group_info"` + Group_type string `json:"group_type" form:"group_type"` + Group_icon string `json:"group_icon" form:"group_icon"` +} + var ( upgrader = websocket.Upgrader{ ReadBufferSize: 1024, @@ -53,6 +61,9 @@ func SetUpIMGroup(router *gin.Engine) { imGroup.GET("/ws", SRMessage) imGroup.POST("/send_message", SendMessage) imGroup.POST("/get_message", GetMessage) + //接受邀请,确认好友关系 + imGroup.POST("/accept_invite", AcceptInvite) + imGroup.POST("/create_group", CreateGroup) } func generateRandomHexString(length int) (string, error) { bytes := make([]byte, length/2) // 16字节的字符串需要32个十六进制字符,即16个字节 @@ -66,7 +77,8 @@ func GetMessage(c *gin.Context) { user_id, _ := c.Get("id") id := int(user_id.(float64)) if err := c.ShouldBind(&req); err == nil { - msgs, err2 := service.GetMsgUserByIndexService(id, req.To_user_id, req.Index, req.Type) + fmt.Println(req) + msgs, err2 := service.GetMsgUserByIndexService(id, req.To_user_id, req.Index, req.Type, req.From_user_id) if err2 == nil { c.JSON(http.StatusOK, gin.H{"code": proto.SuccessCode, "data": msgs, "message": "success"}) } else { @@ -77,15 +89,48 @@ func GetMessage(c *gin.Context) { } } +func CreateGroup(c *gin.Context) { + var req CGroup + id, _ := c.Get("id") + user_id := int(id.(float64)) + if err := c.ShouldBind(&req); err == nil { + err2, id := service.CreateGroup(req.Group_name, req.Group_info, req.Group_type, req.Group_icon, user_id) + if err2 == nil { + c.JSON(http.StatusOK, gin.H{"code": proto.SuccessCode, "data": id, "message": "success"}) + } else { + c.JSON(http.StatusOK, gin.H{"error": err2.Error(), "code": proto.OperationFailed, "message": "failed"}) + } + } else { + c.JSON(http.StatusOK, gin.H{"error": err.Error(), "code": proto.ParameterError, "message": "failed"}) + } +} + +func AcceptInvite(c *gin.Context) { + var req Message + user_id, _ := c.Get("id") + cid := int(user_id.(float64)) + if err := c.ShouldBind(&req); err == nil { + err2 := service.AddFriendService(req.ID, cid, req.To_user_id) + if err2 == nil { + c.JSON(http.StatusOK, gin.H{"code": proto.SuccessCode, "message": "success"}) + } else { + c.JSON(http.StatusOK, gin.H{"error": err2.Error(), "code": proto.OperationFailed, "message": "failed"}) + } + } else { + c.JSON(http.StatusOK, gin.H{"error": err.Error(), "code": proto.ParameterError, "message": "failed"}) + } +} + func SendMessage(c *gin.Context) { var req SMessage user_id, _ := c.Get("id") id := int(user_id.(float64)) if err := c.ShouldBind(&req); err == nil { var err2 error - err2 = service.CreateGeneralMessageService(id, req.To_user_id, req.Type, req.Msg) + var mid uint + err2, mid = service.CreateGeneralMessageService(id, req.To_user_id, req.Type, req.Msg) if err2 == nil { - c.JSON(http.StatusOK, gin.H{"code": proto.SuccessCode, "message": "success"}) + c.JSON(http.StatusOK, gin.H{"code": proto.SuccessCode, "message": "success", "data": mid}) } else { c.JSON(http.StatusOK, gin.H{"error": err2.Error(), "code": proto.MsgSendFailed, "message": "failed"}) } diff --git a/proto/conf.go b/proto/conf.go index d553741..f3c0f8f 100644 --- a/proto/conf.go +++ b/proto/conf.go @@ -22,10 +22,11 @@ const ( const ( // 以下是消息类型 - MSG_TYPE_SIMPLE = 1 // 单聊 - MSG_TYPE_GROUP = 2 // 群聊 - MSG_TYPE_SYSTEM = 3 // 系统消息 - MSG_TYPE_FRIEND = 4 // 好友请求 + MSG_TYPE_SIMPLE = 1 // 单聊 + MSG_TYPE_GROUP = 2 // 群聊 + MSG_TYPE_SYSTEM = 3 // 系统消息 + MSG_TYPE_FRIEND = 4 // 好友请求 + MSG_TYPE_GROUP_ADD = 5 // 加入群聊请求 // 以下是消息状态 MSG_STATUS_READ = 1 // 已读 diff --git a/service/imService.go b/service/imService.go index f5f3ba3..7c038d3 100644 --- a/service/imService.go +++ b/service/imService.go @@ -5,33 +5,98 @@ import ( "videoplayer/dao" ) -func CreateGeneralMessageService(from_id, to_id, msg_type int, content string) error { +func CreateGeneralMessageService(from_id, to_id, msg_type int, content string) (error, uint) { // 业务逻辑 var err error + var id uint switch msg_type { case 1: - err = dao.CreateSimpleMessage(from_id, to_id, content) - case 2, 3: - err = dao.CreateGeneralMessage(from_id, to_id, msg_type, 0, content) + //判断是否是好友 + friend := dao.FindFriend(from_id, to_id) + if len(friend) == 0 { + return errors.New("not a friend"), 0 + } + err, id = dao.CreateSimpleMessage(from_id, to_id, content) + case 2: + err, id = dao.CreateGeneralMessage(from_id, to_id, msg_type, 0, 0, content) + case 3: + //user := dao.FindUserByID(to_id) + // 系统消息,需要管理员权限 + err, id = dao.CreateGeneralMessage(from_id, to_id, msg_type, 0, 0, content) case 4: - err = dao.CreateGeneralMessage(from_id, to_id, msg_type, 0, content) + res, _ := dao.GetMsgUserByIndex(from_id, to_id, 4, 1, 0) + if len(res) > 0 { + // 已经有会话记录 + return errors.New("already have a conversation"), 0 + } + err, id = dao.CreateGeneralMessage(from_id, to_id, msg_type, 0, 0, content) + case 5: + res, _ := dao.GetMsgUserByIndex(from_id, to_id, 5, 1, 0) + if len(res) > 0 { + // 已经有会话记录 + return errors.New("already have a conversation"), 0 + } + //邀请加入群聊请求 + err, id = dao.CreateGeneralMessage(from_id, to_id, msg_type, 0, from_id, content) default: // 未知消息类型 err = errors.New("unknown message type") } - return err + return err, id } -func GetMsgUserByIndexService(from_id, to_id, index, msq_type int) ([]dao.Message, error) { +func GetMsgUserByIndexService(from_id, to_id, index, msq_type, from_user_id int) ([]dao.Message, error) { // 业务逻辑 if index <= 0 || index > 100 { return nil, errors.New("index out of range") } - msgs, err := dao.GetMsgUserByIndex(from_id, to_id, index, msq_type) + if msq_type == 4 { + from_id = from_user_id + } + msgs, err := dao.GetMsgUserByIndex(from_id, to_id, msq_type, index, 0) return msgs, err } -func GetFriendGroupReqService(user_id int) ([]dao.Message, error) { +// AddFriendService 通过消息id添加好友,和加入群聊 +// id 消息id +// from_user_id 发送消息的用户id +// to_user_id 接收消息的用户id,及接受用户id +func AddFriendService(id, from_user_id, to_user_id int) error { // 业务逻辑 - return nil, nil + res := dao.FindMessageByID(uint(id)) + if res[0].FromUserID == to_user_id && res[0].ToUserID == from_user_id { + friend := dao.FindFriend(from_user_id, to_user_id) + if len(friend) > 0 { + return errors.New("already a friend") + } + dao.UpdateMessageStatus(res[0].ID, 1) + return dao.AddFriend(from_user_id, to_user_id) + } else if res[0].ToUserID == from_user_id && res[0].GroupID == to_user_id { + //加入群聊 + //查看是否已经加入 + groupUser := dao.FindGroupUser(from_user_id, to_user_id) + if len(groupUser) > 0 { + return errors.New("already in the group") + } + err := dao.JoinGroup(groupUser[0].GroupID, to_user_id) + if err != nil { + return err + } + err = dao.UpdateMessageStatus(res[0].ID, 1) + return err + } else { + return errors.New("no such message,cannot add friend") + } +} + +// CreateGroup 创建群聊 +// groupName 群聊名称 +// groupInfo 群聊信息 +// groupType 群聊类型 +// groupIcon 群聊图标 +// user_id 创建群的用户id +func CreateGroup(groupName, groupInfo, groupType, groupIcon string, user_id int) (error, uint) { + // 业务逻辑 + err, id := dao.CreateGroup(groupName, groupInfo, groupType, groupIcon, user_id) + return err, id }