package commentctrl import ( "91porn-server/common" "91porn-server/common/constant" "91porn-server/common/log" "91porn-server/common/stderr" "91porn-server/models/l/operatorlgmod" "91porn-server/models/v/cmtmod" "91porn-server/models/v/likemod" "91porn-server/models/v/vidmod" "91porn-server/web/service/commentser" "91porn-server/web/webg" "encoding/json" "errors" "fmt" "io" "math/rand" "os" "path/filepath" "strconv" "strings" "time" "github.com/gin-gonic/gin" "github.com/tealeg/xlsx" "go.mongodb.org/mongo-driver/bson/primitive" ) // List doc // @Summary 评论管理 // @Description 评论列表 // @Tags Web-Comment // @Accept mpfd,json // @Produce json,html // @Param vidID query string false "视频id" // @Param uid query integer false "用户id" // @Param content query string false "评论内容" // @Param status query integer false "审核状态" // @Param pageNumber query integer true "页码" // @Param pageSize query integer true "每页条数" // @Success 200 {string} json "{"msg": "操作成功", "data":[]}" // @Failure 400 {string} json "{"msg": "操作失败"}" // @Router /web/comment/list [get] func List(ctx *gin.Context) { param := cmtmod.WebCmtListReqInfo{} if err := ctx.ShouldBind(¶m); err != nil { common.ServeJSON(ctx, stderr.ErrParamError, err) return } data, err := commentser.GetCommentList(param.VidID, param.UID, param.Content, param.IsRobot, param.IsAdvertiser, param.Status, param.Page) if err != nil { common.ServeJSON(ctx, stderr.Failure, err) return } common.ServeJSON(ctx, stderr.Success, data) } // Delete doc // @Summary 评论管理 - 删除评论(逻辑删除) // @Description 评论删除 // @Tags Web-Comment // @Accept mpfd,json // @Produce json,html // @Param ids formData array true "需要屏蔽的评论id" // @Success 200 {string} json "{"msg": "操作成功", "data":[]}" // @Failure 400 {string} json "{"msg": "操作失败"}" // @Router /web/comment/delete [post] func Delete(ctx *gin.Context) { manager, err := common.GetAdminAct(ctx) if err != nil { common.ServeJSON(ctx, stderr.AdminIDErr, err.Error()) return } param := cmtmod.WebCmtDeleteReqInfo{} if err := ctx.ShouldBind(¶m); err != nil { common.ServeJSON(ctx, stderr.ErrParamError, err) return } if len(param.IDS) == 0 && param.UID == 0 { err := errors.New(fmt.Sprintf("ids is null")) common.ServeJSON(ctx, stderr.ErrParamError, err) return } if err := commentser.DeleteCommentsByID(param.IDS, param.UID, param.Content); err != nil { common.ServeJSON(ctx, stderr.Failure, err) return } log, _ := json.Marshal(param) _ = operatorlgmod.RecordOperation(manager, constant.VideoManageComment, constant.Delete, string(log), ctx.Request.URL.RequestURI()) common.ServeJSON(ctx, stderr.Success, nil) } // Info doc // @Summary 评论管理 // @Description 评论详情 // @Tags Web-Comment // @Accept mpfd,json // @Produce json,html // @Param id query string true "评论id" // @Success 200 {string} json "{"msg": "操作成功", "data":[]}" // @Failure 400 {string} json "{"msg": "操作失败"}" // @Router /web/comment/info [get] func Info(ctx *gin.Context) { param := cmtmod.WebCmtReqInfo{} if err := ctx.ShouldBind(¶m); err != nil { common.ServeJSON(ctx, stderr.ErrParamError, err) return } data, err := commentser.GetCommentInfo(param.ID) if err != nil { common.ServeJSON(ctx, stderr.Failure, err) return } common.ServeJSON(ctx, stderr.Success, data) } // Access doc // @Summary 评论管理 // @Description 通过审核 // @Tags Web-Comment // @Accept mpfd,json // @Produce json,html // @Param id query string true "评论id" // @Success 200 {string} json "{"msg": "操作成功", "data":[]}" // @Failure 400 {string} json "{"msg": "操作失败"}" // @Router /web/comment/access [post] func Access(ctx *gin.Context) { param := cmtmod.WebCmtReqInfo{} if err := ctx.ShouldBind(¶m); err != nil { common.ServeJSON(ctx, stderr.ErrParamError, err) return } if err := commentser.AccessComment(param.ID); err != nil { common.ServeJSON(ctx, stderr.Failure, err) return } common.ServeJSON(ctx, stderr.Success, nil) } // BatchAccess doc // @Summary 评论管理 // @Description 批量通过审核 // @Tags Web-Comment // @Accept mpfd,json // @Produce json,html // @Param ids query []string true "评论ids" // @Param status query integer true "审核状态" // @Success 200 {string} json "{"msg": "操作成功", "data":[]}" // @Failure 400 {string} json "{"msg": "操作失败"}" // @Router /api/web/admin/comment/batch/access [post] func BatchAccess(ctx *gin.Context) { param := cmtmod.BatchPassReqInfo{} if err := ctx.ShouldBind(¶m); err != nil { common.ServeJSON(ctx, stderr.ErrParamError, err) return } if err := commentser.BatchAccessComment(param.IDS, param.Status); err != nil { common.ServeJSON(ctx, stderr.Failure, err) return } common.ServeJSON(ctx, stderr.Success, nil) } // Update doc // @Summary 修改评论管理 // @Description 修改评论为神评论 // @Tags Web-Comment // @Accept mpfd,json // @Produce json,html // @Param id query string true "评论id" // @Success 200 {string} json "{"msg": "操作成功", "data":[]}" // @Failure 400 {string} json "{"msg": "操作失败"}" // @Router /api/web/admin/comment/update [post] func Update(ctx *gin.Context) { in := cmtmod.EditCond{} if err := ctx.ShouldBind(&in); err != nil { common.ServeJSON(ctx, stderr.ErrParamError, err) return } if code := commentser.UpdateComment(&in); code != stderr.Success { log.Error("web service comment UpdateComment error", log.E(code), log.Any("id", in.ID)) common.ServeJSON(ctx, stderr.Failure, code) return } common.ServeJSON(ctx, stderr.Success, nil) } // AddContentExcel // 导入评论内容 doc // @Summary 导入评论内容 // @Description 导入评论内容 // @Tags Web-Comment // @Accept mpfd,json // @Produce json,html // @Param upload formData file true "需要导入的文件 只支持 .xls .xlsx文件" // @Success 200 {string} json "{"msg": "操作成功", "data":[]}" // @Failure 400 {string} json "{"msg": "操作失败"}" // @Router /api/web/admin/comment/importExcel [post] func AddContentExcel(ctx *gin.Context) { now := time.Now() pwd, err := os.Getwd() if err != nil { common.ServeJSON(ctx, stderr.ErrServerUnavailable, err) return } file, fHeader, err := ctx.Request.FormFile("upload") if err != nil { common.ServeJSON(ctx, stderr.ErrServerUnavailable, err) return } ext := filepath.Ext(fHeader.Filename) if !strings.ContainsAny(ext, "xls") { common.ServeJSON(ctx, stderr.ErrMimeType, nil) return } fPath := pwd + "/" + fHeader.Filename //defer os.Remove(fPath) // header调用Filename方法,就可以得到文件名 out, err := os.Create(fPath) if err != nil { return } //defer out.Close() // 将file的内容拷贝到out _, err = io.Copy(out, file) if err != nil { return } var citys = webg.Static.Cities var uids = webg.Static.SysUser xlFile, err := xlsx.OpenFile(fPath) if err != nil { return } rand.Seed(time.Now().Unix()) comments := make([]*cmtmod.Comment, 0) likes := make([]*likemod.Like, 0) commentCountMap := make(map[primitive.ObjectID]int) // 遍历sheet页读取 for _, sheet := range xlFile.Sheets { fmt.Println("sheet name: ", sheet.Name) //遍历行读取 for _, row := range sheet.Rows { // 遍历每行的列读取 var content string var vid string var likeCount int64 for k, cell := range row.Cells { str := cell.String() if str == "" { break } if k == 0 { content = strings.TrimSpace(cell.String()) } if k == 1 { vid = strings.TrimSpace(cell.String()) } if k == 2 { likeCount, _ = strconv.ParseInt(cell.String(), 10, 64) } } v, err := vidmod.GetVideoInfo(vid) if err != nil || v.ID.IsZero() { continue } if _, ok := commentCountMap[v.ID]; !ok { commentCountMap[v.ID] = 0 } commentCountMap[v.ID] = commentCountMap[v.ID] + 1 reviewT := v.ReviewAt.UTC().Unix() duration := time.Now().UTC().Unix() - reviewT rangeMinu := duration / 60 id := primitive.NewObjectID() comments = append(comments, &(cmtmod.Comment{ ID: id, ObjID: v.ID, Type: "video", PublisherID: v.PublisherID, UserID: uids[rand.Intn(len(uids)-1)], AuthorMark: true, IsAuthor: false, Content: content, Level: 1, IPAddr: fmt.Sprintf("%d.%d.%d.%d", rand.Intn(255), rand.Intn(255), rand.Intn(255), rand.Intn(255)), Status: 1, City: citys[rand.Intn(len(citys)-1)], IsDelete: false, IsRobot: true, CreatedAt: now.Add(-time.Minute * time.Duration(rand.Intn(int(rangeMinu)+1))), })) for c := int64(0); c < likeCount; c++ { like := likemod.Like{ Type: "comment", ObjID: id, UserID: uids[rand.Intn(len(uids)-1)], LikedUserID: v.PublisherID, CreatedAt: time.Now(), } like.Uniq = likemod.Unique(like.UserID, like.Type, v.ID) likes = append(likes, &like) } } } contentCount, _ := cmtmod.InsertManyBulket(comments) likeCount, _ := likemod.InsertManyBulk(likes) _, _ = vidmod.UpdateManyForContentCount(commentCountMap) common.ServeJSON(ctx, stderr.Success, gin.H{ "contentCount": contentCount, "likeCount": likeCount, }) } // ImportComment // 导入评论内容 doc // @Summary 导入评论内容 // @Description 导入评论内容 // @Tags Web-Comment // @Accept mpfd,json // @Produce json,html // @Param upload formData file true "需要导入的文件 只支持 .xls .xlsx文件" // @Success 200 {string} json "{"msg": "操作成功", "data":[]}" // @Failure 400 {string} json "{"msg": "操作失败"}" // @Router /api/web/admin/comment/importComment [post] func ImportComment(ctx *gin.Context) { //now := time.Now() pwd, err := os.Getwd() if err != nil { common.ServeJSON(ctx, stderr.ErrServerUnavailable, err) return } file, fHeader, err := ctx.Request.FormFile("upload") if err != nil { common.ServeJSON(ctx, stderr.ErrServerUnavailable, err) return } ext := filepath.Ext(fHeader.Filename) if !strings.ContainsAny(ext, "xls") { common.ServeJSON(ctx, stderr.ErrMimeType, nil) return } fPath := pwd + "/" + fHeader.Filename //defer os.Remove(fPath) // header调用Filename方法,就可以得到文件名 out, err := os.Create(fPath) if err != nil { return } //defer out.Close() // 将file的内容拷贝到out _, err = io.Copy(out, file) if err != nil { return } var citys = webg.Static.Cities //var uids = webg.Static.SysUser xlFile, err := xlsx.OpenFile(fPath) if err != nil { return } rand.Seed(time.Now().Unix()) comments := make([]*cmtmod.Comment, 0) //likes := make([]*likemod.Like, 0) commentCountMap := make(map[primitive.ObjectID]int) // 遍历sheet页读取 for _, sheet := range xlFile.Sheets { fmt.Println("sheet name: ", sheet.Name) //遍历行读取 for _, row := range sheet.Rows { // 遍历每行的列读取 var content string var vid string var contentDateStr string var uid uint64 for k, cell := range row.Cells { str := cell.String() if str == "" { break } if k == 0 { // 用户ID cuid, _ := strconv.ParseInt(cell.String(), 10, 64) uid = uint64(cuid) } if k == 1 { // 评论内容 content = strings.TrimSpace(cell.String()) } if k == 2 { // 评论对象 vid = strings.TrimSpace(cell.String()) } if k == 3 { // 评论时间 contentDateStr = strings.TrimSpace(cell.String()) } } v, err := vidmod.GetVideoInfo(vid) if err != nil || v.ID.IsZero() { continue } if _, ok := commentCountMap[v.ID]; !ok { commentCountMap[v.ID] = 0 } commentCountMap[v.ID] = commentCountMap[v.ID] + 1 //reviewT := v.ReviewAt.UTC().Unix() //duration := time.Now().UTC().Unix() - reviewT //rangeMinu := duration / 60 t, _ := time.Parse("2006-01-02 15:04:05", contentDateStr) t = t.Add(-time.Hour * 8) id := primitive.NewObjectID() comments = append(comments, &(cmtmod.Comment{ ID: id, ObjID: v.ID, Type: "video", PublisherID: v.PublisherID, UserID: uid, AuthorMark: true, IsAuthor: false, Content: content, Level: 1, IPAddr: fmt.Sprintf("%d.%d.%d.%d", rand.Intn(255), rand.Intn(255), rand.Intn(255), rand.Intn(255)), Status: 1, City: citys[rand.Intn(len(citys)-1)], IsDelete: false, IsRobot: true, CreatedAt: t, })) //for c := int64(0); c < likeCount; c++ { // like := likemod.Like{ // Type: "comment", // ObjID: id, // UserID: uids[rand.Intn(len(uids)-1)], // LikedUserID: v.PublisherID, // CreatedAt: time.Now(), // } // like.Uniq = likemod.Unique(like.UserID, like.Type, v.ID) // likes = append(likes, &like) //} } } var contentCount int64 if len(comments) > 0 { contentCount, _ = cmtmod.InsertManyBulket(comments) } //likeCount, _ := likemod.InsertManyBulk(likes) _, _ = vidmod.UpdateManyForContentCount(commentCountMap) common.ServeJSON(ctx, stderr.Success, gin.H{ "contentCount": contentCount, //"likeCount": likeCount, }) } // Send doc // @Summary 评论模块 - 发表评论 // @Description 用户评论 // @Tags Web-Comment // @Accept mpfd,json // @Produce json,html // @Param objID formData string true "评论对象的ID" // @Param cid formData string false "此评论是对某条评论的评论或回复,如果为空,则为对该视频的评论" // @Param rid formData string false "被回复的评论id" // @Param level formData integer false "评论层级 1:一级评论 2:二级评论" // @Param toUserID formData integer false "对某用户回复评论 用户ID" // @Param content formData string true "评论内容" // @Success 200 {string} json "{"msg": "操作成功"}" // @Failure 400 {string} json "{"msg": "操作失败"}" // @Router /api/web/admin/comment/send [post] func Send(ctx *gin.Context) { manager, err := common.GetAdminAct(ctx) if err != nil { common.ServeJSON(ctx, stderr.AdminIDErr, err.Error()) return } param := cmtmod.PublishReqInfo{} err = ctx.ShouldBind(¶m) if err != nil { common.ServeJSON(ctx, stderr.ErrParamError, err) return } code, err := commentser.PublishComment(param) log, _ := json.Marshal(param) _ = operatorlgmod.RecordOperation(manager, constant.VideoManageComment, constant.Add, string(log), ctx.Request.URL.RequestURI()) common.ServeJSON(ctx, code, err) }