501 lines
13 KiB
Go
501 lines
13 KiB
Go
package logic
|
||
|
||
import (
|
||
"encoding/json"
|
||
"errors"
|
||
"fmt"
|
||
planBTypePinduoduo "planA/planB/type/pinduoduo"
|
||
"planA/planD/initialization/golabl"
|
||
"planA/planD/service"
|
||
"planA/planD/tool"
|
||
planDTypeKfz "planA/planD/type/kfz"
|
||
planDTypePinduoduo "planA/planD/type/pinduoduo"
|
||
planAType "planA/type"
|
||
"planA/type/mysql"
|
||
"strconv"
|
||
"strings"
|
||
|
||
"gorm.io/gorm"
|
||
)
|
||
|
||
func Logic() error {
|
||
task, err := service.GetDelTask()
|
||
if err != nil {
|
||
if errors.Is(err, gorm.ErrRecordNotFound) {
|
||
return errors.New("任务不存在")
|
||
}
|
||
return fmt.Errorf("查询任务失败: %w", err)
|
||
}
|
||
|
||
if *task.ShopType == "1" {
|
||
if err := PddLogic(task); err != nil {
|
||
return err
|
||
}
|
||
} else if *task.ShopType == "2" {
|
||
if err := KongFiZLogic(task); err != nil {
|
||
return err
|
||
}
|
||
} else if *task.ShopType == "5" {
|
||
if err := XianYuLogic(); err != nil {
|
||
return err
|
||
}
|
||
} else {
|
||
return errors.New("任务类型错误")
|
||
}
|
||
|
||
//重新查询数据库,判断任务是否完成
|
||
task, err = service.GetDelTask()
|
||
if err != nil {
|
||
if errors.Is(err, gorm.ErrRecordNotFound) {
|
||
return errors.New("任务不存在")
|
||
}
|
||
return fmt.Errorf("查询任务失败: %w", err)
|
||
}
|
||
if *task.TaskCountOver >= *task.TaskCount {
|
||
return service.UpdateTaskStatus(3)
|
||
}
|
||
return nil
|
||
}
|
||
|
||
func PddLogic(task mysql.DelTask) error {
|
||
switch *task.TaskType {
|
||
case 1:
|
||
if err := PddRegularTask(task); err != nil {
|
||
return err
|
||
}
|
||
case 2:
|
||
if err := PddCountTask(task); err != nil {
|
||
return err
|
||
}
|
||
case 3:
|
||
if err := PddTimeTask(task); err != nil {
|
||
return err
|
||
}
|
||
default:
|
||
return errors.New("任务类型错误")
|
||
}
|
||
return nil
|
||
}
|
||
|
||
func KongFiZLogic(task mysql.DelTask) error {
|
||
switch *task.TaskType {
|
||
case 1:
|
||
if err := KfzRegularTask(task); err != nil {
|
||
return err
|
||
}
|
||
default:
|
||
return errors.New("任务类型错误")
|
||
}
|
||
return nil
|
||
}
|
||
|
||
func XianYuLogic() error {
|
||
//闲鱼没有删除
|
||
if err := service.UpdateTaskStatus(3); err != nil {
|
||
return err
|
||
}
|
||
fmt.Println("任务完成!")
|
||
return nil
|
||
}
|
||
|
||
// 通用通知函数
|
||
func notifyDeletedGoods(shopId string, goodsIds []int64) error {
|
||
if len(goodsIds) == 0 {
|
||
return nil
|
||
}
|
||
goodsIdsJSON, err := json.Marshal(goodsIds)
|
||
if err != nil {
|
||
return err
|
||
}
|
||
_, err = tool.SubmitFormData(golabl.Config.FileUrl.DelTaskUrl, map[string]string{
|
||
"shopId": shopId,
|
||
"data": string(goodsIdsJSON),
|
||
})
|
||
return err
|
||
}
|
||
|
||
// 处理删除成功后的逻辑
|
||
func handleDeleteSuccess(task mysql.DelTask, goodsId int64, goodsName, outerId, token string, deleteGoodsId *[]int64) error {
|
||
// 写入redis
|
||
if err := service.InsertDelTaskDetail(task.ID, *task.TaskID, token, goodsName, outerId, goodsId); err != nil {
|
||
return err
|
||
}
|
||
|
||
// 收集商品ID
|
||
*deleteGoodsId = append(*deleteGoodsId, goodsId)
|
||
|
||
// 每达到1000条,立即通知一次
|
||
if len(*deleteGoodsId) >= 1000 {
|
||
if err := notifyDeletedGoods(*task.ShopID, *deleteGoodsId); err != nil {
|
||
return err
|
||
}
|
||
*deleteGoodsId = []int64{} // 清空
|
||
}
|
||
|
||
fmt.Printf("商品id: %v 删除成功\n", goodsId)
|
||
return nil
|
||
}
|
||
|
||
// 处理删除上限错误
|
||
func handleLimitError(task mysql.DelTask, deleteGoodsId []int64) error {
|
||
if err := notifyDeletedGoods(*task.ShopID, deleteGoodsId); err != nil {
|
||
return err
|
||
}
|
||
if err := service.UpdateTaskStatus(2); err != nil {
|
||
return err
|
||
}
|
||
return fmt.Errorf("----您当日所删除的商品已达上限或无法获取需要删除的数据----\n")
|
||
}
|
||
|
||
// 更新任务进度和完成状态
|
||
func updateTaskProgress() (bool, error) {
|
||
if err := service.UpdateTaskCountOver(); err != nil {
|
||
return false, err
|
||
}
|
||
|
||
over, err := service.GetTaskCountOver()
|
||
if err != nil {
|
||
return false, err
|
||
}
|
||
|
||
if over == 0 {
|
||
if err := service.UpdateTaskStatus(3); err != nil {
|
||
return false, err
|
||
}
|
||
fmt.Println("任务完成!")
|
||
return true, nil
|
||
}
|
||
return false, nil
|
||
}
|
||
|
||
///////////////////////////////////////////////////////////拼多多/////////////////////////////////////////////////////////////////////////////////
|
||
|
||
func PddRegularTask(task mysql.DelTask) error {
|
||
delTask, err := service.GetMax5000WaitDelTask()
|
||
if err != nil {
|
||
return err
|
||
}
|
||
|
||
var deleteGoodsId []int64
|
||
|
||
if len(delTask) == 0 {
|
||
if err := handleLimitError(task, deleteGoodsId); err != nil {
|
||
return err
|
||
}
|
||
}
|
||
|
||
for _, v := range delTask {
|
||
status := 1
|
||
errMsg := "执行成功"
|
||
deleteErr := PddDeleteGoodsTask(*v.GoodsID, *v.Token)
|
||
|
||
if deleteErr != nil && strings.Contains(deleteErr.Error(), "您当日所删除的商品已达上限") {
|
||
if err := handleLimitError(task, deleteGoodsId); err != nil {
|
||
return err
|
||
}
|
||
status = 0
|
||
errMsg = deleteErr.Error()
|
||
fmt.Printf("商品id: %v Err %v\n", v.GoodsID, deleteErr.Error())
|
||
} else if deleteErr != nil {
|
||
status = 2
|
||
errMsg = deleteErr.Error()
|
||
fmt.Printf("商品id: %v Err %v\n", v.GoodsID, deleteErr.Error())
|
||
} else {
|
||
if err := handleDeleteSuccess(task, *v.GoodsID, "", "", *v.Token, &deleteGoodsId); err != nil {
|
||
return err
|
||
}
|
||
}
|
||
|
||
if err := service.UpdateDelTaskDetailStatus(v.ID, status, errMsg); err != nil {
|
||
return err
|
||
}
|
||
|
||
if _, err := updateTaskProgress(); err != nil {
|
||
return err
|
||
}
|
||
}
|
||
|
||
return notifyDeletedGoods(*task.ShopID, deleteGoodsId)
|
||
}
|
||
|
||
// 获取商品列表的通用函数
|
||
func getGoodsList(token string, maxTotal int) ([]planBTypePinduoduo.GoodsItem, error) {
|
||
var goodsList []planBTypePinduoduo.GoodsItem
|
||
page := 1
|
||
pageSize := 100
|
||
|
||
for len(goodsList) < maxTotal {
|
||
params := map[string]string{
|
||
"accessToken": token,
|
||
"page": strconv.Itoa(page),
|
||
"pageSize": strconv.Itoa(pageSize),
|
||
"isOnsale": "0",
|
||
}
|
||
|
||
resp, _, err := tool.GetPddGoodsList(params)
|
||
if err != nil {
|
||
return nil, err
|
||
}
|
||
|
||
if len(resp.GoodsList) == 0 {
|
||
break
|
||
}
|
||
|
||
goodsList = append(goodsList, resp.GoodsList...)
|
||
|
||
if len(goodsList) >= resp.TotalCount || len(goodsList) >= maxTotal {
|
||
break
|
||
}
|
||
page++
|
||
}
|
||
|
||
if len(goodsList) > maxTotal {
|
||
goodsList = goodsList[:maxTotal]
|
||
}
|
||
return goodsList, nil
|
||
}
|
||
|
||
// 通用删除逻辑
|
||
func processDeletions(task mysql.DelTask, goodsList []planBTypePinduoduo.GoodsItem, token string) error {
|
||
var deleteGoodsId []int64
|
||
|
||
// 只查询一次任务状态
|
||
currentTask, err := service.GetDelTask()
|
||
if err != nil {
|
||
if errors.Is(err, gorm.ErrRecordNotFound) {
|
||
return errors.New("任务不存在")
|
||
}
|
||
return fmt.Errorf("查询任务失败: %w", err)
|
||
}
|
||
|
||
//修改状态为执行中
|
||
updateTaskStatusErr := service.UpdateTaskStatus(1)
|
||
if updateTaskStatusErr != nil {
|
||
return fmt.Errorf("更新任务状态失败: %w", updateTaskStatusErr)
|
||
}
|
||
|
||
for _, v := range goodsList {
|
||
// 检查任务是否已完成
|
||
if *currentTask.TaskCountOver > *currentTask.TaskCount {
|
||
break
|
||
}
|
||
deleteErr := PddDeleteGoodsTask(v.GoodsId, token)
|
||
|
||
if deleteErr != nil && strings.Contains(deleteErr.Error(), "您当日所删除的商品已达上限") {
|
||
return handleLimitError(task, deleteGoodsId)
|
||
} else if deleteErr != nil {
|
||
fmt.Printf("商品id: %v Err %v\n", v.GoodsId, deleteErr.Error())
|
||
} else {
|
||
outerId := ""
|
||
if len(v.SkuList) > 0 {
|
||
outerId = v.SkuList[0].OuterId
|
||
}
|
||
if err := handleDeleteSuccess(task, v.GoodsId, v.GoodsName, outerId, token, &deleteGoodsId); err != nil {
|
||
return err
|
||
}
|
||
}
|
||
|
||
// 每删除一个,任务的完成数+1
|
||
if err := service.UpdateTaskCountOver(); err != nil {
|
||
return err
|
||
}
|
||
|
||
// 更新当前任务计数(避免每次都查询数据库)
|
||
*currentTask.TaskCount++
|
||
}
|
||
|
||
// 循环结束后通知剩余数据
|
||
if len(deleteGoodsId) > 0 {
|
||
return notifyDeletedGoods(*task.ShopID, deleteGoodsId)
|
||
}
|
||
return nil
|
||
}
|
||
|
||
func PddCountTask(task mysql.DelTask) error {
|
||
var header planAType.TaskHeader
|
||
if err := json.Unmarshal([]byte(*task.Header), &header); err != nil {
|
||
return err
|
||
}
|
||
|
||
var dleNum int
|
||
dleNum = *task.TaskCount - *task.TaskCountOver
|
||
if dleNum > 5000 {
|
||
dleNum = 5000
|
||
}
|
||
fmt.Println("任务ID ", golabl.TaskId, " 删除数量 :", dleNum)
|
||
|
||
goodsList, err := getGoodsList(header.ShopMsg.Token, dleNum)
|
||
if err != nil {
|
||
return err
|
||
}
|
||
fmt.Println("获取删除数量的长度 ", len(goodsList))
|
||
|
||
if len(goodsList) == 0 {
|
||
if err := handleLimitError(task, []int64{}); err != nil {
|
||
return err
|
||
}
|
||
}
|
||
|
||
return processDeletions(task, goodsList, header.ShopMsg.Token)
|
||
}
|
||
|
||
func PddTimeTask(task mysql.DelTask) error {
|
||
var header planAType.TaskHeader
|
||
if err := json.Unmarshal([]byte(*task.Header), &header); err != nil {
|
||
return err
|
||
}
|
||
|
||
goodsList, err := getGoodsList(header.ShopMsg.Token, 5000)
|
||
if err != nil {
|
||
return err
|
||
}
|
||
|
||
updateTaskCountAndTaskCountOverErr := service.UpdateTaskCountAndTaskCountOver()
|
||
if updateTaskCountAndTaskCountOverErr != nil {
|
||
return updateTaskCountAndTaskCountOverErr
|
||
}
|
||
|
||
// 过滤掉创建时间大于停止时间的商品
|
||
filteredList := make([]planBTypePinduoduo.GoodsItem, 0, len(goodsList))
|
||
for _, v := range goodsList {
|
||
if v.CreatedAt <= task.StopAt.Unix() {
|
||
filteredList = append(filteredList, v)
|
||
updateTaskCountErr := service.UpdateTaskCount()
|
||
if updateTaskCountErr != nil {
|
||
return updateTaskCountErr
|
||
}
|
||
}
|
||
}
|
||
fmt.Printf("获取删除数量的长度 %v\n", len(filteredList))
|
||
|
||
if len(filteredList) == 0 {
|
||
if err := handleLimitError(task, []int64{}); err != nil {
|
||
return err
|
||
}
|
||
}
|
||
|
||
if err := processDeletions(task, filteredList, header.ShopMsg.Token); err != nil {
|
||
return err
|
||
}
|
||
|
||
// 如果有商品被过滤掉,标记任务完成
|
||
if len(filteredList) < len(goodsList) {
|
||
return service.UpdateTaskStatus(3)
|
||
}
|
||
return nil
|
||
}
|
||
|
||
func PddDeleteGoodsTask(goodsId int64, token string) error {
|
||
if goodsId == 0 {
|
||
return fmt.Errorf("商品Id不能为空")
|
||
}
|
||
|
||
reqDataInfo := planDTypePinduoduo.DeleteGoodsCommit{GoodsIds: []int64{goodsId}}
|
||
delGoodsRet, _, err := PddDelGoods(reqDataInfo, token)
|
||
if err != nil {
|
||
return err
|
||
}
|
||
if !delGoodsRet.OpenAPIResponse {
|
||
return errors.New("删除商品失败")
|
||
}
|
||
return nil
|
||
}
|
||
|
||
func PddDelGoods(reqDataInfo planDTypePinduoduo.DeleteGoodsCommit, token string) (planDTypePinduoduo.DeleteGoodsCommitResponse, string, error) {
|
||
var delGoods planDTypePinduoduo.DeleteGoodsCommitResponse
|
||
goodsInfoStr, err := json.Marshal(reqDataInfo)
|
||
if err != nil {
|
||
return delGoods, "", err
|
||
}
|
||
|
||
delGoodsStr, err := golabl.PddDll.PddDeleteGoodsCommit(
|
||
golabl.Config.PddConfig.ClientId,
|
||
golabl.Config.PddConfig.ClientSecret,
|
||
token,
|
||
string(goodsInfoStr),
|
||
)
|
||
|
||
if strings.Contains(delGoodsStr, "请求失败") || strings.Contains(delGoodsStr, "错误码") {
|
||
return delGoods, delGoodsStr, errors.New("拼多多 DelGoods 错误:" + delGoodsStr)
|
||
}
|
||
if err != nil {
|
||
return delGoods, "", err
|
||
}
|
||
if err := json.Unmarshal([]byte(delGoodsStr), &delGoods); err != nil {
|
||
return delGoods, "", fmt.Errorf("解析拼多多 DelGoods 接口返回json失败: %v", err)
|
||
}
|
||
return delGoods, delGoodsStr, nil
|
||
}
|
||
|
||
///////////////////////////////////////////////////////////孔夫子/////////////////////////////////////////////////////////////////////////////////
|
||
|
||
func KfzRegularTask(task mysql.DelTask) error {
|
||
delTask, err := service.GetMax5000WaitDelTask()
|
||
if err != nil {
|
||
return err
|
||
}
|
||
|
||
var deleteGoodsId []int64
|
||
|
||
for _, v := range delTask {
|
||
status := 1
|
||
errMsg := "执行成功"
|
||
deleteErr := KfzDeleteGoodsTask(*v.GoodsID, *v.Token)
|
||
|
||
if deleteErr != nil {
|
||
status = 2
|
||
errMsg = deleteErr.Error()
|
||
fmt.Printf("商品id: %v Err %v\n", v.GoodsID, deleteErr.Error())
|
||
} else {
|
||
if err := handleDeleteSuccess(task, *v.GoodsID, "", "", *v.Token, &deleteGoodsId); err != nil {
|
||
return err
|
||
}
|
||
}
|
||
|
||
if err := service.UpdateDelTaskDetailStatus(v.ID, status, errMsg); err != nil {
|
||
return err
|
||
}
|
||
|
||
if _, err := updateTaskProgress(); err != nil {
|
||
return err
|
||
}
|
||
}
|
||
|
||
return notifyDeletedGoods(*task.ShopID, deleteGoodsId)
|
||
}
|
||
|
||
func KfzDeleteGoodsTask(goodsId int64, token string) error {
|
||
if goodsId == 0 {
|
||
return fmt.Errorf("商品Id不能为空")
|
||
}
|
||
|
||
reqDataInfo := planDTypeKfz.DeleteGoodsCommit{ItemId: strconv.FormatInt(goodsId, 10)}
|
||
delGoodsRet, _, err := KfzDelGoods(reqDataInfo, token)
|
||
if err != nil {
|
||
return err
|
||
}
|
||
if delGoodsRet.ErrorResponse != nil {
|
||
return errors.New("删除商品失败")
|
||
}
|
||
return nil
|
||
}
|
||
|
||
func KfzDelGoods(reqDataInfo planDTypeKfz.DeleteGoodsCommit, token string) (planDTypeKfz.DeleteGoodsCommitResponse, string, error) {
|
||
var delGoods planDTypeKfz.DeleteGoodsCommitResponse
|
||
goodsInfoStr, err := json.Marshal(reqDataInfo)
|
||
if err != nil {
|
||
return delGoods, "", err
|
||
}
|
||
delGoodsStr, err := golabl.KfzDll.DeleteGoods(golabl.Config.KfzConfig.AppId, golabl.Config.KfzConfig.AppSecret, token, string(goodsInfoStr))
|
||
if strings.Contains(delGoodsStr, "失败") || strings.Contains(delGoodsStr, "错误") {
|
||
return delGoods, delGoodsStr, errors.New("孔夫子 DelGoods 错误:" + delGoodsStr)
|
||
}
|
||
if err != nil {
|
||
return delGoods, "", err
|
||
}
|
||
if err := json.Unmarshal([]byte(delGoodsStr), &delGoods); err != nil {
|
||
return delGoods, "", fmt.Errorf("解析孔夫子 DelGoods 接口返回json失败: %v", err)
|
||
}
|
||
return delGoods, delGoodsStr, nil
|
||
}
|