package activity import ( "app.yhyue.com/moapp/jybase/common" "app.yhyue.com/moapp/jybase/date" "app.yhyue.com/moapp/jybase/encrypt" "app.yhyue.com/moapp/jybase/go-logger/logger" "app.yhyue.com/moapp/jybase/redis" "app.yhyue.com/moapp/message/db" "app.yhyue.com/moapp/message/model" "app.yhyue.com/moapp/message/util" "encoding/json" "fmt" "github.com/gogf/gf/v2/frame/g" "github.com/gogf/gf/v2/os/gctx" "regexp" "strconv" "time" ) const ( //表 tableTaskInfo = "jyactivities.lottery_task_info" tableTaskUser = "jyactivities.lottery_task_user" tableActivityInfo = "jyactivities.activity_info" ) // 任务信息 type TaskInfo struct { Id int64 `json:"id"` Name string `json:"name"` ActiveId int64 `json:"active_id"` //活动id Qualification int `json:"qualification"` //获取抽奖资格次数; CycleNum int `json:"cycle_num"` //任务周期(每天/每周/每月/活动周期) 可执行任务次数:n次;-1:不限制 CycleUnit int `json:"cycle_unit"` //默认0:当天;;1:当周;2:当月;3:活动周期 ActivityStartTime string `json:"start_time"` //活动开始时间 ActivityEndTime string `json:"end_time"` //活动结束时间 ActivityName string `json:"activity_name"` //活动名称 } // 信息主题 type MsgBody struct { Phone string `json:"phone"` UserId string `json:"userId"` MgoUserId string `json:"mgoUserId"` PositionId int64 `json:"positionId"` ActiveId int64 `json:"activeId"` TaskInfoId int64 `json:"taskInfoId"` OrderCode string `json:"orderCode"` NickName string `json:"nickName"` State int `json:"state"` //购买超级订阅和大会员 0:购买;1:续费;2:升级 } // LotteryDrawTask 抽奖任务 func LotteryDrawTask(msg *model.Message) { var msgBody MsgBody if msg.E_body != nil { b, err := json.Marshal(msg.E_body) if err == nil { err = json.Unmarshal(b, &msgBody) } if err != nil { logger.Info(fmt.Sprintf("任务完成参数信息有误:%s,err:%s", msg.E_userId, err.Error())) return } } if msgBody.MgoUserId == "" { logger.Info(fmt.Sprintf("用户mgo user id 参数信息有误:%v ,userId:%s", msgBody, msg.E_userId)) return } //判断用户是否存在 data, ok := db.Mgo.FindById("user", msgBody.MgoUserId, `{"l_registedate":1,"s_phone":1,"s_m_phone":1}`) if data == nil || len(*data) == 0 || !ok { logger.Info(fmt.Sprintf("未找到用户:%s, 任务id:%d。", msg.E_userId, msgBody.TaskInfoId)) return } //任务信息 taskInfos := db.Mysql.SelectBySql(fmt.Sprintf("SELECT lti.*,ai.start_time,ai.end_time,ai.name AS activity_name FROM %s lti LEFT JOIN %s ai ON lti.active_id = ai.id WHERE lti.active_id = ? AND lti.id = ? AND ai.start_time < NOW() AND ai.end_time >= NOW() ORDER BY lti.create_date DESC", tableTaskInfo, tableActivityInfo), msgBody.ActiveId, msgBody.TaskInfoId) if taskInfos == nil || len(*taskInfos) == 0 { logger.Info(fmt.Sprintf("没有当前需要完成的任务信息:%v", msgBody)) return } //任务信息 var taskInfo TaskInfo b, err := json.Marshal((*taskInfos)[0]) if err == nil { err = json.Unmarshal(b, &taskInfo) } if err != nil { logger.Info(fmt.Sprintf("任务信息异常:%v,err:%s", msgBody, err.Error())) return } var ( now = time.Now() timeRange = util.TimeRange{} emdTime, _ = time.ParseInLocation(date.Date_Full_Layout, taskInfo.ActivityEndTime, time.Local) ) //判断任务有效期内,此次任务是否已完成 switch taskInfo.CycleUnit { case 1: //当周 timeRange = util.GetWeekRange(now) case 2: //当月 timeRange = util.GetMonthRange(now) case 3: //活动周期 startTime, _ := time.ParseInLocation(date.Date_Full_Layout, taskInfo.ActivityStartTime, time.Local) timeRange = util.TimeRange{ StartTime: startTime, EndTime: emdTime, StartUnix: startTime.Unix(), EndUnix: emdTime.Unix(), } default: //当天 timeRange = util.GetDayRange(now) } //当前周期内 是否已完成任务 if taskInfo.CycleNum > 0 { tasks := db.Mysql.SelectBySql(fmt.Sprintf(`SELECT ltu.create_date FROM %s ltu WHERE ltu.active_id = ? AND ltu.task_id = ? AND ltu.position_id = ? AND ltu.create_date < ? AND ltu.create_date > ? `, tableTaskUser), msgBody.ActiveId, taskInfo.Id, msgBody.PositionId, timeRange.EndTime.Format(date.Date_Full_Layout), timeRange.StartTime.Format(date.Date_Full_Layout)) if tasks != nil && taskInfo.CycleNum <= len(*tasks) { createDate := common.InterfaceToStr((*tasks)[0]["create_date"]) logger.Info(fmt.Sprintf("用户:%s ,此任务:%s ,在 %s 已完成", msgBody.Phone, taskInfo.Name, createDate)) return } } else if msgBody.OrderCode != "" { tasks := db.Mysql.SelectBySql(fmt.Sprintf(`SELECT ltu.create_date FROM %s ltu WHERE ltu.active_id = ? AND ltu.position_id = ? AND ltu.order_code = ?`, tableTaskUser), taskInfo.ActiveId, msgBody.PositionId, msgBody.OrderCode) //TODO 判重 担心订单有更新 if tasks != nil && len(*tasks) > 0 { createDate := common.InterfaceToStr((*tasks)[0]["create_date"]) logger.Info(fmt.Sprintf("用户:%s ,此订单:%s ,在 %s 已新增抽奖机会", msgBody.Phone, msgBody.OrderCode, createDate)) return } } //二次验证 switch taskInfo.Id { case 1: //签到赠送剑鱼币任务 case 2: //设置关键词任务 var hasKeys bool //查看当前用户是否有订阅词 res := db.Compatible.Select(msgBody.UserId, `{"o_vipjy":1,"o_member_jy":1,"o_jy":"1"}`) if res != nil && len(*res) > 0 { obj, _ := (*res)["o_jy"].(map[string]interface{}) aKey, _ := obj["a_key"].([]interface{}) if len(aKey) > 0 { hasKeys = true } if !hasKeys { obj, _ = (*res)["o_vipjy"].(map[string]interface{}) if obj == nil { obj, _ = (*res)["o_member_jy"].(map[string]interface{}) } if obj != nil { itmes, _ := obj["a_items"].([]interface{}) for _, v := range itmes { item, _ := v.(map[string]interface{}) keys, _ := item["a_key"].([]interface{}) if len(keys) > 0 { hasKeys = true break } } } } } //没有设置关键词 if !hasKeys { logger.Info(fmt.Sprintf("当前用户:%s,手机号: %s 没有设置订阅词", msgBody.UserId, msgBody.Phone)) return } case 3: //招标采购搜索任务 case 4: //购买/续费/升级超级订阅会员 cacheKey := fmt.Sprintf(model.PayCacheKey, msgBody.ActiveId, msgBody.UserId, "v", strconv.Itoa(msgBody.State)) if cacheBool := redis.Put(PowerCacheDb, cacheKey, msgBody.Phone, int(emdTime.Unix()-time.Now().Unix())); !cacheBool { logger.Info(fmt.Sprintf("当前用户:%s,手机号: %s 超级订阅订单信息 %d redis存储失败,keys:%s", msgBody.UserId, msgBody.Phone, msgBody.State, cacheKey)) } case 5: //购买/续费/升级大会员 // TODO 完成任务 赠送两次 抽奖机会 cacheKey := fmt.Sprintf(model.PayCacheKey, msgBody.ActiveId, msgBody.UserId, "m", strconv.Itoa(msgBody.State)) if cacheBool := redis.Put(PowerCacheDb, cacheKey, msgBody.Phone, int(emdTime.Unix()-time.Now().Unix())); !cacheBool { logger.Info(fmt.Sprintf("当前用户:%s,手机号: %s 大会员订单信息 %d redis存储失败,keys:%s", msgBody.UserId, msgBody.Phone, msgBody.State, cacheKey)) } case 6: //给朋友分享活动 } insertMap := map[string]interface{}{ "active_id": msgBody.ActiveId, "task_id": msgBody.TaskInfoId, "phone": msgBody.Phone, "user_id": msgBody.UserId, "position_id": msgBody.PositionId, "mgo_user_id": msgBody.MgoUserId, "order_code": msgBody.OrderCode, "state": 0, "end_date": timeRange.EndTime.Format(date.Date_Full_Layout), "update_date": time.Now().Format(date.Date_Full_Layout), "create_date": time.Now().Format(date.Date_Full_Layout), } var tf bool for i := 0; i < taskInfo.Qualification; i++ { if id := db.Mysql.Insert(tableTaskUser, insertMap); id < 0 { logger.Info(fmt.Sprintf("保存任务记录异常:%v", msgBody)) // TODO 保存任务记录异常 告警 if webhookURL := g.Cfg().MustGet(gctx.New(), "webhookURL").Strings(); len(webhookURL) > 0 { content := fmt.Sprintf(`保存任务记录异常:\n活动名称:%s \n手机号:%s \n职位id:%d \n任务id:%d \n任务名称:%s`, taskInfo.ActivityName, msgBody.Phone, msgBody.PositionId, msgBody.TaskInfoId, taskInfo.Name) util.SendMsgByWXURL(content, webhookURL) } } else { tf = true } } if tf { logger.Info(" sse 任务信息通知:", msg) var userName = msgBody.NickName if msgBody.Phone != "" { var PhoneReg = regexp.MustCompile(`^(100\d{8}|1[3-9]\d{9})$`) if PhoneReg.MatchString(msgBody.Phone) { phone := []rune(msgBody.Phone) userName = string(phone[0:3]) + "****" + string(phone[(len(phone)-4):]) } } if sendData := util.GetSseRedisCache(msgBody.UserId); len(sendData) > 0 { for _, sv := range sendData { util.SendNotification(sv, model.SseMessage{ //util.SendNotificationToAll(model.SseMessage{ Name: taskInfo.Name, User: encrypt.SE.EncodeString(msgBody.UserId), State: model.TaskTarget, Time: time.Now().Format(date.Date_Full_Layout), Remark: fmt.Sprintf("%s 完成 %s 任务。", userName, taskInfo.Name), ActiveId: encrypt.SE.EncodeString(strconv.FormatInt(msgBody.ActiveId, 10)), }) } } } } type lotteryBody struct { NickName string `json:"nick_name"` Phone string `json:"phone"` MgoUserId string `json:"mgo_user_id"` PositionId int64 `json:"position_id"` ActiveId int64 `json:"active_id"` ActiveName string `json:"active_name"` PrizeId int64 `json:"prize_id"` PrizeName string `json:"prize_name"` } // LotteryWinning 中奖信息 func LotteryWinning(msg *model.Message) { //TODO sse 通知用户 中奖信息 var lb lotteryBody if msg.E_body != nil { b, err := json.Marshal(msg.E_body) if err == nil { err = json.Unmarshal(b, &lb) } if err != nil { logger.Info(fmt.Sprintf("中奖参数信息有误:%s", msg.E_userId)) return } } var userName = lb.NickName if lb.Phone != "" { var PhoneReg = regexp.MustCompile(`^(100\d{8}|1[3-9]\d{9})$`) if PhoneReg.MatchString(lb.Phone) { phone := []rune(lb.Phone) userName = string(phone[0:3]) + "****" + string(phone[(len(phone)-4):]) } } logger.Info(" sse 中奖信息通知:", msg) util.SendNotificationToAll(model.SseMessage{ Name: lb.PrizeName, User: userName, State: model.WinningTarget, Time: time.Now().Format(date.Date_Full_Layout), Remark: fmt.Sprintf("恭喜 %s 抽中 %s ", userName, lb.PrizeName), ActiveId: encrypt.SE.EncodeString(strconv.FormatInt(lb.ActiveId, 10)), }) }