Merge branch 'refs/heads/feature-im-gitea'

This commit is contained in:
junleea 2024-08-16 16:03:29 +08:00
commit b726b2c8f4
7 changed files with 214 additions and 41 deletions

View File

@ -17,6 +17,7 @@ type Message struct {
type Group struct { type Group struct {
gorm.Model gorm.Model
AuthID int `gorm:"column:auth_id"`
GroupName string `gorm:"column:group_name"` GroupName string `gorm:"column:group_name"`
GroupInfo string `gorm:"column:group_info"` GroupInfo string `gorm:"column:group_info"`
GroupType int `gorm:"column:group_type"` 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 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) { func GetFriendGroupReq(user_id int) ([]Message, error) {
var msgs []Message var msgs []Message
@ -125,6 +138,14 @@ func FindMessageByID(id uint) []Message {
return msgs 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 { func UpdateMessageStatus(id uint, status int) error {
res := DB.Debug().Model(&Message{}).Where("id = ?", id).Update("status", status) 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) { 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() tx := DB.Begin()
if err := tx.Create(&group); err.Error != nil { 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} groupUser := GroupUser{GroupID: group_id, UserID: user_id}
res := DB.Debug().Create(&groupUser) 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 { func FindFriends(user_id int) []FriendRet {
var friends []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 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 { func FindGroups(user_id int) []Group {
var groups []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 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 { type FriendRequest struct {
ID int `json:"id"` ID int `json:"id"`
IMID int `json:"im_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) 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 return users
} }
func FindGroupUsers(group_id int) []GroupUser {
var groupUsers []GroupUser
DB.Debug().Where("group_id = ?", group_id).Find(&groupUsers)
return groupUsers
}

View File

@ -39,6 +39,11 @@ func FindUserByID(id int) []proto.User {
DB.Debug().Where("id = ?", id).First(&users) DB.Debug().Where("id = ?", id).First(&users)
return 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 { func FindUserByUserID(id int) User {
var user User var user User
@ -56,7 +61,7 @@ func FindUserByName(name string) User {
// 根据name模糊查询邮箱也是,不查询密码 // 根据name模糊查询邮箱也是,不查询密码
func FindUserByNameLike(name string) []proto.User { func FindUserByNameLike(name string) []proto.User {
var users []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 return users
} }

View File

@ -21,6 +21,7 @@ import (
type SMessage struct { type SMessage struct {
To_user_id int `json:"to_user_id" form:"to_user_id"` To_user_id int `json:"to_user_id" form:"to_user_id"`
Type int `json:"type" form:"type"` Type int `json:"type" form:"type"`
GroupID int `json:"group_id" form:"group_id"`
Msg string `json:"msg" form:"msg"` Msg string `json:"msg" form:"msg"`
} }
@ -28,6 +29,7 @@ type Message struct {
ID int `json:"id" form:"id" ` ID int `json:"id" form:"id" `
To_user_id int `json:"to_user_id" form:"to_user_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" ` 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" ` Index int `json:"index" form:"index" `
Type int `json:"type" form:"type" ` Type int `json:"type" form:"type" `
} }
@ -65,11 +67,13 @@ func SetUpIMGroup(router *gin.Engine) {
//接受邀请,确认好友关系 //接受邀请,确认好友关系
imGroup.POST("/accept_invite", AcceptInvite) imGroup.POST("/accept_invite", AcceptInvite)
imGroup.POST("/create_group", CreateGroup) imGroup.POST("/create_group", CreateGroup)
imGroup.POST("/get_group", GetGroups)
imGroup.GET("/sse_msg", ServerSendMsg) imGroup.GET("/sse_msg", ServerSendMsg)
imGroup.GET("/ws_v2", ServerSsendMsgV2) imGroup.GET("/ws_v2", ServerSsendMsgV2)
imGroup.POST("/get_friend_list", GetFriendList) //获取好友列表,包括群聊 imGroup.POST("/get_friend_list", GetFriendList) //获取好友列表,包括群聊
//获取好友请求 //获取好友请求
imGroup.POST("/get_friend_request", GetFriendRequest) imGroup.POST("/get_friend_request", GetFriendRequest)
imGroup.POST("/del_friend_or_group", DelFriendOrGroup)
} }
func generateRandomHexString(length int) (string, error) { func generateRandomHexString(length int) (string, error) {
bytes := make([]byte, length/2) // 16字节的字符串需要32个十六进制字符即16个字节 bytes := make([]byte, length/2) // 16字节的字符串需要32个十六进制字符即16个字节
@ -79,6 +83,49 @@ func generateRandomHexString(length int) (string, error) {
return hex.EncodeToString(bytes), nil 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) { func GetFriendList(c *gin.Context) {
id, _ := c.Get("id") id, _ := c.Get("id")
user_id := int(id.(float64)) user_id := int(id.(float64))
@ -91,13 +138,24 @@ func GetMessage(c *gin.Context) {
id := int(user_id.(float64)) id := int(user_id.(float64))
//解析参数 //解析参数
if err := c.ShouldBind(&req); err == nil { 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 req.Type == 2 {
msgs, err2 := dao.GetMsgGroupByIndex(req.GroupID, req.Index)
if err2 == nil { if err2 == nil {
c.JSON(http.StatusOK, gin.H{"code": proto.SuccessCode, "data": msgs, "message": "success"}) c.JSON(http.StatusOK, gin.H{"code": proto.SuccessCode, "data": msgs, "message": "success"})
} else { } else {
c.JSON(http.StatusOK, gin.H{"error": err2.Error(), "code": proto.OperationFailed, "message": "failed"}) c.JSON(http.StatusOK, gin.H{"error": err2.Error(), "code": proto.OperationFailed, "message": "failed"})
} }
} else {
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 { } else {
c.JSON(http.StatusOK, gin.H{"error": err.Error(), "code": proto.ParameterError, "message": "failed"}) 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 { if err := c.ShouldBind(&req); err == nil {
var err2 error var err2 error
var mid uint 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 { if err2 == nil {
c.JSON(http.StatusOK, gin.H{"code": proto.SuccessCode, "message": "success", "data": mid}) c.JSON(http.StatusOK, gin.H{"code": proto.SuccessCode, "message": "success", "data": mid})
} else { } else {
@ -372,7 +430,7 @@ func ServerSsendMsgV2(c *gin.Context) {
msg_id := worker.PopRedisListLeft(key) msg_id := worker.PopRedisListLeft(key)
if msg_id != "" { if msg_id != "" {
msg_id_num, _ := strconv.ParseInt(msg_id, 10, 64) 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 { if len(msgs) > 0 {
msg := msgs[0] msg := msgs[0]
//发送消息 //发送消息

View File

@ -9,6 +9,7 @@ import (
"github.com/golang-jwt/jwt" "github.com/golang-jwt/jwt"
"github.com/google/uuid" "github.com/google/uuid"
"time" "time"
"videoplayer/dao"
"videoplayer/proto" "videoplayer/proto"
"videoplayer/service" "videoplayer/service"
"videoplayer/worker" "videoplayer/worker"
@ -25,6 +26,7 @@ func SetUpUserGroup(router *gin.Engine) {
userGroup.POST("/sqr", SetQRStatus) userGroup.POST("/sqr", SetQRStatus)
userGroup.POST("/confirm", ConfirmQRLogin) userGroup.POST("/confirm", ConfirmQRLogin)
userGroup.POST("/search", SearchHandler) userGroup.POST("/search", SearchHandler)
userGroup.POST("/info", GetUserInfo)
} }
type RLReq struct { type RLReq struct {
@ -46,6 +48,14 @@ type SearchReq struct {
ID int `json:"id" form:"id"` 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) { func GetScanUUID(c *gin.Context) {
var ReqData QRReq var ReqData QRReq
if err := c.ShouldBind(&ReqData); err != nil { if err := c.ShouldBind(&ReqData); err != nil {

View File

@ -27,6 +27,7 @@ const (
MSG_TYPE_SYSTEM = 3 // 系统消息 MSG_TYPE_SYSTEM = 3 // 系统消息
MSG_TYPE_FRIEND = 4 // 好友请求 MSG_TYPE_FRIEND = 4 // 好友请求
MSG_TYPE_GROUP_ADD = 5 // 加入群聊请求 MSG_TYPE_GROUP_ADD = 5 // 加入群聊请求
MSG_TYPE_GROUP_INVI = 6 // 邀请加入群聊
// 以下是消息状态 // 以下是消息状态
MSG_STATUS_READ = 1 // 已读 MSG_STATUS_READ = 1 // 已读

View File

@ -5,19 +5,20 @@ import (
"strconv" "strconv"
"time" "time"
"videoplayer/dao" "videoplayer/dao"
"videoplayer/proto"
"videoplayer/worker" "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 err error
var id uint var id uint
switch msg_type { switch msg_type {
case 1: case proto.MSG_TYPE_SIMPLE:
//判断是否是好友 //判断是否是好友
friend := dao.FindFriend(from_id, to_id) friend := dao.FindFriend(from_id, to_id)
if len(friend) == 0 { if len(friend) == 0 {
return errors.New("not a friend"), 0 return errors.New("未添加好友"), 0
} }
err, id = dao.CreateSimpleMessage(from_id, to_id, content) err, id = dao.CreateSimpleMessage(from_id, to_id, content)
res := worker.GetRedis("user_" + strconv.Itoa(to_id) + "_status_v2") 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 //在线,存入redis
worker.PushRedisListWithExpire("user_"+strconv.Itoa(to_id)+"_msg_ids", strconv.Itoa(int(id)), time.Second*300) worker.PushRedisListWithExpire("user_"+strconv.Itoa(to_id)+"_msg_ids", strconv.Itoa(int(id)), time.Second*300)
} }
case 2: case proto.MSG_TYPE_GROUP:
err, id = dao.CreateGeneralMessage(from_id, to_id, msg_type, 0, 0, content) 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: case 3:
//user := dao.FindUserByID(to_id) //user := dao.FindUserByID(to_id)
// 系统消息,需要管理员权限 // 系统消息,需要管理员权限
err, id = dao.CreateGeneralMessage(from_id, to_id, msg_type, 0, 0, content) err, id = dao.CreateGeneralMessage(from_id, to_id, msg_type, 0, group_id, content)
case 4: 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) res, _ := dao.GetMsgUserByIndex(from_id, to_id, 4, 1, 0)
if len(res) > 0 { if len(res) > 0 {
// 已经有会话记录,返回会话id // 已经有会话记录,返回会话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) err, id = dao.CreateGeneralMessage(from_id, to_id, msg_type, 0, group_id, content)
case 5: case proto.MSG_TYPE_GROUP_ADD:
res, _ := dao.GetMsgUserByIndex(from_id, to_id, 5, 1, 0) //加入群聊请求
if len(res) > 0 {
// 已经有会话记录 case proto.MSG_TYPE_GROUP_INVI:
return errors.New("already have a conversation"), 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, 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: default:
// 未知消息类型 // 未知消息类型
err = errors.New("unknown message type") err = errors.New("unknown message type")
@ -53,15 +87,19 @@ func CreateGeneralMessageService(from_id, to_id, msg_type int, content string) (
return err, id 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 { if index <= 0 || index > 100 {
return nil, errors.New("index out of range") return nil, errors.New("index out of range")
} }
if msq_type == 4 { if msq_type == proto.MSG_TYPE_FRIEND {
from_id = from_user_id 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 return msgs, err
} }
@ -86,7 +124,7 @@ func AddFriendService(id, from_user_id, to_user_id int) error {
if len(groupUser) > 0 { if len(groupUser) > 0 {
return errors.New("already in the group") 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 { if err != nil {
return err return err
} }
@ -129,3 +167,21 @@ func GetFriendRequest(user_id int) []dao.FriendRequest {
users := dao.GetFriendRequest(user_id) users := dao.GetFriendRequest(user_id)
return users 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

@ -18,7 +18,7 @@ func InitRedis() error {
// 连接redis // 连接redis
redisClient = redis.NewClient(&redis.Options{ redisClient = redis.NewClient(&redis.Options{
Addr: proto.REDIS_ADDR, // Redis 服务器地址 Addr: proto.REDIS_ADDR, // Redis 服务器地址
Password: proto.REDIS_PASSWORD, // 如果 Redis 设置了密码 //Password: proto.REDIS_PASSWORD, // 如果 Redis 设置了密码
DB: proto.REIDS_DB, // 使用的数据库编号 DB: proto.REIDS_DB, // 使用的数据库编号
}) })