This commit is contained in:
2025-07-28 18:46:14 +08:00
parent a8d45ca7a0
commit 9fbb933ed2
12 changed files with 303 additions and 257 deletions

Binary file not shown.

View File

@@ -3,38 +3,70 @@ package mysql
import (
"acquaintances/biz/model"
"acquaintances/biz/model/user"
"errors"
"fmt"
"github.com/cloudwego/hertz/pkg/common/hlog"
"gorm.io/gorm"
"gorm.io/gorm/clause"
)
// CreateFriendApplication 发起好友申请
func CreateFriendApplication(applicantID, targetUserID, message string) error {
tx := DB
// 检查是否已存在未处理的申请
var existing int64
if err := tx.Model(&model.FriendRelationship{}).
Where("applicant_id = ? AND target_user_id = ? AND status = ?",
applicantID, targetUserID, model.ApplicationPending).
Count(&existing).Error; err != nil {
return err
// 检查是否为同一用户
if applicantID == targetUserID {
return errors.New("不能添加自己为好友")
}
if existing > 0 {
return gorm.ErrDuplicatedKey // 已存在未处理的申请
// 检查目标用户是否存在(假设存在用户表查询函数)
exists, err := CheckUserExists(targetUserID)
if err != nil {
return fmt.Errorf("检查目标用户失败: %w", err)
}
if !exists {
return errors.New("目标用户不存在")
}
application := &model.FriendRelationship{
ApplicantID: applicantID,
TargetUserID: targetUserID,
ApplicationMessage: message,
Status: model.ApplicationPending,
}
// 使用事务保证原子性
return DB.Transaction(func(tx *gorm.DB) error {
// 悲观锁查询,防止并发问题
var existing model.FriendRelationship
err := tx.Clauses(clause.Locking{Strength: "UPDATE"}).
Where("applicant_id = ? AND target_user_id = ? AND status = ?",
applicantID, targetUserID, model.ApplicationPending).
First(&existing).Error
if err := tx.Create(application).Error; err != nil {
return err
}
// 存在未处理申请
if err == nil {
return errors.New("已向该用户发起好友申请,待对方处理")
}
// 非"记录不存在"的其他错误
if !errors.Is(err, gorm.ErrRecordNotFound) {
return fmt.Errorf("查询申请记录失败: %w", err)
}
return nil
// 检查是否有反向的待处理申请B向A申请时A已向B申请
var reverseExisting model.FriendRelationship
err = tx.Where("applicant_id = ? AND target_user_id = ? AND status = ?",
targetUserID, applicantID, model.ApplicationPending).
First(&reverseExisting).Error
if err == nil {
return errors.New("对方已向你发起好友申请,请先处理")
}
if !errors.Is(err, gorm.ErrRecordNotFound) {
return fmt.Errorf("查询反向申请记录失败: %w", err)
}
// 创建新申请
application := &model.FriendRelationship{
ApplicantID: applicantID,
TargetUserID: targetUserID,
ApplicationMessage: message,
Status: model.ApplicationPending,
}
if err := tx.Create(application).Error; err != nil {
return fmt.Errorf("创建申请失败: %w", err)
}
return nil
})
}
// HandleFriendApplication 处理好友申请(接受/拒绝)
@@ -75,26 +107,37 @@ func GetApplications(req user.ListFriendRelationshipReq, status ...model.FriendA
}
var result []*user.FriendRelationshipListInfo
for _, v := range applications {
var tmp user.FriendRelationshipListInfo
if v.ApplicantID == req.UserID {
data, err := GetUsersById(v.TargetUserID)
if err != nil || len(data) != 1 {
hlog.Errorf("GetApplications err:%v", err)
continue
}
tmp.UserName = data[0].UserName
tmp.AvatarImageURL = data[0].AvatarImageURL
info := &user.FriendRelationshipListInfo{
ID: int64(v.ID),
ApplicationMessage: v.ApplicationMessage,
Status: int8(v.Status),
}
tmp.ApplicationMessage = v.ApplicationMessage
tmp.Status = int8(v.Status)
result = append(result, &user.FriendRelationshipListInfo{
UserName: tmp.UserName,
AvatarImageURL: tmp.AvatarImageURL,
UserID: tmp.UserID,
Status: tmp.Status,
ApplicationMessage: tmp.ApplicationMessage,
})
// 发出的申请获取目标用户信息TargetUserID
if v.ApplicantID == req.UserID {
info.UserID = v.TargetUserID
userInfo, err := InfoUser(v.TargetUserID) // 假设改为获取单个用户的函数
if err != nil {
hlog.Errorf("获取目标用户 %s 信息失败: %v", v.TargetUserID, err)
// 可设置默认值(如"未知用户"),避免漏显示
info.UserName = "未知用户"
} else {
info.UserName = userInfo.UserName
info.AvatarImageURL = userInfo.AvatarImageURL
}
} else if v.TargetUserID == req.UserID { // 收到的申请获取申请人信息ApplicantID
info.UserID = v.ApplicantID
userInfo, err := InfoUser(v.ApplicantID)
if err != nil {
hlog.Errorf("获取申请人 %s 信息失败: %v", v.ApplicantID, err)
info.UserName = "未知用户"
} else {
info.UserName = userInfo.UserName
info.AvatarImageURL = userInfo.AvatarImageURL
}
}
result = append(result, info)
}
return result, nil

View File

@@ -1822,10 +1822,10 @@ func (p *UserInfoReq) String() string {
}
type CreateUserRequest struct {
Name string `thrift:"name,1" form:"name" form:"name" json:"name" vd:"(len($) > 0 && len($) < 100)"`
Gender Gender `thrift:"gender,2" form:"gender" form:"gender" json:"gender" vd:"($ == 1||$ == 2)"`
Name string `thrift:"name,1" form:"name" json:"name" vd:"(len($) > 0 && len($) < 100)"`
Gender Gender `thrift:"gender,2" form:"gender" json:"gender" vd:"($ == 1||$ == 2)"`
Age int64 `thrift:"age,3" form:"age" json:"age" vd:"$>0"`
Mobile string `thrift:"mobile,4" form:"mobile" form:"mobile" json:"mobile" vd:"(len($) > 0 && len($) < 12)"`
Mobile string `thrift:"mobile,4" form:"mobile" json:"mobile" vd:"(len($) > 0 && len($) < 12)"`
Area int64 `thrift:"area,5" form:"area" json:"area" vd:"$>0"`
UserPassword string `thrift:"user_password,6" form:"user_password" json:"user_password" vd:"(len($) > 0 && len($) < 15)"`
}
@@ -7613,11 +7613,12 @@ func (p *ListFriendRelationshipReq) String() string {
}
type FriendRelationshipListInfo struct {
UserID string `thrift:"user_id,1" form:"user_id" json:"user_id" query:"user_id"`
ID int64 `thrift:"id,1" form:"id" json:"id" query:"id"`
ApplicationMessage string `thrift:"application_message,2" form:"application_message" json:"application_message" query:"application_message"`
Status int8 `thrift:"status,3" form:"status" json:"status" query:"status"`
UserName string `thrift:"user_name,4" form:"user_name" json:"user_name" query:"user_name"`
AvatarImageURL string `thrift:"avatar_image_url,5" form:"avatar_image_url" json:"avatar_image_url" query:"avatar_image_url"`
UserID string `thrift:"user_id,6" form:"user_id" json:"user_id" query:"user_id"`
}
func NewFriendRelationshipListInfo() *FriendRelationshipListInfo {
@@ -7627,8 +7628,8 @@ func NewFriendRelationshipListInfo() *FriendRelationshipListInfo {
func (p *FriendRelationshipListInfo) InitDefault() {
}
func (p *FriendRelationshipListInfo) GetUserID() (v string) {
return p.UserID
func (p *FriendRelationshipListInfo) GetID() (v int64) {
return p.ID
}
func (p *FriendRelationshipListInfo) GetApplicationMessage() (v string) {
@@ -7647,12 +7648,17 @@ func (p *FriendRelationshipListInfo) GetAvatarImageURL() (v string) {
return p.AvatarImageURL
}
func (p *FriendRelationshipListInfo) GetUserID() (v string) {
return p.UserID
}
var fieldIDToName_FriendRelationshipListInfo = map[int16]string{
1: "user_id",
1: "id",
2: "application_message",
3: "status",
4: "user_name",
5: "avatar_image_url",
6: "user_id",
}
func (p *FriendRelationshipListInfo) Read(iprot thrift.TProtocol) (err error) {
@@ -7674,7 +7680,7 @@ func (p *FriendRelationshipListInfo) Read(iprot thrift.TProtocol) (err error) {
switch fieldId {
case 1:
if fieldTypeId == thrift.STRING {
if fieldTypeId == thrift.I64 {
if err = p.ReadField1(iprot); err != nil {
goto ReadFieldError
}
@@ -7713,6 +7719,14 @@ func (p *FriendRelationshipListInfo) Read(iprot thrift.TProtocol) (err error) {
} else if err = iprot.Skip(fieldTypeId); err != nil {
goto SkipFieldError
}
case 6:
if fieldTypeId == thrift.STRING {
if err = p.ReadField6(iprot); err != nil {
goto ReadFieldError
}
} else if err = iprot.Skip(fieldTypeId); err != nil {
goto SkipFieldError
}
default:
if err = iprot.Skip(fieldTypeId); err != nil {
goto SkipFieldError
@@ -7744,13 +7758,13 @@ ReadStructEndError:
func (p *FriendRelationshipListInfo) ReadField1(iprot thrift.TProtocol) error {
var _field string
if v, err := iprot.ReadString(); err != nil {
var _field int64
if v, err := iprot.ReadI64(); err != nil {
return err
} else {
_field = v
}
p.UserID = _field
p.ID = _field
return nil
}
func (p *FriendRelationshipListInfo) ReadField2(iprot thrift.TProtocol) error {
@@ -7797,6 +7811,17 @@ func (p *FriendRelationshipListInfo) ReadField5(iprot thrift.TProtocol) error {
p.AvatarImageURL = _field
return nil
}
func (p *FriendRelationshipListInfo) ReadField6(iprot thrift.TProtocol) error {
var _field string
if v, err := iprot.ReadString(); err != nil {
return err
} else {
_field = v
}
p.UserID = _field
return nil
}
func (p *FriendRelationshipListInfo) Write(oprot thrift.TProtocol) (err error) {
var fieldId int16
@@ -7824,6 +7849,10 @@ func (p *FriendRelationshipListInfo) Write(oprot thrift.TProtocol) (err error) {
fieldId = 5
goto WriteFieldError
}
if err = p.writeField6(oprot); err != nil {
fieldId = 6
goto WriteFieldError
}
}
if err = oprot.WriteFieldStop(); err != nil {
goto WriteFieldStopError
@@ -7843,10 +7872,10 @@ WriteStructEndError:
}
func (p *FriendRelationshipListInfo) writeField1(oprot thrift.TProtocol) (err error) {
if err = oprot.WriteFieldBegin("user_id", thrift.STRING, 1); err != nil {
if err = oprot.WriteFieldBegin("id", thrift.I64, 1); err != nil {
goto WriteFieldBeginError
}
if err := oprot.WriteString(p.UserID); err != nil {
if err := oprot.WriteI64(p.ID); err != nil {
return err
}
if err = oprot.WriteFieldEnd(); err != nil {
@@ -7922,6 +7951,22 @@ WriteFieldBeginError:
WriteFieldEndError:
return thrift.PrependError(fmt.Sprintf("%T write field 5 end error: ", p), err)
}
func (p *FriendRelationshipListInfo) writeField6(oprot thrift.TProtocol) (err error) {
if err = oprot.WriteFieldBegin("user_id", thrift.STRING, 6); err != nil {
goto WriteFieldBeginError
}
if err := oprot.WriteString(p.UserID); err != nil {
return err
}
if err = oprot.WriteFieldEnd(); err != nil {
goto WriteFieldEndError
}
return nil
WriteFieldBeginError:
return thrift.PrependError(fmt.Sprintf("%T write field 6 begin error: ", p), err)
WriteFieldEndError:
return thrift.PrependError(fmt.Sprintf("%T write field 6 end error: ", p), err)
}
func (p *FriendRelationshipListInfo) String() string {
if p == nil {

View File

@@ -238,11 +238,12 @@ struct ListFriendRelationshipReq{
}
struct FriendRelationshipListInfo {
1: string user_id
1: i64 id
2: string application_message
3: i8 status
4: string user_name
5: string avatar_image_url
6: string user_id
}
struct ListFriendRelationshipRes{

View File

@@ -0,0 +1,56 @@
package livekit
import (
"audioAndVideoCalls/biz/dal/redis"
audioAndVideoCalls "audioAndVideoCalls/biz/model/audioAndVideoCalls"
"audioAndVideoCalls/protocol"
"encoding/json"
"errors"
"github.com/cloudwego/hertz/pkg/common/hlog"
"time"
)
var livekitClient = GetGlobalRoomClient()
func AudioCall(req audioAndVideoCalls.AudioCallReq) error {
if req.UserID == "" {
return errors.New("invalid user id")
}
if req.TargetUserID == "" {
return errors.New("invalid target user id")
}
//creatReq := &livekit.CreateRoomRequest{
// Name: utils.GenerateUniqueAudioRoomName(),
// EmptyTimeout: 60,
// MaxParticipants: 2,
// MinPlayoutDelay: 0,
// MaxPlayoutDelay: 0,
// SyncStreams: false,
//}
//room, err := livekitClient.CreateRoom(creatReq)
//if err != nil {
// return err
//}
//
//livekitClient.GetJoinToken(room.Name,req.UserID,"")
msg := protocol.Message{
Type: protocol.TypeAudioCallReq,
FileType: "",
From: req.UserID,
To: req.TargetUserID,
Content: "Audio Call",
MsgID: "",
SendTime: time.Now().Format("2006-01-02 15:04:05"),
Expand: nil,
}
// 序列化消息
msgBytes, err := json.Marshal(msg)
if err != nil {
hlog.Errorf("消息序列化错误: %v", err)
return err
}
redis.PublishToRedis(protocol.TypePrivate+":"+req.TargetUserID, msgBytes)
return nil
}

View File

@@ -3,16 +3,16 @@
package audioAndVideoCalls
import (
"context"
"audioAndVideoCalls/biz/dal/livekit"
audioAndVideoCalls "audioAndVideoCalls/biz/model/audioAndVideoCalls"
"context"
"github.com/cloudwego/hertz/pkg/app"
"github.com/cloudwego/hertz/pkg/protocol/consts"
)
// HelloMethod .
// @router /audioCall [GET]
func HelloMethod(ctx context.Context, c *app.RequestContext) {
// Call .
// @router /audioCall [POST]
func Call(ctx context.Context, c *app.RequestContext) {
var err error
var req audioAndVideoCalls.AudioCallReq
err = c.BindAndValidate(&req)
@@ -20,7 +20,11 @@ func HelloMethod(ctx context.Context, c *app.RequestContext) {
c.String(consts.StatusBadRequest, err.Error())
return
}
err = livekit.AudioCall(req)
if err != nil {
c.JSON(consts.StatusBadRequest, err.Error())
return
}
resp := new(audioAndVideoCalls.AudioCallResp)
c.JSON(consts.StatusOK, resp)

View File

@@ -63,8 +63,8 @@ func (p *Code) Value() (driver.Value, error) {
}
type AudioCallReq struct {
UserID string `thrift:"user_id,1" json:"user_id" query:"user_id"`
TargetUserID string `thrift:"target_user_id,2" json:"target_user_id" query:"target_user_id"`
UserID string `thrift:"user_id,1" form:"user_id" json:"user_id"`
TargetUserID string `thrift:"target_user_id,2" form:"target_user_id" json:"target_user_id"`
}
func NewAudioCallReq() *AudioCallReq {
@@ -247,11 +247,8 @@ func (p *AudioCallReq) String() string {
}
type AudioCallResp struct {
Code Code `thrift:"code,1" form:"code" json:"code" query:"code"`
Msg string `thrift:"msg,2" form:"msg" json:"msg" query:"msg"`
Room string `thrift:"room,3" form:"room" json:"room" query:"room"`
Auth string `thrift:"auth,4" form:"auth" json:"auth" query:"auth"`
LivekitServer string `thrift:"livekit_server,5" form:"livekit_server" json:"livekit_server" query:"livekit_server"`
Code Code `thrift:"code,1" form:"code" json:"code" query:"code"`
Msg string `thrift:"msg,2" form:"msg" json:"msg" query:"msg"`
}
func NewAudioCallResp() *AudioCallResp {
@@ -269,24 +266,9 @@ func (p *AudioCallResp) GetMsg() (v string) {
return p.Msg
}
func (p *AudioCallResp) GetRoom() (v string) {
return p.Room
}
func (p *AudioCallResp) GetAuth() (v string) {
return p.Auth
}
func (p *AudioCallResp) GetLivekitServer() (v string) {
return p.LivekitServer
}
var fieldIDToName_AudioCallResp = map[int16]string{
1: "code",
2: "msg",
3: "room",
4: "auth",
5: "livekit_server",
}
func (p *AudioCallResp) Read(iprot thrift.TProtocol) (err error) {
@@ -323,30 +305,6 @@ func (p *AudioCallResp) Read(iprot thrift.TProtocol) (err error) {
} else if err = iprot.Skip(fieldTypeId); err != nil {
goto SkipFieldError
}
case 3:
if fieldTypeId == thrift.STRING {
if err = p.ReadField3(iprot); err != nil {
goto ReadFieldError
}
} else if err = iprot.Skip(fieldTypeId); err != nil {
goto SkipFieldError
}
case 4:
if fieldTypeId == thrift.STRING {
if err = p.ReadField4(iprot); err != nil {
goto ReadFieldError
}
} else if err = iprot.Skip(fieldTypeId); err != nil {
goto SkipFieldError
}
case 5:
if fieldTypeId == thrift.STRING {
if err = p.ReadField5(iprot); err != nil {
goto ReadFieldError
}
} else if err = iprot.Skip(fieldTypeId); err != nil {
goto SkipFieldError
}
default:
if err = iprot.Skip(fieldTypeId); err != nil {
goto SkipFieldError
@@ -398,39 +356,6 @@ func (p *AudioCallResp) ReadField2(iprot thrift.TProtocol) error {
p.Msg = _field
return nil
}
func (p *AudioCallResp) ReadField3(iprot thrift.TProtocol) error {
var _field string
if v, err := iprot.ReadString(); err != nil {
return err
} else {
_field = v
}
p.Room = _field
return nil
}
func (p *AudioCallResp) ReadField4(iprot thrift.TProtocol) error {
var _field string
if v, err := iprot.ReadString(); err != nil {
return err
} else {
_field = v
}
p.Auth = _field
return nil
}
func (p *AudioCallResp) ReadField5(iprot thrift.TProtocol) error {
var _field string
if v, err := iprot.ReadString(); err != nil {
return err
} else {
_field = v
}
p.LivekitServer = _field
return nil
}
func (p *AudioCallResp) Write(oprot thrift.TProtocol) (err error) {
var fieldId int16
@@ -446,18 +371,6 @@ func (p *AudioCallResp) Write(oprot thrift.TProtocol) (err error) {
fieldId = 2
goto WriteFieldError
}
if err = p.writeField3(oprot); err != nil {
fieldId = 3
goto WriteFieldError
}
if err = p.writeField4(oprot); err != nil {
fieldId = 4
goto WriteFieldError
}
if err = p.writeField5(oprot); err != nil {
fieldId = 5
goto WriteFieldError
}
}
if err = oprot.WriteFieldStop(); err != nil {
goto WriteFieldStopError
@@ -508,54 +421,6 @@ WriteFieldBeginError:
WriteFieldEndError:
return thrift.PrependError(fmt.Sprintf("%T write field 2 end error: ", p), err)
}
func (p *AudioCallResp) writeField3(oprot thrift.TProtocol) (err error) {
if err = oprot.WriteFieldBegin("room", thrift.STRING, 3); err != nil {
goto WriteFieldBeginError
}
if err := oprot.WriteString(p.Room); err != nil {
return err
}
if err = oprot.WriteFieldEnd(); err != nil {
goto WriteFieldEndError
}
return nil
WriteFieldBeginError:
return thrift.PrependError(fmt.Sprintf("%T write field 3 begin error: ", p), err)
WriteFieldEndError:
return thrift.PrependError(fmt.Sprintf("%T write field 3 end error: ", p), err)
}
func (p *AudioCallResp) writeField4(oprot thrift.TProtocol) (err error) {
if err = oprot.WriteFieldBegin("auth", thrift.STRING, 4); err != nil {
goto WriteFieldBeginError
}
if err := oprot.WriteString(p.Auth); err != nil {
return err
}
if err = oprot.WriteFieldEnd(); err != nil {
goto WriteFieldEndError
}
return nil
WriteFieldBeginError:
return thrift.PrependError(fmt.Sprintf("%T write field 4 begin error: ", p), err)
WriteFieldEndError:
return thrift.PrependError(fmt.Sprintf("%T write field 4 end error: ", p), err)
}
func (p *AudioCallResp) writeField5(oprot thrift.TProtocol) (err error) {
if err = oprot.WriteFieldBegin("livekit_server", thrift.STRING, 5); err != nil {
goto WriteFieldBeginError
}
if err := oprot.WriteString(p.LivekitServer); err != nil {
return err
}
if err = oprot.WriteFieldEnd(); err != nil {
goto WriteFieldEndError
}
return nil
WriteFieldBeginError:
return thrift.PrependError(fmt.Sprintf("%T write field 5 begin error: ", p), err)
WriteFieldEndError:
return thrift.PrependError(fmt.Sprintf("%T write field 5 end error: ", p), err)
}
func (p *AudioCallResp) String() string {
if p == nil {
@@ -566,7 +431,7 @@ func (p *AudioCallResp) String() string {
}
type AudioCallService interface {
HelloMethod(ctx context.Context, request *AudioCallReq) (r *AudioCallResp, err error)
Call(ctx context.Context, request *AudioCallReq) (r *AudioCallResp, err error)
}
type AudioCallServiceClient struct {
@@ -595,11 +460,11 @@ func (p *AudioCallServiceClient) Client_() thrift.TClient {
return p.c
}
func (p *AudioCallServiceClient) HelloMethod(ctx context.Context, request *AudioCallReq) (r *AudioCallResp, err error) {
var _args AudioCallServiceHelloMethodArgs
func (p *AudioCallServiceClient) Call(ctx context.Context, request *AudioCallReq) (r *AudioCallResp, err error) {
var _args AudioCallServiceCallArgs
_args.Request = request
var _result AudioCallServiceHelloMethodResult
if err = p.Client_().Call(ctx, "HelloMethod", &_args, &_result); err != nil {
var _result AudioCallServiceCallResult
if err = p.Client_().Call(ctx, "Call", &_args, &_result); err != nil {
return
}
return _result.GetSuccess(), nil
@@ -625,7 +490,7 @@ func (p *AudioCallServiceProcessor) ProcessorMap() map[string]thrift.TProcessorF
func NewAudioCallServiceProcessor(handler AudioCallService) *AudioCallServiceProcessor {
self := &AudioCallServiceProcessor{handler: handler, processorMap: make(map[string]thrift.TProcessorFunction)}
self.AddToProcessorMap("HelloMethod", &audioCallServiceProcessorHelloMethod{handler: handler})
self.AddToProcessorMap("Call", &audioCallServiceProcessorCall{handler: handler})
return self
}
func (p *AudioCallServiceProcessor) Process(ctx context.Context, iprot, oprot thrift.TProtocol) (success bool, err thrift.TException) {
@@ -646,16 +511,16 @@ func (p *AudioCallServiceProcessor) Process(ctx context.Context, iprot, oprot th
return false, x
}
type audioCallServiceProcessorHelloMethod struct {
type audioCallServiceProcessorCall struct {
handler AudioCallService
}
func (p *audioCallServiceProcessorHelloMethod) Process(ctx context.Context, seqId int32, iprot, oprot thrift.TProtocol) (success bool, err thrift.TException) {
args := AudioCallServiceHelloMethodArgs{}
func (p *audioCallServiceProcessorCall) Process(ctx context.Context, seqId int32, iprot, oprot thrift.TProtocol) (success bool, err thrift.TException) {
args := AudioCallServiceCallArgs{}
if err = args.Read(iprot); err != nil {
iprot.ReadMessageEnd()
x := thrift.NewTApplicationException(thrift.PROTOCOL_ERROR, err.Error())
oprot.WriteMessageBegin("HelloMethod", thrift.EXCEPTION, seqId)
oprot.WriteMessageBegin("Call", thrift.EXCEPTION, seqId)
x.Write(oprot)
oprot.WriteMessageEnd()
oprot.Flush(ctx)
@@ -664,11 +529,11 @@ func (p *audioCallServiceProcessorHelloMethod) Process(ctx context.Context, seqI
iprot.ReadMessageEnd()
var err2 error
result := AudioCallServiceHelloMethodResult{}
result := AudioCallServiceCallResult{}
var retval *AudioCallResp
if retval, err2 = p.handler.HelloMethod(ctx, args.Request); err2 != nil {
x := thrift.NewTApplicationException(thrift.INTERNAL_ERROR, "Internal error processing HelloMethod: "+err2.Error())
oprot.WriteMessageBegin("HelloMethod", thrift.EXCEPTION, seqId)
if retval, err2 = p.handler.Call(ctx, args.Request); err2 != nil {
x := thrift.NewTApplicationException(thrift.INTERNAL_ERROR, "Internal error processing Call: "+err2.Error())
oprot.WriteMessageBegin("Call", thrift.EXCEPTION, seqId)
x.Write(oprot)
oprot.WriteMessageEnd()
oprot.Flush(ctx)
@@ -676,7 +541,7 @@ func (p *audioCallServiceProcessorHelloMethod) Process(ctx context.Context, seqI
} else {
result.Success = retval
}
if err2 = oprot.WriteMessageBegin("HelloMethod", thrift.REPLY, seqId); err2 != nil {
if err2 = oprot.WriteMessageBegin("Call", thrift.REPLY, seqId); err2 != nil {
err = err2
}
if err2 = result.Write(oprot); err == nil && err2 != nil {
@@ -694,35 +559,35 @@ func (p *audioCallServiceProcessorHelloMethod) Process(ctx context.Context, seqI
return true, err
}
type AudioCallServiceHelloMethodArgs struct {
type AudioCallServiceCallArgs struct {
Request *AudioCallReq `thrift:"request,1"`
}
func NewAudioCallServiceHelloMethodArgs() *AudioCallServiceHelloMethodArgs {
return &AudioCallServiceHelloMethodArgs{}
func NewAudioCallServiceCallArgs() *AudioCallServiceCallArgs {
return &AudioCallServiceCallArgs{}
}
func (p *AudioCallServiceHelloMethodArgs) InitDefault() {
func (p *AudioCallServiceCallArgs) InitDefault() {
}
var AudioCallServiceHelloMethodArgs_Request_DEFAULT *AudioCallReq
var AudioCallServiceCallArgs_Request_DEFAULT *AudioCallReq
func (p *AudioCallServiceHelloMethodArgs) GetRequest() (v *AudioCallReq) {
func (p *AudioCallServiceCallArgs) GetRequest() (v *AudioCallReq) {
if !p.IsSetRequest() {
return AudioCallServiceHelloMethodArgs_Request_DEFAULT
return AudioCallServiceCallArgs_Request_DEFAULT
}
return p.Request
}
var fieldIDToName_AudioCallServiceHelloMethodArgs = map[int16]string{
var fieldIDToName_AudioCallServiceCallArgs = map[int16]string{
1: "request",
}
func (p *AudioCallServiceHelloMethodArgs) IsSetRequest() bool {
func (p *AudioCallServiceCallArgs) IsSetRequest() bool {
return p.Request != nil
}
func (p *AudioCallServiceHelloMethodArgs) Read(iprot thrift.TProtocol) (err error) {
func (p *AudioCallServiceCallArgs) Read(iprot thrift.TProtocol) (err error) {
var fieldTypeId thrift.TType
var fieldId int16
@@ -767,7 +632,7 @@ ReadStructBeginError:
ReadFieldBeginError:
return thrift.PrependError(fmt.Sprintf("%T read field %d begin error: ", p, fieldId), err)
ReadFieldError:
return thrift.PrependError(fmt.Sprintf("%T read field %d '%s' error: ", p, fieldId, fieldIDToName_AudioCallServiceHelloMethodArgs[fieldId]), err)
return thrift.PrependError(fmt.Sprintf("%T read field %d '%s' error: ", p, fieldId, fieldIDToName_AudioCallServiceCallArgs[fieldId]), err)
SkipFieldError:
return thrift.PrependError(fmt.Sprintf("%T field %d skip type %d error: ", p, fieldId, fieldTypeId), err)
@@ -777,7 +642,7 @@ ReadStructEndError:
return thrift.PrependError(fmt.Sprintf("%T read struct end error: ", p), err)
}
func (p *AudioCallServiceHelloMethodArgs) ReadField1(iprot thrift.TProtocol) error {
func (p *AudioCallServiceCallArgs) ReadField1(iprot thrift.TProtocol) error {
_field := NewAudioCallReq()
if err := _field.Read(iprot); err != nil {
return err
@@ -786,9 +651,9 @@ func (p *AudioCallServiceHelloMethodArgs) ReadField1(iprot thrift.TProtocol) err
return nil
}
func (p *AudioCallServiceHelloMethodArgs) Write(oprot thrift.TProtocol) (err error) {
func (p *AudioCallServiceCallArgs) Write(oprot thrift.TProtocol) (err error) {
var fieldId int16
if err = oprot.WriteStructBegin("HelloMethod_args"); err != nil {
if err = oprot.WriteStructBegin("Call_args"); err != nil {
goto WriteStructBeginError
}
if p != nil {
@@ -814,7 +679,7 @@ WriteStructEndError:
return thrift.PrependError(fmt.Sprintf("%T write struct end error: ", p), err)
}
func (p *AudioCallServiceHelloMethodArgs) writeField1(oprot thrift.TProtocol) (err error) {
func (p *AudioCallServiceCallArgs) writeField1(oprot thrift.TProtocol) (err error) {
if err = oprot.WriteFieldBegin("request", thrift.STRUCT, 1); err != nil {
goto WriteFieldBeginError
}
@@ -831,43 +696,43 @@ WriteFieldEndError:
return thrift.PrependError(fmt.Sprintf("%T write field 1 end error: ", p), err)
}
func (p *AudioCallServiceHelloMethodArgs) String() string {
func (p *AudioCallServiceCallArgs) String() string {
if p == nil {
return "<nil>"
}
return fmt.Sprintf("AudioCallServiceHelloMethodArgs(%+v)", *p)
return fmt.Sprintf("AudioCallServiceCallArgs(%+v)", *p)
}
type AudioCallServiceHelloMethodResult struct {
type AudioCallServiceCallResult struct {
Success *AudioCallResp `thrift:"success,0,optional"`
}
func NewAudioCallServiceHelloMethodResult() *AudioCallServiceHelloMethodResult {
return &AudioCallServiceHelloMethodResult{}
func NewAudioCallServiceCallResult() *AudioCallServiceCallResult {
return &AudioCallServiceCallResult{}
}
func (p *AudioCallServiceHelloMethodResult) InitDefault() {
func (p *AudioCallServiceCallResult) InitDefault() {
}
var AudioCallServiceHelloMethodResult_Success_DEFAULT *AudioCallResp
var AudioCallServiceCallResult_Success_DEFAULT *AudioCallResp
func (p *AudioCallServiceHelloMethodResult) GetSuccess() (v *AudioCallResp) {
func (p *AudioCallServiceCallResult) GetSuccess() (v *AudioCallResp) {
if !p.IsSetSuccess() {
return AudioCallServiceHelloMethodResult_Success_DEFAULT
return AudioCallServiceCallResult_Success_DEFAULT
}
return p.Success
}
var fieldIDToName_AudioCallServiceHelloMethodResult = map[int16]string{
var fieldIDToName_AudioCallServiceCallResult = map[int16]string{
0: "success",
}
func (p *AudioCallServiceHelloMethodResult) IsSetSuccess() bool {
func (p *AudioCallServiceCallResult) IsSetSuccess() bool {
return p.Success != nil
}
func (p *AudioCallServiceHelloMethodResult) Read(iprot thrift.TProtocol) (err error) {
func (p *AudioCallServiceCallResult) Read(iprot thrift.TProtocol) (err error) {
var fieldTypeId thrift.TType
var fieldId int16
@@ -912,7 +777,7 @@ ReadStructBeginError:
ReadFieldBeginError:
return thrift.PrependError(fmt.Sprintf("%T read field %d begin error: ", p, fieldId), err)
ReadFieldError:
return thrift.PrependError(fmt.Sprintf("%T read field %d '%s' error: ", p, fieldId, fieldIDToName_AudioCallServiceHelloMethodResult[fieldId]), err)
return thrift.PrependError(fmt.Sprintf("%T read field %d '%s' error: ", p, fieldId, fieldIDToName_AudioCallServiceCallResult[fieldId]), err)
SkipFieldError:
return thrift.PrependError(fmt.Sprintf("%T field %d skip type %d error: ", p, fieldId, fieldTypeId), err)
@@ -922,7 +787,7 @@ ReadStructEndError:
return thrift.PrependError(fmt.Sprintf("%T read struct end error: ", p), err)
}
func (p *AudioCallServiceHelloMethodResult) ReadField0(iprot thrift.TProtocol) error {
func (p *AudioCallServiceCallResult) ReadField0(iprot thrift.TProtocol) error {
_field := NewAudioCallResp()
if err := _field.Read(iprot); err != nil {
return err
@@ -931,9 +796,9 @@ func (p *AudioCallServiceHelloMethodResult) ReadField0(iprot thrift.TProtocol) e
return nil
}
func (p *AudioCallServiceHelloMethodResult) Write(oprot thrift.TProtocol) (err error) {
func (p *AudioCallServiceCallResult) Write(oprot thrift.TProtocol) (err error) {
var fieldId int16
if err = oprot.WriteStructBegin("HelloMethod_result"); err != nil {
if err = oprot.WriteStructBegin("Call_result"); err != nil {
goto WriteStructBeginError
}
if p != nil {
@@ -959,7 +824,7 @@ WriteStructEndError:
return thrift.PrependError(fmt.Sprintf("%T write struct end error: ", p), err)
}
func (p *AudioCallServiceHelloMethodResult) writeField0(oprot thrift.TProtocol) (err error) {
func (p *AudioCallServiceCallResult) writeField0(oprot thrift.TProtocol) (err error) {
if p.IsSetSuccess() {
if err = oprot.WriteFieldBegin("success", thrift.STRUCT, 0); err != nil {
goto WriteFieldBeginError
@@ -978,10 +843,10 @@ WriteFieldEndError:
return thrift.PrependError(fmt.Sprintf("%T write field 0 end error: ", p), err)
}
func (p *AudioCallServiceHelloMethodResult) String() string {
func (p *AudioCallServiceCallResult) String() string {
if p == nil {
return "<nil>"
}
return fmt.Sprintf("AudioCallServiceHelloMethodResult(%+v)", *p)
return fmt.Sprintf("AudioCallServiceCallResult(%+v)", *p)
}

View File

@@ -17,5 +17,5 @@ import (
func Register(r *server.Hertz) {
root := r.Group("/", rootMw()...)
root.GET("/audioCall", append(_hellomethodMw(), audioAndVideoCalls.HelloMethod)...)
root.POST("/audioCall", append(_callMw(), audioAndVideoCalls.Call)...)
}

View File

@@ -15,3 +15,8 @@ func _hellomethodMw() []app.HandlerFunc {
// your code...
return nil
}
func _callMw() []app.HandlerFunc {
// your code...
return nil
}

View File

@@ -0,0 +1,30 @@
package utils
import (
"crypto/rand"
"encoding/base64"
"fmt"
"time"
)
// GenerateUniqueAudioRoomName 生成唯一音频房间名
// 格式:[时间戳(16进制)]-[随机字符(4位)]
func GenerateUniqueAudioRoomName() string {
// 1. 获取毫秒级时间戳并转为16进制缩短长度
timestamp := time.Now().UnixMilli() // 毫秒级时间戳13位数字
hexTimestamp := fmt.Sprintf("%x", timestamp) // 转为16进制约10-11位
// 2. 生成4位随机字符字母+数字)
randomBytes := make([]byte, 3) // 3字节经base64编码后约4字符
_, err := rand.Read(randomBytes)
if err != nil {
// 极端情况下随机数生成失败,用当前纳秒补充(降低重复风险)
ns := time.Now().UnixNano() % 10000
return fmt.Sprintf("%s-%04d", hexTimestamp, ns)
}
// 取base64的前4位过滤特殊字符
randomStr := base64.URLEncoding.EncodeToString(randomBytes)[:4]
// 3. 拼接结果
return fmt.Sprintf("audioRoom:%s-%s", hexTimestamp, randomStr)
}

View File

@@ -9,19 +9,16 @@ enum Code {
struct audioCallReq {
1: string user_id (api.query="user_id");
2: string target_user_id (api.query="target_user_id");
1: string user_id (api.body="user_id");
2: string target_user_id (api.body="target_user_id");
}
struct audioCallResp {
1: Code code
2: string msg
3: string room
4: string auth
5: string livekit_server
}
service AudioCallService {
audioCallResp HelloMethod(1: audioCallReq request) (api.get="/audioCall");
audioCallResp Call(1: audioCallReq request) (api.post="/audioCall");
}

View File

@@ -17,8 +17,8 @@ DbPassWord =
[database]
MysqlHost = 127.0.0.1
MysqlPort = 3306
MysqlUser = iuqtRoot
MysqlPassWord = mN3x4diYX6NzmC5a
MysqlUser = root
MysqlPassWord = 123456
MysqlDBName = iuqt_acquaintances
#ETCD参数