群组管理及发送群聊消息,用户设置

This commit is contained in:
junleea 2024-08-16 15:25:10 +08:00
parent 4c20d06327
commit b1fec34718
7 changed files with 214 additions and 41 deletions

View File

@ -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
}

View File

@ -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
}

View File

@ -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]
//发送消息

View File

@ -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 {

View File

@ -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 // 已读

View File

@ -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
}

View File

@ -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 客户端是否可以正常工作