diff --git a/dao/im.go b/dao/im.go index 588c207..d8d2268 100644 --- a/dao/im.go +++ b/dao/im.go @@ -17,6 +17,7 @@ type Message struct { type Group struct { gorm.Model + AuthID int `gorm:"column:auth_id"` GroupName string `gorm:"column:group_name"` GroupInfo string `gorm:"column:group_info"` GroupType int `gorm:"column:group_type"` @@ -65,6 +66,18 @@ func GetMsgUserByIndex(from_user_id, to_user_id, msg_type, index, status int) ([ return msgs, res.Error } +type GroupMessage struct { + Message + UserName string `gorm:"column:name" json:"name"` +} + +func GetMsgGroupByIndex(group_id, index int) ([]GroupMessage, error) { + var msgs []GroupMessage + res := DB.Debug().Raw("select messages.*,users.name from messages join users on messages.from_user_id = users.id where type = 2 and group_id = ? order by created_at desc limit ?", group_id, 20*index).Scan(&msgs) + return msgs, res.Error + +} + // 获取邀请消息 func GetFriendGroupReq(user_id int) ([]Message, error) { var msgs []Message @@ -125,6 +138,14 @@ func FindMessageByID(id uint) []Message { return msgs } +// 通过id查找消息(包括name) +func FindMessageByID2(id uint) []GroupMessage { + var msgs []GroupMessage + DB.Debug().Raw("select messages.*,users.name from messages join users on messages.from_user_id = users.id where messages.id = ?", id).Scan(&msgs) + return msgs + +} + // 更新消息状态 func UpdateMessageStatus(id uint, status int) error { res := DB.Debug().Model(&Message{}).Where("id = ?", id).Update("status", status) @@ -133,7 +154,7 @@ func UpdateMessageStatus(id uint, status int) error { // 创建群聊,需要事务 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} + group := Group{GroupName: groupName, GroupInfo: groupInfo, GroupType: proto.MSG_TYPE_GROUP, GroupIcon: groupIcon, AuthID: user_id} //开启事务 tx := DB.Begin() if err := tx.Create(&group); err.Error != nil { @@ -160,10 +181,10 @@ func FindGroupUser(user_id, group_id int) []GroupUser { } // 加入群聊 -func JoinGroup(group_id, user_id int) error { +func JoinGroup(group_id, user_id int) (error, uint) { groupUser := GroupUser{GroupID: group_id, UserID: user_id} res := DB.Debug().Create(&groupUser) - return res.Error + return res.Error, groupUser.ID } // 退出群聊 @@ -186,16 +207,32 @@ type FriendRet struct { func FindFriends(user_id int) []FriendRet { var friends []FriendRet - DB.Debug().Raw("select users.id, users.name, users.email from users join friends on users.id = friends.friend_id where friends.user_id = ?", user_id).Scan(&friends) + DB.Debug().Raw("select users.id, users.name, users.email from users join friends on users.id = friends.friend_id where friends.user_id = ? and friends.deleted_at is null", user_id).Scan(&friends) return friends } +func GetGroups(user_id int) []Group { + var groups []Group + DB.Debug().Where("auth_id = ?", user_id).Find(&groups) + return groups +} func FindGroups(user_id int) []Group { var groups []Group - DB.Debug().Raw("select groups.* from groups join group_users on groups.id = group_users.group_id where group_users.user_id = ?", user_id).Scan(&groups) + DB.Debug().Raw("select groups.* from groups join group_users on groups.id = group_users.group_id where group_users.user_id = ? and group_users.deleted_at is null", user_id).Scan(&groups) return groups } +func FindGroupByID(group_id int) []Group { + var groups []Group + DB.Debug().Where("id = ?", group_id).Find(&groups) + return groups +} + +func UpdateGroup(group_id int, groupName, groupInfo, groupIcon string) error { + res := DB.Debug().Model(&Group{}).Where("id = ?", group_id).Updates(map[string]interface{}{"group_name": groupName, "group_info": groupInfo, "group_icon": groupIcon}) + return res.Error +} + type FriendRequest struct { ID int `json:"id"` IMID int `json:"im_id"` @@ -209,3 +246,9 @@ func GetFriendRequest(user_id int) []FriendRequest { DB.Debug().Raw("select users.id,users.name,users.email,users.age,messages.id as im_id from users join messages on users.id = messages.from_user_id where messages.to_user_id = ? and messages.type = ? and status = ?", user_id, proto.MSG_TYPE_FRIEND, 0).Scan(&users) return users } + +func FindGroupUsers(group_id int) []GroupUser { + var groupUsers []GroupUser + DB.Debug().Where("group_id = ?", group_id).Find(&groupUsers) + return groupUsers +} diff --git a/dao/user.go b/dao/user.go index 5f171be..a82521a 100644 --- a/dao/user.go +++ b/dao/user.go @@ -37,6 +37,11 @@ func FindUserByID(id int) []proto.User { DB.Debug().Where("id = ?", id).First(&users) return users } +func FindUserByID2(id int) User { + var user User + DB.Debug().Where("id = ?", id).First(&user) + return user +} func FindUserByUserID(id int) User { var user User @@ -54,7 +59,7 @@ func FindUserByName(name string) User { // 根据name模糊查询,邮箱也是,不查询密码 func FindUserByNameLike(name string) []proto.User { var users []proto.User - DB.Debug().Where("name LIKE ? OR email LIKE ?", "%"+name+"%", "%"+name+"%").Find(&users) + DB.Debug().Where("name LIKE ? OR email LIKE ?", "%"+name+"%", "%"+name+"%").Find(&users).Limit(32) return users } diff --git a/handler/im.go b/handler/im.go index d1f9084..6f11ffa 100644 --- a/handler/im.go +++ b/handler/im.go @@ -21,6 +21,7 @@ import ( type SMessage struct { To_user_id int `json:"to_user_id" form:"to_user_id"` Type int `json:"type" form:"type"` + GroupID int `json:"group_id" form:"group_id"` Msg string `json:"msg" form:"msg"` } @@ -28,6 +29,7 @@ type Message struct { ID int `json:"id" form:"id" ` To_user_id int `json:"to_user_id" form:"to_user_id" ` From_user_id int `json:"from_user_id" form:"from_user_id" ` + GroupID int `json:"group_id" form:"group_id"` Index int `json:"index" form:"index" ` Type int `json:"type" form:"type" ` } @@ -65,11 +67,13 @@ func SetUpIMGroup(router *gin.Engine) { //接受邀请,确认好友关系 imGroup.POST("/accept_invite", AcceptInvite) imGroup.POST("/create_group", CreateGroup) + imGroup.POST("/get_group", GetGroups) imGroup.GET("/sse_msg", ServerSendMsg) imGroup.GET("/ws_v2", ServerSsendMsgV2) imGroup.POST("/get_friend_list", GetFriendList) //获取好友列表,包括群聊 //获取好友请求 imGroup.POST("/get_friend_request", GetFriendRequest) + imGroup.POST("/del_friend_or_group", DelFriendOrGroup) } func generateRandomHexString(length int) (string, error) { bytes := make([]byte, length/2) // 16字节的字符串需要32个十六进制字符,即16个字节 @@ -79,6 +83,49 @@ func generateRandomHexString(length int) (string, error) { return hex.EncodeToString(bytes), nil } +func GetGroups(c *gin.Context) { + id, _ := c.Get("id") + user_id := int(id.(float64)) + data := service.GetGroups(user_id) + c.JSON(http.StatusOK, gin.H{"code": proto.SuccessCode, "data": data, "message": "success"}) + +} + +func DelFriendOrGroup(c *gin.Context) { + var req Message + user_id, _ := c.Get("id") + cid := int(user_id.(float64)) + if err := c.ShouldBind(&req); err == nil { + if req.Type == 1 { + if req.To_user_id == 0 { + c.JSON(http.StatusOK, gin.H{"error": "parameter error", "code": proto.ParameterError, "message": "failed"}) + return + } + err2 := service.DelFriendService(req.To_user_id, cid) + 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 if req.Type == 2 { + if req.GroupID == 0 { + c.JSON(http.StatusOK, gin.H{"error": "parameter error", "code": proto.ParameterError, "message": "failed"}) + return + } + err2 := service.QuitGroupService(cid, req.GroupID) + 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": "parameter error", "code": proto.ParameterError, "message": "failed"}) + } + } else { + c.JSON(http.StatusOK, gin.H{"error": err.Error(), "code": proto.ParameterError, "message": "failed"}) + } +} + func GetFriendList(c *gin.Context) { id, _ := c.Get("id") user_id := int(id.(float64)) @@ -91,13 +138,24 @@ func GetMessage(c *gin.Context) { id := int(user_id.(float64)) //解析参数 if err := c.ShouldBind(&req); err == nil { - fmt.Println(req) - msgs, err2 := service.GetMsgUserByIndexService(req.From_user_id, 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"}) + + if req.Type == 2 { + msgs, err2 := dao.GetMsgGroupByIndex(req.GroupID, req.Index) + if err2 == nil { + c.JSON(http.StatusOK, gin.H{"code": proto.SuccessCode, "data": msgs, "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": err2.Error(), "code": proto.OperationFailed, "message": "failed"}) + msgs, err2 := service.GetMsgUserByIndexService(req.From_user_id, id, req.Index, req.Type, req.From_user_id, req.GroupID) + if err2 == nil { + c.JSON(http.StatusOK, gin.H{"code": proto.SuccessCode, "data": msgs, "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"}) } @@ -149,7 +207,7 @@ func SendMessage(c *gin.Context) { if err := c.ShouldBind(&req); err == nil { var err2 error var mid uint - err2, mid = service.CreateGeneralMessageService(id, req.To_user_id, req.Type, req.Msg) + err2, mid = service.CreateGeneralMessageService(id, req.To_user_id, req.Type, req.GroupID, req.Msg) if err2 == nil { c.JSON(http.StatusOK, gin.H{"code": proto.SuccessCode, "message": "success", "data": mid}) } else { @@ -372,7 +430,7 @@ func ServerSsendMsgV2(c *gin.Context) { msg_id := worker.PopRedisListLeft(key) if msg_id != "" { msg_id_num, _ := strconv.ParseInt(msg_id, 10, 64) - msgs := dao.FindMessageByID(uint(msg_id_num)) + msgs := dao.FindMessageByID2(uint(msg_id_num)) if len(msgs) > 0 { msg := msgs[0] //发送消息 diff --git a/handler/user.go b/handler/user.go index 5e1ffdc..ef7fb8f 100644 --- a/handler/user.go +++ b/handler/user.go @@ -9,6 +9,7 @@ import ( "github.com/golang-jwt/jwt" "github.com/google/uuid" "time" + "videoplayer/dao" "videoplayer/proto" "videoplayer/service" "videoplayer/worker" @@ -25,6 +26,7 @@ func SetUpUserGroup(router *gin.Engine) { userGroup.POST("/sqr", SetQRStatus) userGroup.POST("/confirm", ConfirmQRLogin) userGroup.POST("/search", SearchHandler) + userGroup.POST("/info", GetUserInfo) } type RLReq struct { @@ -46,6 +48,14 @@ type SearchReq struct { ID int `json:"id" form:"id"` } +func GetUserInfo(c *gin.Context) { + id, _ := c.Get("id") + user_id := int(id.(float64)) + user := dao.FindUserByID2(user_id) + user.Password = "" //不返回密码 + c.JSON(200, gin.H{"code": proto.SuccessCode, "message": "success", "data": user}) +} + func GetScanUUID(c *gin.Context) { var ReqData QRReq if err := c.ShouldBind(&ReqData); err != nil { diff --git a/proto/conf.go b/proto/conf.go index 5e3fa2e..af1a95b 100644 --- a/proto/conf.go +++ b/proto/conf.go @@ -22,11 +22,12 @@ const ( const ( // 以下是消息类型 - MSG_TYPE_SIMPLE = 1 // 单聊 - MSG_TYPE_GROUP = 2 // 群聊 - MSG_TYPE_SYSTEM = 3 // 系统消息 - MSG_TYPE_FRIEND = 4 // 好友请求 - MSG_TYPE_GROUP_ADD = 5 // 加入群聊请求 + MSG_TYPE_SIMPLE = 1 // 单聊 + MSG_TYPE_GROUP = 2 // 群聊 + MSG_TYPE_SYSTEM = 3 // 系统消息 + MSG_TYPE_FRIEND = 4 // 好友请求 + MSG_TYPE_GROUP_ADD = 5 // 加入群聊请求 + MSG_TYPE_GROUP_INVI = 6 // 邀请加入群聊 // 以下是消息状态 MSG_STATUS_READ = 1 // 已读 diff --git a/service/imService.go b/service/imService.go index 0ed7563..13c878d 100644 --- a/service/imService.go +++ b/service/imService.go @@ -5,19 +5,20 @@ import ( "strconv" "time" "videoplayer/dao" + "videoplayer/proto" "videoplayer/worker" ) -func CreateGeneralMessageService(from_id, to_id, msg_type int, content string) (error, uint) { +func CreateGeneralMessageService(from_id, to_id, msg_type, group_id int, content string) (error, uint) { // 业务逻辑 var err error var id uint switch msg_type { - case 1: + case proto.MSG_TYPE_SIMPLE: //判断是否是好友 friend := dao.FindFriend(from_id, to_id) if len(friend) == 0 { - return errors.New("not a friend"), 0 + return errors.New("未添加好友"), 0 } err, id = dao.CreateSimpleMessage(from_id, to_id, content) res := worker.GetRedis("user_" + strconv.Itoa(to_id) + "_status_v2") @@ -25,27 +26,60 @@ func CreateGeneralMessageService(from_id, to_id, msg_type int, content string) ( //在线,存入redis worker.PushRedisListWithExpire("user_"+strconv.Itoa(to_id)+"_msg_ids", strconv.Itoa(int(id)), time.Second*300) } - case 2: - err, id = dao.CreateGeneralMessage(from_id, to_id, msg_type, 0, 0, content) + case proto.MSG_TYPE_GROUP: + if from_id == 0 || group_id == 0 || content == "" { + return errors.New("参数错误"), 0 + } + //判断该用户是否在群里 + groupUser := dao.FindGroupUser(from_id, group_id) + if len(groupUser) == 0 { + return errors.New("用户不在群里"), 0 + } + err, id = dao.CreateGeneralMessage(from_id, to_id, msg_type, 0, group_id, content) + //获取群里的用户 + users := dao.FindGroupUsers(group_id) + for _, user := range users { + if user.UserID == from_id { + continue + } + res := worker.GetRedis("user_" + strconv.Itoa(user.UserID) + "_status_v2") + if res == "1" { + //在线,存入redis + worker.PushRedisListWithExpire("user_"+strconv.Itoa(user.UserID)+"_msg_ids", strconv.Itoa(int(id)), time.Second*300) + } + } case 3: //user := dao.FindUserByID(to_id) // 系统消息,需要管理员权限 - err, id = dao.CreateGeneralMessage(from_id, to_id, msg_type, 0, 0, content) - case 4: + err, id = dao.CreateGeneralMessage(from_id, to_id, msg_type, 0, group_id, content) + case proto.MSG_TYPE_FRIEND: + res1 := dao.FindFriend(from_id, to_id) + if len(res1) > 0 { + // 已经有会话记录 + return errors.New("已是好友关系"), 0 + } res, _ := dao.GetMsgUserByIndex(from_id, to_id, 4, 1, 0) if len(res) > 0 { // 已经有会话记录,返回会话id - return nil, res[0].ID + return errors.New("已有请求"), res[0].ID } - 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, group_id, content) + case proto.MSG_TYPE_GROUP_ADD: + //加入群聊请求 + + case proto.MSG_TYPE_GROUP_INVI: + //邀请加群,直接加入 + //判断邀请人是否在群里 + groupUser := dao.FindGroupUser(from_id, group_id) + if len(groupUser) == 0 { + return errors.New("邀请人不在群里"), 0 } - //邀请加入群聊请求 - err, id = dao.CreateGeneralMessage(from_id, to_id, msg_type, 0, from_id, content) + //判断被邀请人是否在群里 + groupUser = dao.FindGroupUser(to_id, group_id) + if len(groupUser) > 0 { + return errors.New("已在群里"), 0 + } + err, id = dao.JoinGroup(group_id, to_id) default: // 未知消息类型 err = errors.New("unknown message type") @@ -53,15 +87,19 @@ func CreateGeneralMessageService(from_id, to_id, msg_type int, content string) ( return err, id } -func GetMsgUserByIndexService(from_id, to_id, index, msq_type, from_user_id int) ([]dao.Message, error) { +func GetMsgUserByIndexService(from_id, to_id, index, msq_type, from_user_id, group_id int) ([]dao.Message, error) { // 业务逻辑 + var msgs []dao.Message + var err error if index <= 0 || index > 100 { return nil, errors.New("index out of range") } - if msq_type == 4 { + if msq_type == proto.MSG_TYPE_FRIEND { from_id = from_user_id } - msgs, err := dao.GetMsgUserByIndex(from_id, to_id, msq_type, index, 0) + msgs, err = dao.GetMsgUserByIndex(from_id, to_id, msq_type, index, 0) + //群聊消息 + return msgs, err } @@ -86,7 +124,7 @@ func AddFriendService(id, from_user_id, to_user_id int) error { if len(groupUser) > 0 { return errors.New("already in the group") } - err := dao.JoinGroup(groupUser[0].GroupID, to_user_id) + err, _ := dao.JoinGroup(groupUser[0].GroupID, to_user_id) if err != nil { return err } @@ -129,3 +167,21 @@ func GetFriendRequest(user_id int) []dao.FriendRequest { users := dao.GetFriendRequest(user_id) return users } + +func DelFriendService(user_id, friend_id int) error { + //删除好友 + err := dao.DeleteFriend(user_id, friend_id) + return err +} + +func QuitGroupService(user_id, group_id int) error { + //退出群聊 + err := dao.QuitGroup(group_id, user_id) + return err +} + +func GetGroups(user_id int) []dao.Group { + //获取群聊 + groups := dao.GetGroups(user_id) + return groups +} diff --git a/worker/redis.go b/worker/redis.go index bc19b5f..da00887 100644 --- a/worker/redis.go +++ b/worker/redis.go @@ -17,9 +17,9 @@ func InitRedis() error { ctx := context.Background() // 连接redis redisClient = redis.NewClient(&redis.Options{ - Addr: proto.REDIS_ADDR, // Redis 服务器地址 - Password: proto.REDIS_PASSWORD, // 如果 Redis 设置了密码 - DB: proto.REIDS_DB, // 使用的数据库编号 + Addr: proto.REDIS_ADDR, // Redis 服务器地址 + //Password: proto.REDIS_PASSWORD, // 如果 Redis 设置了密码 + DB: proto.REIDS_DB, // 使用的数据库编号 }) // 验证 Redis 客户端是否可以正常工作