Compare commits
No commits in common. "a9d1d4542a7769c7e19f6c5d9bcda399bf7cdf84" and "f8e3dc4d6109ffbc0245d2b6a4cc8edbeddaafa9" have entirely different histories.
a9d1d4542a
...
f8e3dc4d61
30
dao/db.go
30
dao/db.go
|
|
@ -9,33 +9,28 @@ import (
|
||||||
|
|
||||||
var DB *gorm.DB
|
var DB *gorm.DB
|
||||||
|
|
||||||
func Init() error {
|
func Init() {
|
||||||
dsn := proto.MYSQL_DSN
|
dsn := proto.MYSQL_DSN
|
||||||
|
|
||||||
db, err := gorm.Open(mysql.Open(dsn), &gorm.Config{})
|
db, err := gorm.Open(mysql.Open(dsn), &gorm.Config{})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic("failed to connect database")
|
panic("failed to connect database")
|
||||||
return err
|
|
||||||
}
|
}
|
||||||
err = db.AutoMigrate(&User{})
|
err = db.AutoMigrate(&User{})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Println("user table:", err)
|
fmt.Println("user table:", err)
|
||||||
return err
|
|
||||||
} // 自动迁移,创建表,如果表已经存在,会自动更新表结构,不会删除表,只会创建不存在的表
|
} // 自动迁移,创建表,如果表已经存在,会自动更新表结构,不会删除表,只会创建不存在的表
|
||||||
err = db.AutoMigrate(&Video{})
|
err = db.AutoMigrate(&Video{})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Println("video table:", err)
|
fmt.Println("video table:", err)
|
||||||
return err
|
|
||||||
} // 自动迁移,创建表,如果表已经存在,会自动更新表结构,不会删除表,只会创建不存在的表
|
} // 自动迁移,创建表,如果表已经存在,会自动更新表结构,不会删除表,只会创建不存在的表
|
||||||
err = db.AutoMigrate(&Device{})
|
err = db.AutoMigrate(&Device{})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Println("device table:", err)
|
fmt.Println("device table:", err)
|
||||||
return err
|
|
||||||
} // 自动迁移,创建表,如果表已经存在,会自动更新表结构,不会删除表,只会创建不存在的表
|
} // 自动迁移,创建表,如果表已经存在,会自动更新表结构,不会删除表,只会创建不存在的表
|
||||||
err = db.AutoMigrate(&Logger{})
|
err = db.AutoMigrate(&Logger{})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Println("logger table:", err)
|
fmt.Println("logger table:", err)
|
||||||
return err
|
|
||||||
} // 自动迁移,创建表,如果表已经存在,会自动更新表结构,不会删除表,只会创建不存在的表
|
} // 自动迁移,创建表,如果表已经存在,会自动更新表结构,不会删除表,只会创建不存在的表
|
||||||
err = db.AutoMigrate(&CID{})
|
err = db.AutoMigrate(&CID{})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
@ -45,30 +40,7 @@ func Init() error {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Println("cidrunlog table:", err)
|
fmt.Println("cidrunlog table:", err)
|
||||||
} // 自动迁移,创建表,如果表已经存在,会自动更新表结构,不会删除表,只会创建不存在的表
|
} // 自动迁移,创建表,如果表已经存在,会自动更新表结构,不会删除表,只会创建不存在的表
|
||||||
|
|
||||||
err = db.AutoMigrate(&Message{})
|
|
||||||
if err != nil {
|
|
||||||
fmt.Println("message table:", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
err = db.AutoMigrate(&Group{})
|
|
||||||
if err != nil {
|
|
||||||
fmt.Println("usergroup table:", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
err = db.AutoMigrate(&GroupUser{})
|
|
||||||
if err != nil {
|
|
||||||
fmt.Println("groupuser table:", err)
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
err = db.AutoMigrate(&Friend{})
|
|
||||||
if err != nil {
|
|
||||||
fmt.Println("friend table:", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
DB = db
|
DB = db
|
||||||
return err
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func Close() {
|
func Close() {
|
||||||
|
|
|
||||||
196
dao/im.go
196
dao/im.go
|
|
@ -1,196 +0,0 @@
|
||||||
package dao
|
|
||||||
|
|
||||||
import (
|
|
||||||
"gorm.io/gorm"
|
|
||||||
"videoplayer/proto"
|
|
||||||
)
|
|
||||||
|
|
||||||
type Message struct {
|
|
||||||
gorm.Model
|
|
||||||
FromUserID int `gorm:"column:from_user_id"`
|
|
||||||
ToUserID int `gorm:"column:to_user_id"`
|
|
||||||
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为系统消息,4为好友请求,5为加入群聊请求
|
|
||||||
}
|
|
||||||
|
|
||||||
type Group struct {
|
|
||||||
gorm.Model
|
|
||||||
GroupName string `gorm:"column:group_name"`
|
|
||||||
GroupInfo string `gorm:"column:group_info"`
|
|
||||||
GroupType int `gorm:"column:group_type"`
|
|
||||||
GroupIcon string `gorm:"column:group_icon"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type GroupUser struct {
|
|
||||||
gorm.Model
|
|
||||||
GroupID int `gorm:"column:group_id"`
|
|
||||||
UserID int `gorm:"column:user_id"`
|
|
||||||
IsMaster bool `gorm:"column:is_master"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type Friend struct {
|
|
||||||
gorm.Model
|
|
||||||
UserID int `gorm:"column:user_id"`
|
|
||||||
FriendID int `gorm:"column:friend_id"`
|
|
||||||
}
|
|
||||||
|
|
||||||
// 创建单聊消息
|
|
||||||
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, msg.ID
|
|
||||||
}
|
|
||||||
|
|
||||||
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, status int) ([]Message, error) {
|
|
||||||
var msgs []Message
|
|
||||||
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
|
|
||||||
}
|
|
||||||
|
|
||||||
// 修改信息
|
|
||||||
func UpdateMessage() {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
// 添加好友
|
|
||||||
func AddFriend(user_id, friend_id int) error {
|
|
||||||
friend := Friend{UserID: user_id, FriendID: friend_id}
|
|
||||||
friend2 := Friend{UserID: friend_id, FriendID: user_id}
|
|
||||||
|
|
||||||
//开启事务
|
|
||||||
tx := DB.Begin()
|
|
||||||
if err := tx.Create(&friend); err.Error != nil {
|
|
||||||
tx.Rollback()
|
|
||||||
return err.Error
|
|
||||||
}
|
|
||||||
if err := tx.Create(&friend2); err.Error != nil {
|
|
||||||
tx.Rollback()
|
|
||||||
return err.Error
|
|
||||||
}
|
|
||||||
//提交事务
|
|
||||||
if err := tx.Commit().Error; err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
return error(nil)
|
|
||||||
}
|
|
||||||
|
|
||||||
// 删除好友,删除后双方都不是好友
|
|
||||||
func DeleteFriend(user_id, friend_id int) error {
|
|
||||||
//开启事务
|
|
||||||
tx := DB.Begin()
|
|
||||||
if err := tx.Delete(&Friend{}, "user_id = ? and friend_id = ?", user_id, friend_id); err.Error != nil {
|
|
||||||
tx.Rollback()
|
|
||||||
return err.Error
|
|
||||||
}
|
|
||||||
if err := tx.Delete(&Friend{}, "user_id = ? and friend_id = ?", friend_id, user_id); err.Error != nil {
|
|
||||||
tx.Rollback()
|
|
||||||
return err.Error
|
|
||||||
}
|
|
||||||
//提交事务
|
|
||||||
if err := tx.Commit().Error; err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
return error(nil)
|
|
||||||
}
|
|
||||||
|
|
||||||
// 通过id查找消息
|
|
||||||
func FindMessageByID(id uint) []Message {
|
|
||||||
var msgs []Message
|
|
||||||
DB.Debug().Where("id = ?", id).Find(&msgs)
|
|
||||||
return msgs
|
|
||||||
}
|
|
||||||
|
|
||||||
// 更新消息状态
|
|
||||||
func UpdateMessageStatus(id uint, status int) error {
|
|
||||||
res := DB.Debug().Model(&Message{}).Where("id = ?", id).Update("status", status)
|
|
||||||
return res.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}
|
|
||||||
//开启事务
|
|
||||||
tx := DB.Begin()
|
|
||||||
if err := tx.Create(&group); err.Error != nil {
|
|
||||||
tx.Rollback()
|
|
||||||
return err.Error, 0
|
|
||||||
}
|
|
||||||
groupUser := GroupUser{GroupID: int(group.ID), UserID: user_id, IsMaster: true}
|
|
||||||
if err := tx.Create(&groupUser); err.Error != nil {
|
|
||||||
tx.Rollback()
|
|
||||||
return err.Error, 0
|
|
||||||
}
|
|
||||||
//提交事务
|
|
||||||
if err := tx.Commit().Error; err != nil {
|
|
||||||
return err, 0
|
|
||||||
}
|
|
||||||
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
|
|
||||||
}
|
|
||||||
|
|
||||||
// 加入群聊
|
|
||||||
func JoinGroup(group_id, user_id int) error {
|
|
||||||
groupUser := GroupUser{GroupID: group_id, UserID: user_id}
|
|
||||||
res := DB.Debug().Create(&groupUser)
|
|
||||||
return res.Error
|
|
||||||
}
|
|
||||||
|
|
||||||
// 退出群聊
|
|
||||||
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
|
|
||||||
}
|
|
||||||
|
|
||||||
type FriendRet struct {
|
|
||||||
ID int `json:"id"` //用户id
|
|
||||||
Username string `json:"username"` //用户名
|
|
||||||
Avatar string `json:"avatar"` //头像
|
|
||||||
}
|
|
||||||
|
|
||||||
func FindFriends(user_id int) []FriendRet {
|
|
||||||
var friends []FriendRet
|
|
||||||
DB.Debug().Raw("select users.id, users.username, users.avatar from users join friends on users.id = friends.friend_id where friends.user_id = ?", user_id).Scan(&friends)
|
|
||||||
return friends
|
|
||||||
}
|
|
||||||
|
|
||||||
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)
|
|
||||||
return groups
|
|
||||||
}
|
|
||||||
|
|
@ -13,7 +13,6 @@ type User struct {
|
||||||
Email string `gorm:"column:email"`
|
Email string `gorm:"column:email"`
|
||||||
Password string `gorm:"column:password"`
|
Password string `gorm:"column:password"`
|
||||||
Gender string `gorm:"column:gender"`
|
Gender string `gorm:"column:gender"`
|
||||||
Role string `gorm:"column:role"`
|
|
||||||
CreateTime string `gorm:"column:create_time"`
|
CreateTime string `gorm:"column:create_time"`
|
||||||
UpdateTime string `gorm:"column:update_time"`
|
UpdateTime string `gorm:"column:update_time"`
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -108,10 +108,3 @@ func QuashAllDelay(user_id int, day int) int {
|
||||||
}
|
}
|
||||||
return int(res.RowsAffected)
|
return int(res.RowsAffected)
|
||||||
}
|
}
|
||||||
|
|
||||||
// 获取视频列表分页
|
|
||||||
func GetVideoListByPage(auth_id, page, pageSize int) []Video {
|
|
||||||
var videos []Video
|
|
||||||
DB.Debug().Where("auth_id = ? and isdelete = ?", auth_id, 0).Order("create_time DESC").Offset((page - 1) * pageSize).Limit(pageSize).Find(&videos) //Offset((page - 1) * pageSize).Limit(pageSize),分页,page从1开始,pageSize每页多少条,Offset是偏移量,Limit是限制条数
|
|
||||||
return videos
|
|
||||||
}
|
|
||||||
|
|
|
||||||
|
|
@ -162,7 +162,6 @@ func CIDCallback(c *gin.Context) {
|
||||||
// 获取用户ID
|
// 获取用户ID
|
||||||
token := c.Query("token")
|
token := c.Query("token")
|
||||||
cid_id := c.Query("id")
|
cid_id := c.Query("id")
|
||||||
fmt.Println("token:", token, "cid_id:", cid_id)
|
|
||||||
//将cid转换为int
|
//将cid转换为int
|
||||||
cid, _ := strconv.Atoi(cid_id)
|
cid, _ := strconv.Atoi(cid_id)
|
||||||
if token == "" || cid == 0 {
|
if token == "" || cid == 0 {
|
||||||
|
|
@ -171,8 +170,8 @@ func CIDCallback(c *gin.Context) {
|
||||||
}
|
}
|
||||||
res := dao.FindCIDByIDAndToken(cid, token)
|
res := dao.FindCIDByIDAndToken(cid, token)
|
||||||
if res.ID != 0 {
|
if res.ID != 0 {
|
||||||
user := dao.FindUserByID(res.Auth_id)
|
username, _ := c.Get("username")
|
||||||
go RunShell(user[0].Name, res.Url, res.Script, int(res.ID), res.Auth_id)
|
go RunShell(username.(string), res.Url, res.Script, int(res.ID), res.Auth_id)
|
||||||
c.JSON(200, gin.H{"code": proto.SuccessCode, "message": "success", "data": "success"})
|
c.JSON(200, gin.H{"code": proto.SuccessCode, "message": "success", "data": "success"})
|
||||||
} else {
|
} else {
|
||||||
c.JSON(200, gin.H{"error": "CID not found by id and token", "code": proto.OperationFailed, "message": "failed"})
|
c.JSON(200, gin.H{"error": "CID not found by id and token", "code": proto.OperationFailed, "message": "failed"})
|
||||||
|
|
|
||||||
|
|
@ -1,16 +1,11 @@
|
||||||
package handler
|
package handler
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"encoding/json"
|
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/gin-gonic/gin"
|
"github.com/gin-gonic/gin"
|
||||||
"github.com/gorilla/websocket"
|
|
||||||
"net/http"
|
"net/http"
|
||||||
"strconv"
|
|
||||||
"time"
|
|
||||||
"videoplayer/proto"
|
"videoplayer/proto"
|
||||||
"videoplayer/service"
|
"videoplayer/service"
|
||||||
"videoplayer/worker"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
type DeviceAddReq struct {
|
type DeviceAddReq struct {
|
||||||
|
|
@ -204,64 +199,3 @@ func Restart(ip string) bool {
|
||||||
}
|
}
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
// 接收及发送消息
|
|
||||||
func GetRealTimeImage(c *gin.Context) {
|
|
||||||
id, _ := c.Get("id")
|
|
||||||
id1 := int(id.(float64))
|
|
||||||
device_id := c.Query("device_id")
|
|
||||||
//字符串转int
|
|
||||||
device_id_int, _ := strconv.Atoi(device_id)
|
|
||||||
device := service.GetDevice(device_id_int, id1)
|
|
||||||
if device.ID == 0 {
|
|
||||||
c.JSON(http.StatusOK, gin.H{"code": proto.DataNotFound, "message": "device not found"})
|
|
||||||
return
|
|
||||||
}
|
|
||||||
//建立连接
|
|
||||||
// 升级HTTP连接为WebSocket连接
|
|
||||||
ws, err := upgrader.Upgrade(c.Writer, c.Request, nil)
|
|
||||||
clients[ws] = true
|
|
||||||
if err != nil {
|
|
||||||
// log.Println(err)
|
|
||||||
fmt.Println(err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
defer ws.Close()
|
|
||||||
worker.SetRedisWithExpire(strconv.Itoa(int(device.ID))+"_is_play", "1", time.Minute*5) //设置播放状态
|
|
||||||
// 接收客户端消息并发送到指定用户
|
|
||||||
|
|
||||||
go func(ws *websocket.Conn, device_id int) {
|
|
||||||
|
|
||||||
}(ws, device_id_int)
|
|
||||||
|
|
||||||
for {
|
|
||||||
if v := clients[ws]; v == true {
|
|
||||||
res2 := worker.PopRedisListLeft(device_id + "_frames")
|
|
||||||
var res3 []byte
|
|
||||||
var msg proto.Message
|
|
||||||
if res2 != "" {
|
|
||||||
//若有消息则发送消息
|
|
||||||
msg.Type = "img"
|
|
||||||
msg.Msg = res2
|
|
||||||
msg.From_user_id = id1
|
|
||||||
res3, _ = json.Marshal(msg)
|
|
||||||
} else {
|
|
||||||
//若无消息则发送心跳包
|
|
||||||
msg.Type = "check"
|
|
||||||
msg.Msg = "check"
|
|
||||||
msg.From_user_id = -1
|
|
||||||
res3, _ = json.Marshal(msg)
|
|
||||||
}
|
|
||||||
err2 := ws.WriteMessage(websocket.TextMessage, res3)
|
|
||||||
if err2 != nil {
|
|
||||||
clientsMux.Lock()
|
|
||||||
clients[ws] = false
|
|
||||||
clientsMux.Unlock()
|
|
||||||
//设置ws关闭状态信息
|
|
||||||
worker.SetRedisWithExpire(strconv.Itoa(int(device.ID))+"_is_play", "0", time.Minute*5) //设置播放状态
|
|
||||||
break
|
|
||||||
}
|
|
||||||
time.Sleep(time.Millisecond * 100) //设置延时100ms
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
|
||||||
165
handler/im.go
165
handler/im.go
|
|
@ -12,33 +12,10 @@ import (
|
||||||
"strconv"
|
"strconv"
|
||||||
"sync"
|
"sync"
|
||||||
"time"
|
"time"
|
||||||
"videoplayer/dao"
|
|
||||||
"videoplayer/proto"
|
"videoplayer/proto"
|
||||||
"videoplayer/service"
|
|
||||||
"videoplayer/worker"
|
"videoplayer/worker"
|
||||||
)
|
)
|
||||||
|
|
||||||
type SMessage struct {
|
|
||||||
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 (
|
var (
|
||||||
upgrader = websocket.Upgrader{
|
upgrader = websocket.Upgrader{
|
||||||
ReadBufferSize: 1024,
|
ReadBufferSize: 1024,
|
||||||
|
|
@ -60,13 +37,7 @@ func SetUpIMGroup(router *gin.Engine) {
|
||||||
imGroup := router.Group("/im")
|
imGroup := router.Group("/im")
|
||||||
imGroup.POST("/get_imKey", GetImKey)
|
imGroup.POST("/get_imKey", GetImKey)
|
||||||
imGroup.GET("/ws", SRMessage)
|
imGroup.GET("/ws", SRMessage)
|
||||||
imGroup.POST("/send_message", SendMessage)
|
|
||||||
imGroup.POST("/get_message", GetMessage)
|
|
||||||
//接受邀请,确认好友关系
|
|
||||||
imGroup.POST("/accept_invite", AcceptInvite)
|
|
||||||
imGroup.POST("/create_group", CreateGroup)
|
|
||||||
imGroup.GET("/sse_msg", ServerSendMsg)
|
|
||||||
imGroup.POST("/get_friend_list", GetFriendList) //获取好友列表,包括群聊
|
|
||||||
}
|
}
|
||||||
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个字节
|
||||||
|
|
@ -76,79 +47,6 @@ func generateRandomHexString(length int) (string, error) {
|
||||||
return hex.EncodeToString(bytes), nil
|
return hex.EncodeToString(bytes), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func GetFriendList(c *gin.Context) {
|
|
||||||
id, _ := c.Get("id")
|
|
||||||
user_id := int(id.(float64))
|
|
||||||
data := service.GetFriendList(user_id)
|
|
||||||
c.JSON(http.StatusOK, gin.H{"code": proto.SuccessCode, "data": data, "message": "success"})
|
|
||||||
}
|
|
||||||
func GetMessage(c *gin.Context) {
|
|
||||||
var req Message
|
|
||||||
user_id, _ := c.Get("id")
|
|
||||||
id := int(user_id.(float64))
|
|
||||||
if err := c.ShouldBind(&req); err == nil {
|
|
||||||
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 {
|
|
||||||
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 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
|
|
||||||
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", "data": mid})
|
|
||||||
} else {
|
|
||||||
c.JSON(http.StatusOK, gin.H{"error": err2.Error(), "code": proto.MsgSendFailed, "message": "failed"})
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
c.JSON(http.StatusOK, gin.H{"error": err.Error(), "code": proto.ParameterError, "message": "failed"})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func GetImKey(c *gin.Context) {
|
func GetImKey(c *gin.Context) {
|
||||||
id, _ := c.Get("id")
|
id, _ := c.Get("id")
|
||||||
var req proto.ImKeyReq
|
var req proto.ImKeyReq
|
||||||
|
|
@ -246,7 +144,7 @@ func SRMessage(c *gin.Context) {
|
||||||
}
|
}
|
||||||
defer ws.Close()
|
defer ws.Close()
|
||||||
res := worker.GetRedis(redis_key + "_connection")
|
res := worker.GetRedis(redis_key + "_connection")
|
||||||
worker.SetRedisWithExpire("user_"+strconv.Itoa(id1)+"_status", "1", time.Second*5)
|
worker.SetRedisWithExpire("user_"+id.(string)+"_status", "1", time.Second*5)
|
||||||
if res == "" {
|
if res == "" {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
@ -300,8 +198,8 @@ func SRMessage(c *gin.Context) {
|
||||||
res3, _ = json.Marshal(msg)
|
res3, _ = json.Marshal(msg)
|
||||||
}
|
}
|
||||||
//判断对方是否在线,若不在线则发送离线消息,否则正常发送消息
|
//判断对方是否在线,若不在线则发送离线消息,否则正常发送消息
|
||||||
if worker.IsContainKey("user_"+to_user_id+"_status") == true {
|
if worker.IsContainKey(to_user_id+"_status") == true {
|
||||||
if worker.GetRedis("user_"+to_user_id+"_status") == "0" {
|
if worker.GetRedis(to_user_id+"_status") == "0" {
|
||||||
msg.Type = "offline"
|
msg.Type = "offline"
|
||||||
msg.Msg = "offline"
|
msg.Msg = "offline"
|
||||||
msg.From_user_id = -1
|
msg.From_user_id = -1
|
||||||
|
|
@ -323,9 +221,13 @@ func SRMessage(c *gin.Context) {
|
||||||
}
|
}
|
||||||
err2 := ws.WriteMessage(websocket.TextMessage, res3)
|
err2 := ws.WriteMessage(websocket.TextMessage, res3)
|
||||||
if err2 != nil {
|
if err2 != nil {
|
||||||
worker.SetRedisWithExpire("user_"+strconv.Itoa(id1)+"_status", "0", time.Second*120) //设置用户在线状态,1为在线,0为离线,5秒后过期
|
worker.SetRedisWithExpire("user_"+id.(string)+"_status", "0", time.Second*120) //设置用户在线状态,1为在线,0为离线,5秒后过期
|
||||||
|
clientsMux.Lock()
|
||||||
|
delete(clients, ws)
|
||||||
|
clientsMux.Unlock()
|
||||||
|
break
|
||||||
} else {
|
} else {
|
||||||
worker.SetRedisWithExpire("user_"+strconv.Itoa(id1)+"_status", "1", time.Second*5) //设置用户在线状态,1为在线,0为离线,5秒后过期
|
worker.SetRedisWithExpire("user_"+id.(string)+"_status", "1", time.Second*5) //设置用户在线状态,1为在线,0为离线,5秒后过期
|
||||||
}
|
}
|
||||||
time.Sleep(time.Second * 1) // 每1秒查询一次
|
time.Sleep(time.Second * 1) // 每1秒查询一次
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -336,50 +238,3 @@ func SRMessage(c *gin.Context) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func ServerSendMsg(c *gin.Context) {
|
|
||||||
//sse
|
|
||||||
c.Writer.Header().Set("Content-Type", "text/event-stream")
|
|
||||||
c.Writer.Header().Set("Cache-Control", "no-cache")
|
|
||||||
c.Writer.Header().Set("Connection", "keep-alive")
|
|
||||||
c.Writer.Header().Set("Access-Control-Allow-Origin", "*")
|
|
||||||
|
|
||||||
id, _ := c.Get("id")
|
|
||||||
user_id := int(id.(float64))
|
|
||||||
|
|
||||||
//设置用户在线状态
|
|
||||||
worker.SetRedisWithExpire("user_"+strconv.Itoa(user_id)+"_status_v2", "1", time.Second*60)
|
|
||||||
//发送消息
|
|
||||||
|
|
||||||
key := "user_" + strconv.Itoa(user_id) + "_msg_ids"
|
|
||||||
|
|
||||||
for {
|
|
||||||
msg_id := worker.PopRedisListLeft(key)
|
|
||||||
if msg_id != "" {
|
|
||||||
msg_id_num, _ := strconv.ParseInt(msg_id, 10, 64)
|
|
||||||
msgs := dao.FindMessageByID(uint(msg_id_num))
|
|
||||||
if len(msgs) > 0 {
|
|
||||||
msg := msgs[0]
|
|
||||||
//发送消息
|
|
||||||
_, err := c.Writer.Write([]byte("data: " + msg.Msg + "\n\n"))
|
|
||||||
if err != nil {
|
|
||||||
worker.SetRedisWithExpire("user_"+strconv.Itoa(user_id)+"_status_v2", "0", time.Second*3600)
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
var msg proto.Message
|
|
||||||
msg.Type = "check"
|
|
||||||
msg.Msg = "check"
|
|
||||||
msg.From_user_id = -1
|
|
||||||
//发送心跳包
|
|
||||||
res3, _ := json.Marshal(msg)
|
|
||||||
_, err := c.Writer.Write([]byte("data: " + string(res3) + "\n\n"))
|
|
||||||
if err != nil {
|
|
||||||
worker.SetRedisWithExpire("user_"+strconv.Itoa(user_id)+"_status_v2", "0", time.Second*3600)
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
time.Sleep(time.Second * 1)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
|
||||||
10
main.go
10
main.go
|
|
@ -18,14 +18,8 @@ func main() {
|
||||||
|
|
||||||
r := gin.Default()
|
r := gin.Default()
|
||||||
gin.SetMode(gin.ReleaseMode)
|
gin.SetMode(gin.ReleaseMode)
|
||||||
err := dao.Init()
|
dao.Init()
|
||||||
if err != nil {
|
worker.InitRedis()
|
||||||
panic("failed to connect database:" + err.Error())
|
|
||||||
}
|
|
||||||
err = worker.InitRedis()
|
|
||||||
if err != nil {
|
|
||||||
panic("failed to connect redis:" + err.Error())
|
|
||||||
}
|
|
||||||
r.Use(handler.CrosHandler())
|
r.Use(handler.CrosHandler())
|
||||||
r.Use(JWTAuthMiddleware()) // 使用 JWT 认证中间件
|
r.Use(JWTAuthMiddleware()) // 使用 JWT 认证中间件
|
||||||
handler.SetUpVideoGroup(r) // Video
|
handler.SetUpVideoGroup(r) // Video
|
||||||
|
|
|
||||||
|
|
@ -20,19 +20,6 @@ const (
|
||||||
CID_BASE_DIR = "/home/lijun/cid/"
|
CID_BASE_DIR = "/home/lijun/cid/"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
|
||||||
// 以下是消息类型
|
|
||||||
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 // 已读
|
|
||||||
MSG_STATUS_UNREAD = 0 // 未读
|
|
||||||
)
|
|
||||||
|
|
||||||
type User struct {
|
type User struct {
|
||||||
gorm.Model
|
gorm.Model
|
||||||
Name string `gorm:"column:name"`
|
Name string `gorm:"column:name"`
|
||||||
|
|
|
||||||
|
|
@ -41,7 +41,4 @@ const (
|
||||||
|
|
||||||
// UUID相关错误码
|
// UUID相关错误码
|
||||||
UUIDNotFound = 18 // uuid不存在
|
UUIDNotFound = 18 // uuid不存在
|
||||||
|
|
||||||
//消息错误码
|
|
||||||
MsgSendFailed = 61 // 消息发送失败
|
|
||||||
)
|
)
|
||||||
|
|
|
||||||
|
|
@ -1,125 +0,0 @@
|
||||||
package service
|
|
||||||
|
|
||||||
import (
|
|
||||||
"errors"
|
|
||||||
"strconv"
|
|
||||||
"time"
|
|
||||||
"videoplayer/dao"
|
|
||||||
"videoplayer/worker"
|
|
||||||
)
|
|
||||||
|
|
||||||
func CreateGeneralMessageService(from_id, to_id, msg_type int, content string) (error, uint) {
|
|
||||||
// 业务逻辑
|
|
||||||
var err error
|
|
||||||
var id uint
|
|
||||||
switch msg_type {
|
|
||||||
case 1:
|
|
||||||
//判断是否是好友
|
|
||||||
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)
|
|
||||||
res := worker.GetRedis("user_" + strconv.Itoa(to_id) + "_status_v2")
|
|
||||||
if res == "1" {
|
|
||||||
//在线,存入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 3:
|
|
||||||
//user := dao.FindUserByID(to_id)
|
|
||||||
// 系统消息,需要管理员权限
|
|
||||||
err, id = dao.CreateGeneralMessage(from_id, to_id, msg_type, 0, 0, content)
|
|
||||||
case 4:
|
|
||||||
res, _ := dao.GetMsgUserByIndex(from_id, to_id, 4, 1, 0)
|
|
||||||
if len(res) > 0 {
|
|
||||||
// 已经有会话记录,返回会话id
|
|
||||||
return nil, 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, from_id, content)
|
|
||||||
default:
|
|
||||||
// 未知消息类型
|
|
||||||
err = errors.New("unknown message type")
|
|
||||||
}
|
|
||||||
return err, id
|
|
||||||
}
|
|
||||||
|
|
||||||
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")
|
|
||||||
}
|
|
||||||
if msq_type == 4 {
|
|
||||||
from_id = from_user_id
|
|
||||||
}
|
|
||||||
msgs, err := dao.GetMsgUserByIndex(from_id, to_id, msq_type, index, 0)
|
|
||||||
return msgs, err
|
|
||||||
}
|
|
||||||
|
|
||||||
// AddFriendService 通过消息id添加好友,和加入群聊
|
|
||||||
// id 消息id
|
|
||||||
// from_user_id 发送消息的用户id
|
|
||||||
// to_user_id 接收消息的用户id,及接受用户id
|
|
||||||
func AddFriendService(id, from_user_id, to_user_id int) error {
|
|
||||||
// 业务逻辑
|
|
||||||
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
|
|
||||||
}
|
|
||||||
|
|
||||||
type FGRet struct {
|
|
||||||
Friends []dao.FriendRet `json:"friends"`
|
|
||||||
Groups []dao.Group `json:"groups"`
|
|
||||||
}
|
|
||||||
|
|
||||||
func GetFriendList(user_id int) FGRet {
|
|
||||||
//获取好友id和群id
|
|
||||||
friends := dao.FindFriends(user_id)
|
|
||||||
groups := dao.FindGroups(user_id)
|
|
||||||
var fg FGRet
|
|
||||||
fg.Friends = friends
|
|
||||||
fg.Groups = groups
|
|
||||||
return fg
|
|
||||||
}
|
|
||||||
|
|
@ -68,16 +68,6 @@ func CreateVideo(videoPath, videoName string, cameraID, authID, human, isDelete
|
||||||
return dao.CreateVideo(videoPath, videoName, cameraID, authID, human, isDelete, createTime, endTime, deleteTime, fileSize)
|
return dao.CreateVideo(videoPath, videoName, cameraID, authID, human, isDelete, createTime, endTime, deleteTime, fileSize)
|
||||||
}
|
}
|
||||||
|
|
||||||
func GetVideoListByPage(auth_id, page, page_size int) []dao.Video {
|
|
||||||
if page < 0 {
|
|
||||||
page = 0 //默认第一页
|
|
||||||
}
|
|
||||||
if page_size < 0 || page_size > 100 {
|
|
||||||
page_size = 10 //默认每页10条
|
|
||||||
}
|
|
||||||
return dao.GetVideoListByPage(auth_id, page, page_size)
|
|
||||||
}
|
|
||||||
|
|
||||||
func DeleteVideo(id, user int) int {
|
func DeleteVideo(id, user int) int {
|
||||||
return dao.DeleteVideoByID(id, user)
|
return dao.DeleteVideoByID(id, user)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -13,7 +13,7 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
var redisClient *redis.Client // Redis 客户端, 用于连接 Redis 服务器
|
var redisClient *redis.Client // Redis 客户端, 用于连接 Redis 服务器
|
||||||
func InitRedis() error {
|
func InitRedis() {
|
||||||
ctx := context.Background()
|
ctx := context.Background()
|
||||||
// 连接redis
|
// 连接redis
|
||||||
redisClient = redis.NewClient(&redis.Options{
|
redisClient = redis.NewClient(&redis.Options{
|
||||||
|
|
@ -27,7 +27,6 @@ func InitRedis() error {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Println("Error connecting to Redis: %v", err)
|
fmt.Println("Error connecting to Redis: %v", err)
|
||||||
}
|
}
|
||||||
return err
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func CloseRedis() {
|
func CloseRedis() {
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue