Files
huangguo_server/app/service/messageser/message.go
T
rootandClaude Opus 5 8679200f41 Initial commit
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-15 13:57:10 +08:00

862 lines
27 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
package messageser
import (
"91porn-server/app/appg"
"91porn-server/app/middleware/authuser"
"91porn-server/app/service/imser"
"91porn-server/common"
"91porn-server/common/db"
"91porn-server/common/log"
"91porn-server/common/services/message"
"91porn-server/common/stderr"
"91porn-server/models/cache/sysconfdata"
"91porn-server/models/v/imusermod"
"91porn-server/models/v/messagemod"
"91porn-server/models/v/sessionmod"
"91porn-server/models/v/sysconfmod"
"91porn-server/models/v/txnmod"
"91porn-server/models/v/usermod"
"91porn-server/models/v/vidmod"
"91porn-server/models/v/walletmod"
"encoding/json"
"fmt"
"strconv"
"time"
"go.mongodb.org/mongo-driver/bson"
"go.mongodb.org/mongo-driver/bson/primitive"
)
// QueryDynamics 查询动态列表
func QueryDynamics(uid uint64, req *messagemod.QueryCond) ([]messagemod.MsgDynamicsApp, bool, stderr.Code) {
//now := time.Now()
// 处理用户消息提示状态
_ = message.CancelTip(uid)
//动态类型消息
var msgType []string
if req.MsgType == 1 {
msgType = []string{"like_msg", "like_comment_msg"}
} else {
msgType = []string{"comment_msg", "reply_comment_msg"}
}
cond := bson.M{"msgType": bson.M{"$in": msgType}, "takeUid": uid}
mData, hasNext, err := messagemod.QueryDynamics(cond, int(req.PageSize), int(req.PageNumber))
if err != nil {
return nil, false, stderr.ErrDbQueryError
}
if len(mData) > 0 {
//用户查看自己的动态列表, 则消息接受者是查看用户
uids := []uint64{}
vid := []primitive.ObjectID{}
for _, m := range mData {
uids = append(uids, m.SendUid)
vid = append(vid, m.ObjId)
}
//查询帖子信息
vidMap, _ := vidmod.VideoMap(vid)
if len(uids) > 0 {
//查询用户信息
uData, err := usermod.FindUsersMapByUID(uids)
if err != nil {
return mData, false, stderr.ErrDbQueryError
}
//循环获取组装用户信息
for i, m := range mData {
if uData[m.SendUid] != nil {
mData[i].SendName = uData[m.SendUid].Name
mData[i].SendAvatar = uData[m.SendUid].Portrait
mData[i].SendGender = uData[m.SendUid].Gender
//mData[i].SuperUser = uData[m.SendUid].GetSuperUser(now)
mData[i].SuperUser = 0
mData[i].Awards = uData[m.SendUid].Awards
mData[i].VipExpireDate = uData[m.SendUid].VipExpireDate
mData[i].VipLevel = uData[m.SendUid].VipLevel
}
if m.MsgType == messagemod.LikeCommentMsg {
mData[i].LikeCount = m.UserCount
} else if m.MsgType == messagemod.LikeMsg {
if video, ok := vidMap[m.ObjId]; ok {
mData[i].LikeCount = video.LikeCount
mData[i].ImgUrl = video.Cover
}
}
}
}
//获取成功后, 将当前动态全部变为已读
common.Go(func() {
//更新状态
messagemod.UpdDynamicsIsReadByUid(nil, uid)
//清除redis
appg.Redis.Del(messagemod.NoRedDynamicNumRedisKey + strconv.FormatUint(uid, 10))
})
}
return mData, hasNext, stderr.Success
}
// 查询未读动态数
func QueryNoRedDynamicNum(uid uint64) (messagemod.NoReadMsgDynamicsCountApp, stderr.Code) {
var ret = messagemod.NoReadMsgDynamicsCountApp{
DtCount: 0,
MsgCount: 0,
}
//redis限制, 一分钟一次
key := messagemod.NoRedDynamicNumRedisKey + strconv.FormatUint(uid, 10)
result, err := appg.Redis.Get(key)
if err != nil || result == nil {
mt := messagemod.GetDynamics()
//包含私信
mt = append(mt, messagemod.PrivateLetterMsg)
//动态类型消息
cond := bson.M{"msgType": bson.M{"$in": mt}, "takeUid": uid, "isRead": false}
data, err := messagemod.FindByFilter(cond)
if err != nil {
log.Warn(fmt.Sprintf("messageser QueryNoRedDynamicNum messagemod.FindByFilter error:%+v:", err), log.Any("uid", uid))
return ret, stderr.ErrDbQueryError
}
if len(data) > 0 {
for _, d := range data {
if d.MsgType == messagemod.PrivateLetterMsg {
ret.MsgCount += 1
} else {
ret.DtCount += 1
}
}
}
} else {
err := json.Unmarshal([]byte(*result), &ret)
if err != nil {
log.Warn(fmt.Sprintf("messageser QueryNoRedDynamicNum json.Unmarshal error:%+v:", err), log.Any("uid", uid))
return ret, stderr.Failure
}
return ret, stderr.Success
}
//将对象转为字符串
jsonstr, err := json.Marshal(ret)
if err != nil {
log.Warn(fmt.Sprintf("messageser QueryNoRedDynamicNum json.Marshal error:%+v:", err), log.Any("uid", uid))
return ret, stderr.Success
}
//设置redis缓存
_ = appg.Redis.Set(key, string(jsonstr), time.Minute*1)
return ret, stderr.Success
}
// QueryPrivateLetterSession 查询私信会话列表
func QueryPrivateLetterSession(uid uint64, req *sessionmod.QueryCond) ([]sessionmod.SessionApp, bool, stderr.Code) {
// 处理用户消息提示状态
_ = message.CancelTip(uid)
//查询当前用户的会话
cond := bson.M{"$or": []bson.M{{"sendUid": uid}, {"takeUid": uid}}}
sData, hasNext, err := sessionmod.Query(cond, req)
if err != nil {
log.Warn(fmt.Sprintf("messageser Add sessionmod.Query error:%+v:", err), log.Any("uid", uid))
return nil, false, stderr.ErrDbQueryError
}
if len(sData) > 0 {
var uids []uint64
for i, m := range sData {
//查询未读条数
count, err := messagemod.Count(bson.M{"sessionId": m.SessionId, "takeUid": uid, "isRead": false})
if err != nil {
log.Error(fmt.Sprintf("messageser Add messagemod.Count error:%+v:", err), log.Any("sessionId", m.ID.Hex()), log.Any("uid", uid))
continue
}
sData[i].NoReadNum = count
//sendId是当前用户,则会话是有当前用户主动发起的,反之,对方用户主动发起
//注意, 会话列表用来展示对方用户头像姓名, 所有这里取对方用户信息
if uid == m.SendUid {
uids = append(uids, m.TakeUid)
continue
}
if uid == m.TakeUid {
uids = append(uids, m.SendUid)
}
}
if len(uids) > 0 {
//查询用户信息
uData, err := usermod.FindUsersMapByUID(uids)
if err != nil {
log.Warn(fmt.Sprintf("messageser Add usermod.FindUsersMapByUID error:%+v:", err), log.Any("uids", uids), log.Any("uid", uid))
return sData, false, stderr.ErrDbQueryError
}
imByUID, _ := imusermod.IMUserIDMapByUIDs(uids) // uid → imUserIdimusermod 为准)
//循环获取组装用户信息
for i, m := range sData {
if uid == m.SendUid && uData[m.TakeUid] != nil {
peer := uData[m.TakeUid]
sData[i].UserId = peer.UID
sData[i].PeerImUserID = imByUID[peer.UID]
sData[i].UserName = peer.Name
sData[i].UserAvatar = peer.Portrait
continue
}
if uid == m.TakeUid && uData[m.SendUid] != nil {
peer := uData[m.SendUid]
sData[i].UserId = peer.UID
sData[i].PeerImUserID = imByUID[peer.UID]
sData[i].UserName = peer.Name
sData[i].UserAvatar = peer.Portrait
}
}
}
}
return sData, hasNext, stderr.Success
}
// DelSession 删除私信会话
func DelSession(uid uint64, sessionId string) stderr.Code {
//查询会话是否存在
session, err := sessionmod.FindOneByFilter(bson.M{"sessionId": sessionId})
if err != nil {
log.Warn(fmt.Sprintf("messageser DelSession sessionmod.FindOneByFilter error:%+v:", err), log.Any("uid", uid), log.Any("sessionId", sessionId))
return stderr.ErrDbQueryError
}
if session.ID.IsZero() {
log.Warn("messageser DelSession session is null", log.Any("uid", uid), log.Any("sessionId", sessionId))
return stderr.Failure
}
if session.SendUid != uid && session.TakeUid != uid {
log.Warn("messageser DelSession session.SendUid != uid && session.TakeUid != uid", log.Any("uid", uid), log.Any("sessionId", sessionId))
return stderr.Failure
}
//删除
err = sessionmod.Delete(bson.M{"sessionId": sessionId})
if err != nil {
log.Warn(fmt.Sprintf("messageser DelSession sessionmod.Delete error:%+v:", err), log.Any("uid", uid), log.Any("sessionId", sessionId))
return stderr.ErrDbDeleteError
}
//删除会话对应的消息
_, err = messagemod.DeleteMsgBySessionId(sessionId)
if err != nil {
log.Warn(fmt.Sprintf("messageser DelSession messagemod.DeleteMsgBySessionId error:%+v:", err), log.Any("uid", uid), log.Any("sessionId", sessionId))
return stderr.ErrDbDeleteError
}
return stderr.Success
}
// GetSessionId 获取sessionId
func GetSessionId(uid, takeUid uint64) string {
//会话id
sessionId := ""
if uid == takeUid {
log.Warn(fmt.Sprintf("messageser GetSessionId uid == takeUid"), log.Any("uid", uid), log.Any("takeUid", takeUid))
return sessionId
}
//先查询是否有会话信息
cond := bson.M{"$or": []bson.M{bson.M{"sendUid": uid, "takeUid": takeUid}, bson.M{"sendUid": takeUid, "takeUid": uid}}}
session, err := sessionmod.FindOneByFilter(cond)
if err != nil {
log.Warn(fmt.Sprintf("messageser GetSessionId sessionmod.FindOneByFilter error:%+v:", err), log.Any("uid", uid))
return sessionId
}
if session.ID.IsZero() {
sessionId = common.UUID()
//新增session
s := &sessionmod.Session{
SendUid: uid,
TakeUid: takeUid,
SessionId: sessionId,
CreatedAt: time.Now(),
}
err := sessionmod.InsertOne(nil, s)
if err != nil {
log.Warn(fmt.Sprintf("messageser GetSessionId sessionmod.InsertOne error:%+v:", err), log.Any("session", s), log.Any("uid", uid), log.Any("takeUid", takeUid))
return ""
}
} else {
sessionId = session.SessionId
}
return sessionId
}
// QueryPrivateLetterMsg 查询私信聊天列表
func QueryPrivateLetterMsg(uid uint64, req *messagemod.QueryMsgCond) ([]messagemod.MessageApp, bool, stderr.Code) {
//私信类型消息
msgTypes := [...]string{string(messagemod.PrivateLetterMsg), string(messagemod.OfficialPrivateLetterMsg)}
cond := bson.M{"msgType": bson.M{"$in": msgTypes}, "sessionId": req.SessionId}
mData, hasNext, err := messagemod.Query(cond, int(req.PageSize), int(req.PageNumber))
if err != nil {
return nil, false, stderr.ErrDbQueryError
}
if len(mData) > 0 {
uids := []uint64{}
for _, m := range mData {
uids = append(uids, m.SendUid)
uids = append(uids, m.TakeUid)
}
if len(uids) > 0 {
//查询用户信息
uData, err := usermod.FindUsersMapByUID(uids)
if err != nil {
return mData, false, stderr.ErrDbQueryError
}
//循环获取组装用户信息
for i, m := range mData {
if sendUser := uData[m.SendUid]; sendUser != nil {
mData[i].SendName = sendUser.Name
mData[i].SendAvatar = sendUser.Portrait
}
if takeUser := uData[m.TakeUid]; takeUser != nil {
mData[i].TakeName = takeUser.Name
mData[i].TakeAvatar = takeUser.Portrait
}
peerUID := m.SendUid
if uid == m.SendUid {
peerUID = m.TakeUid
}
if peer := uData[peerUID]; peer != nil {
mData[i].PeerImUserID = imusermod.IMUserIDByUID(peer.UID)
}
}
}
}
//请求列表时,将当前用户当前会话所有未读消息更新为已读
common.Go(func() {
messagemod.UpdIsReadBySessionIdAndUid(nil, uid, req.SessionId)
})
return mData, hasNext, stderr.Success
}
// AddPrivateLetter 新增私信消息
func AddPrivateLetter(uid uint64, req messagemod.AddMsgReqInfo) stderr.Code {
data, err := usermod.FindUserByUID(uid)
if err != nil || data == nil {
log.Warn(fmt.Sprintf("messageser Add send user is null"), log.Any("uid", uid), log.Any("takeUid", req.TakeUid))
return stderr.CommentUserInfoErr
}
if data.HasBanned {
return stderr.CommentUserHasBanned
}
if uid == req.TakeUid {
log.Warn(fmt.Sprintf("messageser Add user cant self add msg"), log.Any("uid", uid), log.Any("takeUid", req.TakeUid))
return stderr.NoSelfAddMsg
}
//校验私信用户是否vip
//if !data.IsVIP(time.Now()) {
// return stderr.Success
//}
////校验vip是否是充值过的,没有充值则不允许私信
//if uid > 150000 && !walletmod.IsRechargeUser(nil, uid) {
// log.Warn(fmt.Sprintf("messageser Add user no recharge"), log.Any("uid", uid), log.Any("takeUid", req.TakeUid), log.Any("content", req.Content))
// return stderr.Success
//}
price := CheckChatPrice(data)
wallet, err := walletmod.GetWallet(uid)
if err != nil {
return stderr.ErrParamError
}
if price > 0 && (wallet == nil || wallet.ID.IsZero()) {
return stderr.InsufficientBalance
}
checkUserBalance, deAmt, deIncome := CheckUserBalance(wallet, price)
if !checkUserBalance {
return stderr.InsufficientBalance
}
//if wallet.Amount+wallet.Income<=0 || wallet.Amount+wallet.Income
fengjin := false
//查询被私信的用户是否存在
takeUser, err := usermod.FindUserByUID(req.TakeUid)
if err != nil || takeUser == nil {
fengjin = true
}
//校验用户请求频率,5秒内超过5次,则封禁
//key := "add-private-letter-" + strconv.FormatUint(uid, 10)
//ret, err := appg.Redis.Get(key)
//if !fengjin && err == nil {
// var i int = 0
// if ret != nil {
// i, _ = strconv.Atoi(*ret)
// }
// if i > 5 {
// //封禁
// fengjin = true
// } else {
// i += 1
// appg.Redis.Set(key, strconv.Itoa(i), time.Second*5)
// }
//}
//检测私信内容是否包含网址
//if truthutil.CheckStrIsUrl(req.Content) {
// fengjin = true
// //这里直接返回成功,让广告用户误以为成功了,免得一直来麻烦
// log.Warn("messageser Add checkStrIsUrl true", log.Any("uid", uid), log.Any("takeUid", req.TakeUid), log.Any("content", req.Content))
// return stderr.Success
//}
if fengjin {
common.Go(func() {
log.Warn("messageser Add takeUser == nil", log.Any("uid", uid), log.Any("takeUid", req.TakeUid), log.Any("content", req.Content))
//如果用户不存在, 则证明是脚本在刷私信, 封禁该用户
hasLocked := true
lockReason := "脚本打广告的用户"
doc := usermod.UserSelector{
HasLocked: &hasLocked,
LockReason: &lockReason,
}
usermod.Update(uid, doc)
//删除token
authuser.RevokeTokenCache(uid)
})
return stderr.CommentUserHasBanned
}
//会话id
sessionId := ""
//新增私聊信息之前, 先查询是否有会话信息
cond := bson.M{"$or": []bson.M{bson.M{"sendUid": uid, "takeUid": req.TakeUid}, bson.M{"sendUid": req.TakeUid, "takeUid": uid}}}
session, err := sessionmod.FindOneByFilter(cond)
if err != nil {
log.Warn(fmt.Sprintf("messageser Add sessionmod.FindOneByFilter error:%+v:", err), log.Any("uid", uid))
return stderr.ErrDbQueryError
}
t := time.Now()
if session.ID.IsZero() {
sessionId = common.UUID()
//新增session
s := &sessionmod.Session{
SendUid: uid,
TakeUid: req.TakeUid,
SessionId: sessionId,
CreatedAt: t,
UpdatedAt: t,
}
err := sessionmod.InsertOne(nil, s)
if err != nil {
log.Warn(fmt.Sprintf("messageser Add sessionmod.InsertOne error:%+v:", err), log.Any("session", s), log.Any("uid", uid), log.Any("takeUid", req.TakeUid))
return stderr.ErrDbInsertError
}
} else {
sessionId = session.SessionId
}
if deAmt > 0 || deIncome > 0 {
// 扣除用户余额
plan := &walletmod.DebitPlan{
Amount: deAmt,
Income: deIncome,
}
if err = appg.VideoDB.Trans(func(t *db.MongoTool) error {
wallet, err := walletmod.Debit(t, plan, uid)
if err != nil { //扣钱
return err
}
var txnLogs []txnmod.TransactionLog
if deAmt > 0 {
txnLogs = append(txnLogs, txnmod.TransactionLog{
UID: uid,
Amount: -deAmt,
ActualAmount: float64(-deAmt),
TranType: txnmod.SendMsgDebitAmountGold.Key(),
TranTypeInt: int64(txnmod.SendMsgDebitAmountGoldReturn),
Desc: fmt.Sprintf("用户私信扣除%v个金币", deAmt),
SysType: data.SysType,
RealAmount: walletmod.GetRealAmount(wallet),
})
}
if deIncome > 0 {
if err = txnmod.InsertTransactionLog(t, &txnmod.TransactionLog{
UID: uid,
Amount: -deIncome,
ActualAmount: float64(-deIncome),
TranType: txnmod.SendMsgDebitIncomeGold.Key(),
TranTypeInt: int64(txnmod.SendMsgDebitIncomeGold),
Desc: fmt.Sprintf("用户私信扣除收益%v个金币", deIncome),
SysType: data.SysType,
RealAmount: walletmod.GetRealAmount(wallet),
}); err != nil {
return stderr.ErrDbQueryError
}
}
if len(txnLogs) > 0 {
if err = txnmod.InsertManyTransactionLog(t, txnLogs); err != nil {
log.Warn(fmt.Sprintf("productser BuyVIP Transaction err %s", err.Error()))
return err
}
}
return nil
}); err != nil {
log.Warn(fmt.Sprintf("send meaasge Transaction err %s", err.Error()))
return stderr.ErrDbUpdateError //通知消息
}
}
if err = imser.SendPrivateMessage(uid, req.TakeUid, req.Content, req.ImgUrl); err != nil {
imser.LogSDKSendError(uid, req.TakeUid, err)
return stderr.Failure
}
code := PublicAddMsg(messagemod.PublicAddMsg{
SendUid: uid,
TakeUid: req.TakeUid,
SessionId: sessionId,
Content: req.Content,
ImgUrl: req.ImgUrl,
MsgType: messagemod.PrivateLetterMsg,
})
if code != stderr.Success {
return code
}
common.Go(func() {
//更新会话预览消息
content := req.Content
if len(req.ImgUrl) > 0 && content == "" {
content = "发送了一张图片"
}
err := sessionmod.UpdOneByFilter(nil, bson.M{"sessionId": sessionId}, bson.M{"$set": bson.M{"preContent": content, "updatedAt": t}})
if err != nil {
log.Warn(fmt.Sprintf("messageser Add messagemod.UpdOneByFilter error:%+v:", err), log.Any("sessionId", sessionId), log.Any("preContent", req.Content), log.Any("uid", uid))
}
})
return stderr.Success
}
// SendIMPrivateLetter 走第三方 IM 通道发送私信:
// 校验发送/接收方 → 校验余额 → 扣费(含 txn log)→ 调用 imser.SendPrivateMessage 走 IM SDK 投递。
func SendIMPrivateLetter(uid uint64, req messagemod.AddMsgReqInfo) stderr.Code {
sender, err := usermod.FindUserByUID(uid)
if err != nil || sender == nil {
log.Warn("messageser SendIMPrivateLetter sender not found",
log.Any("uid", uid), log.Any("takeUid", req.TakeUid))
return stderr.CommentUserInfoErr
}
if sender.HasBanned {
return stderr.CommentUserHasBanned
}
if uid == req.TakeUid {
return stderr.NoSelfAddMsg
}
takeUser, err := usermod.FindUserByUID(req.TakeUid)
if err != nil || takeUser == nil {
log.Warn("messageser SendIMPrivateLetter take user not found",
log.Any("uid", uid), log.Any("takeUid", req.TakeUid))
return stderr.UserIsNotExists
}
price := CheckChatPrice(sender)
if uid != 100001 && price > 0 {
wallet, err := walletmod.GetWallet(uid)
if err != nil {
return stderr.ErrParamError
}
if wallet == nil || wallet.ID.IsZero() {
return stderr.InsufficientBalance
}
ok, deAmt, deIncome := CheckUserBalance(wallet, price)
if !ok {
return stderr.InsufficientBalance
}
if err = appg.VideoDB.Trans(func(t *db.MongoTool) error {
w, err := walletmod.Debit(t, &walletmod.DebitPlan{Amount: deAmt, Income: deIncome}, uid)
if err != nil {
return err
}
var logs []txnmod.TransactionLog
if deAmt > 0 {
logs = append(logs, txnmod.TransactionLog{
UID: uid,
Amount: -deAmt,
ActualAmount: float64(-deAmt),
TranType: txnmod.SendMsgDebitAmountGold.Key(),
TranTypeInt: int64(txnmod.SendMsgDebitAmountGoldReturn),
Desc: fmt.Sprintf("用户私信(IM)扣除%v个金币", deAmt),
SysType: sender.SysType,
RealAmount: w.RealAmount(),
})
}
if deIncome > 0 {
logs = append(logs, txnmod.TransactionLog{
UID: uid,
Amount: -deIncome,
ActualAmount: float64(-deIncome),
TranType: txnmod.SendMsgDebitIncomeGold.Key(),
TranTypeInt: int64(txnmod.SendMsgDebitIncomeGold),
Desc: fmt.Sprintf("用户私信(IM)扣除收益%v个金币", deIncome),
SysType: sender.SysType,
RealAmount: w.RealAmount(),
})
}
if len(logs) > 0 {
if err = txnmod.InsertManyTransactionLog(t, logs); err != nil {
return err
}
}
return nil
}); err != nil {
log.Warn("messageser SendIMPrivateLetter charge tx fail",
log.Any("uid", uid), log.Any("takeUid", req.TakeUid), log.E(err))
return stderr.ErrDbUpdateError
}
}
if err := imser.SendPrivateMessage(uid, req.TakeUid, req.Content, req.ImgUrl); err != nil {
log.Error("messageser SendIMPrivateLetter imser.SendPrivateMessage fail",
log.Any("uid", uid), log.Any("takeUid", req.TakeUid), log.E(err))
return stderr.Failure
}
return stderr.Success
}
func CheckChatPrice(u *usermod.User) int64 {
configure, _ := sysconfdata.GetAllFromCache()
if u == nil {
return configure.GetInt(sysconfmod.SendMsgPrice)
}
var price int64
// 校验私信用户是否vip
isVip := u.IsPaidVIP()
if isVip && u.ChatPrice > 0 {
price = u.ChatPrice
} else if isVip && u.ChatPrice < 0 {
// vip私信价格设置为负数的时候,则说明不需要钱(因为旧的用户数据这个字段都是0,所以都得读默认配置)
price = 0
} else {
// 非vip用户或者是旧的vip用户的u.ChatPrice字段为0的时候,都是默认读配置
price = configure.GetInt(sysconfmod.SendMsgPrice)
}
return price
}
func CheckUserBalance(w *walletmod.Wallet, price int64) (checkStatus bool, deAmt, deIncome int64) {
totalAmt := w.Amount + w.Income
var dAmt, dIncome int64
if totalAmt < price {
return false, dAmt, dIncome
}
if totalAmt >= price && w.Amount >= price {
dAmt = price
}
if totalAmt >= price && w.Amount < price {
dAmt = w.Amount
dIncome = price - w.Amount
}
return true, dAmt, dIncome
}
// ReadMsg 阅读消息
func ReadMsg(uid uint64, req messagemod.ReadMsgReqInfo) stderr.Code {
if len(req.MsgIds) < 0 {
log.Error(fmt.Sprintf("messageser readMsg req.MsgIds <= 0"), log.Any("uid", uid))
return stderr.Success
}
var ids []primitive.ObjectID
for _, v := range req.MsgIds {
id, _ := primitive.ObjectIDFromHex(v)
ids = append(ids, id)
}
if len(ids) < 0 {
log.Error(fmt.Sprintf("messageser readMsg ids <= 0"), log.Any("uid", uid))
return stderr.Success
}
//更新消息已读状态
err := messagemod.UpdIsRead(nil, uid, ids)
if err != nil {
log.Error(fmt.Sprintf("messageser messagemod.UpdIsRead error:%+v:", err), log.Any("ids", ids), log.Any("uid", uid))
return stderr.ErrDbUpdateError
}
return stderr.Success
}
// DynamicMsgUserGroup 同一obj下的相同操作归类相同用户
func DynamicMsgUserGroup(params messagemod.PublicAddMsg) stderr.Code {
//查询用户信息
user, err := usermod.FindUserByUID(params.SendUid)
if err != nil {
return stderr.ErrDbQueryError
}
if user == nil || user.HasLocked {
return stderr.UserIsNotExists
}
filter := bson.M{"takeUid": params.TakeUid, "msgType": params.MsgType, "objId": params.ObjId}
msg, err := messagemod.FindOneByFilter(filter)
if err != nil || msg.ID.IsZero() {
params.UserCount = 1
params.UserGroup = []messagemod.UserInfo{
{
Uid: user.UID,
Name: user.Name,
Avatar: user.Portrait,
},
}
// 发布消息并返回
return PublicAddMsg(params)
}
ug := msg.UserGroup
for _, v := range ug {
// 已经有记录直接返回
if v.Uid == params.SendUid {
return stderr.Success
}
}
// 取前9个用户 + 当前用户
if len(ug) >= 10 {
ug = ug[:9]
}
ug = append([]messagemod.UserInfo{{
Uid: user.UID,
Name: user.Name,
Avatar: user.Portrait,
}}, ug...)
set := bson.M{"userCount": msg.UserCount + 1, "updatedAt": time.Now(), "userGroup": ug}
err = messagemod.UpdOneByFilter(nil, bson.M{"_id": msg.ID}, bson.M{"$set": set})
if err != nil {
log.Error(fmt.Sprintf("PublicMsgUserGroup error:%+v:", err), log.Any("set", set), log.Any("msgID", msg.ID))
return stderr.ErrDbQueryError
}
return stderr.Success
}
// PublicAddMsg 添加消息公共方法
func PublicAddMsg(prams messagemod.PublicAddMsg) stderr.Code {
//查询用户信息
user, err := usermod.FindUserByUID(prams.SendUid)
if err != nil {
return stderr.ErrDbQueryError
}
if user == nil || user.HasLocked {
return stderr.UserIsNotExists
}
now := time.Now()
//新增消息
msg := &messagemod.Message{
SendUid: prams.SendUid,
TakeUid: prams.TakeUid,
MsgType: prams.MsgType,
Content: prams.Content,
ImgUrl: prams.ImgUrl,
UserCount: prams.UserCount,
UserGroup: prams.UserGroup,
IsRead: false,
CreatedAt: now,
UpdatedAt: now,
}
// 是否加入未读提醒
needTip := false
switch prams.MsgType {
case messagemod.PrivateLetterMsg:
//私信
msg.SessionId = prams.SessionId
needTip = true
case messagemod.OfficialPrivateLetterMsg:
//官方私信
msg.SessionId = prams.SessionId
msg.ContentType = prams.ContentType
needTip = true
case messagemod.FollowMsg:
//关注
msg.Content = "关注了你"
//needTip = true
case messagemod.LikeMsg:
//点赞
msg.Content = "点赞了你的帖子"
msg.ObjId = prams.ObjId
msg.ObjName = prams.ObjName
msg.ObjType = prams.ObjType
needTip = true
case messagemod.ForwardMsg: //转发
msg.Content = "转发了你的帖子"
msg.ObjId = prams.ObjId
msg.ObjName = prams.ObjName
case messagemod.CommentMsg: //评论
//msg.Content = "评论了你的帖子"
msg.ObjId = prams.ObjId
msg.ObjName = prams.ObjName
msg.ObjCover = prams.ObjCover
msg.ObjType = prams.ObjType
needTip = true
case messagemod.DesireMsg:
msg.Content = "回复了你的工单"
msg.ObjId = prams.ObjId
msg.ObjName = prams.ObjName
//needTip = true
case messagemod.LikeCommentMsg: // 点赞评论
msg.Content = "点赞了你的评论"
msg.ObjId = prams.ObjId
msg.ObjName = prams.ObjName
msg.ObjType = prams.ObjType
needTip = true
case messagemod.ReplyCommentMsg: // 回复评论
msg.Content = "回复了你的评论"
msg.ObjId = prams.ObjId
msg.ObjName = prams.ObjName
msg.ObjType = prams.ObjType
//needTip = true
}
_, err = messagemod.InsertOne(nil, msg)
if err != nil {
log.Warn(fmt.Sprintf("messageser Add messagemod.InsertOne error:%+v:", err), log.Any("message", msg))
return stderr.ErrDbQueryError
}
go func() {
err = usermod.IncDynamic(prams.TakeUid)
}()
// 更新提示状态
if needTip {
_ = message.SetTip(prams.TakeUid)
}
return stderr.Success
}
func HandleOfficialMsg(receiveUId uint64, content string, contentType int) stderr.Code {
var (
uid uint64 = 100000 // 官方ID
sessionId = "" // 会话ID
)
//新增私聊信息之前, 先查询是否有会话信息
cond := bson.M{"$or": []bson.M{bson.M{"sendUid": uid, "takeUid": receiveUId}, bson.M{"sendUid": receiveUId, "takeUid": uid}}}
session, err := sessionmod.FindOneByFilter(cond)
if err != nil {
log.Warn(fmt.Sprintf("messageser Add sessionmod.FindOneByFilter error:%+v:", err), log.Any("uid", uid))
return stderr.ErrDbQueryError
}
t := time.Now()
if session.ID.IsZero() {
sessionId = common.UUID()
//新增session
s := &sessionmod.Session{
SendUid: uid,
TakeUid: receiveUId,
SessionId: sessionId,
CreatedAt: t,
UpdatedAt: t,
}
err := sessionmod.InsertOne(nil, s)
if err != nil {
log.Warn(fmt.Sprintf("messageser Add sessionmod.InsertOne error:%+v:", err), log.Any("session", s), log.Any("uid", uid), log.Any("takeUid", receiveUId))
return stderr.ErrDbInsertError
}
} else {
sessionId = session.SessionId
}
code := PublicAddMsg(messagemod.PublicAddMsg{
SendUid: uid,
TakeUid: receiveUId,
SessionId: sessionId,
Content: content,
ContentType: contentType,
MsgType: messagemod.OfficialPrivateLetterMsg,
})
if code != stderr.Success {
return code
}
common.Go(func() {
//更新会话预览消息
err := sessionmod.UpdOneByFilter(nil, bson.M{"sessionId": sessionId}, bson.M{"$set": bson.M{"preContent": content, "updatedAt": t}})
if err != nil {
log.Warn(fmt.Sprintf("messageser Add messagemod.UpdOneByFilter error:%+v:", err), log.Any("sessionId", sessionId), log.Any("preContent", content), log.Any("uid", uid))
}
})
return stderr.Success
}