|
@@ -0,0 +1,352 @@
|
|
|
+package usermanager
|
|
|
+
|
|
|
+import (
|
|
|
+ "net/http"
|
|
|
+ "os"
|
|
|
+ qu "qfw/util"
|
|
|
+ "qfw/util/redis"
|
|
|
+ "strings"
|
|
|
+ "sync"
|
|
|
+ "time"
|
|
|
+ . "utils"
|
|
|
+
|
|
|
+ "qfw/util/mail"
|
|
|
+
|
|
|
+ "github.com/robfig/cron"
|
|
|
+ log "github.com/sirupsen/logrus"
|
|
|
+ "github.com/tealeg/xlsx"
|
|
|
+)
|
|
|
+
|
|
|
+//给用户发送邮件
|
|
|
+var Gmails []*mail.GmailAuth
|
|
|
+
|
|
|
+func init() {
|
|
|
+ mails, _ := Sysconfig["mail"].([]interface{})
|
|
|
+ if len(mails) > 0 {
|
|
|
+ Gmails = make([]*mail.GmailAuth, len(mails))
|
|
|
+ for k, v1 := range mails {
|
|
|
+ v, _ := v1.(map[string]interface{})
|
|
|
+ Gmails[k] = &mail.GmailAuth{
|
|
|
+ SmtpHost: qu.ObjToString(v["addr"]),
|
|
|
+ SmtpPort: qu.IntAll(v["port"]),
|
|
|
+ User: qu.ObjToString(v["user"]),
|
|
|
+ Pwd: qu.ObjToString(v["pwd"]),
|
|
|
+ //PoolSize: v.MailPollSize,
|
|
|
+ //ReTry: v.MailReTry,
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ go func() {
|
|
|
+ time.Sleep(5 * time.Second)
|
|
|
+ cron1, _ := Sysconfig["cron-sendmail"].(string)
|
|
|
+ if len(cron1) > 2 {
|
|
|
+ log.Debug("enter sendMailtask...")
|
|
|
+ c := cron.New()
|
|
|
+ log.Println("发送数据定时任务")
|
|
|
+ c.AddFunc(cron1, sm)
|
|
|
+ c.Start()
|
|
|
+ defer c.Stop()
|
|
|
+ select {}
|
|
|
+ }
|
|
|
+ }()
|
|
|
+}
|
|
|
+
|
|
|
+func sm() {
|
|
|
+ sendmail("", -1, 1, "")
|
|
|
+}
|
|
|
+
|
|
|
+//调用url地址发送邮件
|
|
|
+func SendMailByAppid(w http.ResponseWriter, r *http.Request) {
|
|
|
+ defer qu.Catch()
|
|
|
+ appid := r.FormValue("appid") //用户身份
|
|
|
+ days := r.FormValue("days") //往前取几天的数据
|
|
|
+ force := r.FormValue("force") //强制获取忽略bget状态
|
|
|
+ fn := r.FormValue("fn") //文件名
|
|
|
+ if len(appid) > 0 {
|
|
|
+ day := -1
|
|
|
+ if days != "" {
|
|
|
+ day = qu.IntAll(days)
|
|
|
+ }
|
|
|
+ force1 := qu.IntAll(force)
|
|
|
+ sendmail(appid, day, force1, fn)
|
|
|
+ w.Write([]byte("ok"))
|
|
|
+ } else {
|
|
|
+ w.Write([]byte("param error"))
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+//定时发送邮件
|
|
|
+/**
|
|
|
+appid 用户身份
|
|
|
+days -1发送昨天数据 -3发送前三天数据
|
|
|
+force 1不判断bget 0判断bget为1的不发送
|
|
|
+**/
|
|
|
+func sendmail(appid string, days int, force int, fn string) {
|
|
|
+ query := map[string]interface{}{
|
|
|
+ "mails": map[string]interface{}{
|
|
|
+ "$exists": 1,
|
|
|
+ },
|
|
|
+ }
|
|
|
+ if len(appid) > 6 {
|
|
|
+ query = map[string]interface{}{
|
|
|
+ "appid": appid,
|
|
|
+ }
|
|
|
+ }
|
|
|
+ res, b := Mgo.Find("user", query, nil, nil, false, -1, -1)
|
|
|
+ if b && res != nil && *res != nil && len(*res) > 0 {
|
|
|
+ for _, v := range *res {
|
|
|
+ if !(v["bnormal"] == nil || qu.IntAll(v["bnormal"]) == 1) {
|
|
|
+ log.Println("用户为关闭状态", appid)
|
|
|
+ continue
|
|
|
+ }
|
|
|
+ appid, _ := v["appid"].(string)
|
|
|
+ //h := qu.IntAll(v["sendmailhour"])
|
|
|
+ // key := fmt.Sprintf("sendmail_%d_%s", tn.Day(), appid)
|
|
|
+ // b, _ := redis.Exists(REDISDB, key)
|
|
|
+ plan, _ := v["plan"].(map[string]interface{})
|
|
|
+ planname := ""
|
|
|
+ if len(plan) > 0 && plan["name"] != nil {
|
|
|
+ planname, _ = plan["name"].(string)
|
|
|
+ }
|
|
|
+ appfields, _ := v["fields"].(string)
|
|
|
+ mails, _ := v["mails"].(map[string]interface{})
|
|
|
+ if len(mails) > 0 && appid != "" && len(planname) > 1 {
|
|
|
+ GetDataMapLock.Lock()
|
|
|
+ appidLock := GetDataMap[appid]
|
|
|
+ if appidLock == nil {
|
|
|
+ appidLock = &sync.Mutex{}
|
|
|
+ GetDataMap[appid] = appidLock
|
|
|
+ }
|
|
|
+ GetDataMapLock.Unlock()
|
|
|
+ appidLock.Lock()
|
|
|
+ defer appidLock.Unlock()
|
|
|
+ log.Println(appid, mails)
|
|
|
+
|
|
|
+ //判断剩余服务条数
|
|
|
+ limitnum := redis.Get(REDISDB, "limitnum_"+appid) //值
|
|
|
+ if limitnum == nil { //值为空时从数据库中提取
|
|
|
+ limitnum = plan["current"]
|
|
|
+ if limitnum != nil {
|
|
|
+ redis.Put(REDISDB, "limitnum_"+appid, limitnum, 0)
|
|
|
+ }
|
|
|
+ }
|
|
|
+ num := qu.IntAll(limitnum)
|
|
|
+ if num < 1 {
|
|
|
+ log.Println("用户额度已使用完", appid)
|
|
|
+ continue
|
|
|
+ }
|
|
|
+ //最近7天,bget不等于1套餐
|
|
|
+ dataQuery := map[string]interface{}{
|
|
|
+ "appid": appid,
|
|
|
+ }
|
|
|
+ st, _ := GetDayMinMax(time.Now())
|
|
|
+ st1 := st + int64(days*86400)
|
|
|
+ dataQuery["createtime"] = map[string]interface{}{
|
|
|
+ "$gte": st1,
|
|
|
+ "$lt": st,
|
|
|
+ }
|
|
|
+ if fn == "" {
|
|
|
+ fn = qu.FormatDateByInt64(&st1, qu.Date_Short_Layout) + "_" + qu.FormatDateByInt64(&st, qu.Date_Short_Layout)
|
|
|
+ }
|
|
|
+ if force == 0 {
|
|
|
+ dataQuery["bget"] = map[string]interface{}{
|
|
|
+ "$ne": 1,
|
|
|
+ }
|
|
|
+ }
|
|
|
+ pn := planname[:1]
|
|
|
+ var fields map[string]interface{}
|
|
|
+ if pn == "A" {
|
|
|
+ fields = A
|
|
|
+ } else if pn == "B" {
|
|
|
+ fields = B
|
|
|
+ } else if pn == "C" {
|
|
|
+ fields = C
|
|
|
+ } else if pn == "D" {
|
|
|
+ fields = D
|
|
|
+ } else if pn == "E" {
|
|
|
+ fields = E
|
|
|
+ } else if pn == "F" {
|
|
|
+ fields = F
|
|
|
+ }
|
|
|
+ fields2 := map[string]interface{}{}
|
|
|
+ for k1, v1 := range fields {
|
|
|
+ fields2[k1] = v1
|
|
|
+ }
|
|
|
+ //增加自定义字段控制 2019/9/6
|
|
|
+ if appfields != "" {
|
|
|
+ FS := strings.Split(appfields, ",")
|
|
|
+ for _, vf := range FS {
|
|
|
+ if strings.HasPrefix(vf, "-") && len(vf) > 1 {
|
|
|
+ delete(fields2, vf[1:])
|
|
|
+ } else {
|
|
|
+ fields2[vf] = 1
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ fields2["item"] = 1
|
|
|
+ log.Info(fields2)
|
|
|
+ data, bdata := Mgo.Find("usermail", dataQuery, `{"_id":1}`, fields2, false, -1, -1)
|
|
|
+ firstId, lastId := "", ""
|
|
|
+ if bdata && data != nil && *data != nil && len(*data) > 0 {
|
|
|
+ infos := *data
|
|
|
+ allUserData := map[string][]map[string]interface{}{}
|
|
|
+ updateMap := [][]map[string]interface{}{}
|
|
|
+ newGetLen := 0
|
|
|
+ for index, v1 := range infos {
|
|
|
+ if qu.IntAll(v1["bget"]) == 0 {
|
|
|
+ newGetLen++
|
|
|
+ updateMap = append(updateMap, []map[string]interface{}{
|
|
|
+ map[string]interface{}{
|
|
|
+ "_id": v1["_id"],
|
|
|
+ },
|
|
|
+ map[string]interface{}{
|
|
|
+ "$set": map[string]interface{}{
|
|
|
+ "bget": 1,
|
|
|
+ },
|
|
|
+ },
|
|
|
+ })
|
|
|
+ }
|
|
|
+ if index == 0 {
|
|
|
+ firstId = qu.BsonIdToSId(v1["_id"])
|
|
|
+ }
|
|
|
+ if index == len(infos)-1 {
|
|
|
+ lastId = qu.BsonIdToSId(v1["_id"])
|
|
|
+ }
|
|
|
+ id, _ := v1["id"].(string)
|
|
|
+ v1["id"] = SE.EncodeString(id)
|
|
|
+ delete(v1, "_id")
|
|
|
+ delete(v1, "bget")
|
|
|
+ if qu.Int64All(v1["bidopentime"]) == 0 {
|
|
|
+ delete(v1, "bidopentime")
|
|
|
+ } else {
|
|
|
+ bo := v1["bidopentime"]
|
|
|
+ v1["bidopentime"] = qu.FormatDateWithObj(&bo, qu.Date_Full_Layout)
|
|
|
+ }
|
|
|
+ if qu.Int64All(v1["publishtime"]) > 0 {
|
|
|
+ bo := v1["publishtime"]
|
|
|
+ v1["publishtime"] = qu.FormatDateWithObj(&bo, qu.Date_Full_Layout)
|
|
|
+ }
|
|
|
+ item, _ := v1["item"].(string)
|
|
|
+ if item == "" {
|
|
|
+ log.Info("info err,item nil")
|
|
|
+ continue
|
|
|
+ }
|
|
|
+ userMap := allUserData[item]
|
|
|
+ if userMap == nil {
|
|
|
+ userMap = []map[string]interface{}{}
|
|
|
+ }
|
|
|
+ userMap = append(userMap, v1)
|
|
|
+ allUserData[item] = userMap
|
|
|
+ }
|
|
|
+ //处理总条数,有重复获取的信息条不计数,*******************
|
|
|
+ if newGetLen > 0 {
|
|
|
+ redis.Decrby(REDISDB, "limitnum_"+appid, newGetLen)
|
|
|
+ go Mgo.UpdateBulk("usermail", updateMap...)
|
|
|
+ }
|
|
|
+ d := map[string]interface{}{}
|
|
|
+ d["size"] = len(infos)
|
|
|
+ d["new_size"] = newGetLen
|
|
|
+ d["available_infos"] = qu.IntAll(limitnum) - newGetLen
|
|
|
+ go func() {
|
|
|
+ saveData := map[string]interface{}{
|
|
|
+ "appid": appid,
|
|
|
+ "flag": "sendmail",
|
|
|
+ "alltype": 2,
|
|
|
+ "data": d,
|
|
|
+ "date": time.Now().Unix(),
|
|
|
+ "first": firstId,
|
|
|
+ "last": lastId,
|
|
|
+ }
|
|
|
+ if Mgo.Save("userdatalog", saveData) == "" {
|
|
|
+ log.Println(saveData)
|
|
|
+ }
|
|
|
+ }()
|
|
|
+ GetBidInfoXlsx(appid, fn, mails, fields2, allUserData)
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+}
|
|
|
+
|
|
|
+func GetBidInfoXlsx(appid string, fn string, mails map[string]interface{}, fields map[string]interface{}, allUserData map[string][]map[string]interface{}) {
|
|
|
+ //信息
|
|
|
+ for key, data := range allUserData {
|
|
|
+ email, _ := mails[key].(string)
|
|
|
+ if email == "" {
|
|
|
+ log.Info("mail nil error", appid, key)
|
|
|
+ continue
|
|
|
+ }
|
|
|
+ fx := xlsx.NewFile()
|
|
|
+ sheet := xlsx.Sheet{}
|
|
|
+
|
|
|
+ style := xlsx.NewStyle()
|
|
|
+ border := *xlsx.NewBorder("thin", "thin", "thin", "thin")
|
|
|
+ style.Border = border
|
|
|
+ style.ApplyBorder = true
|
|
|
+ style.Alignment.WrapText = true
|
|
|
+
|
|
|
+ //生表头
|
|
|
+ styleHead := xlsx.NewStyle()
|
|
|
+ styleHead.Alignment.WrapText = true
|
|
|
+ styleHead.Font.Bold = true
|
|
|
+ styleHead.Border = border
|
|
|
+ styleHead.ApplyBorder = true
|
|
|
+ head := sheet.AddRow()
|
|
|
+ arr := []string{}
|
|
|
+ for _, t := range FielsArr {
|
|
|
+ if fields[t] != nil {
|
|
|
+ arr = append(arr, t)
|
|
|
+ cell := head.AddCell()
|
|
|
+ cell.SetValue(Fiels[t])
|
|
|
+ cell.SetStyle(styleHead)
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ for _, v := range data {
|
|
|
+ row := sheet.AddRow()
|
|
|
+ for _, t := range arr {
|
|
|
+ cell := row.AddCell()
|
|
|
+ if v[t] != nil {
|
|
|
+ cell.SetValue(v[t])
|
|
|
+ cell.SetStyle(style)
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ fx.AppendSheet(sheet, "剑鱼标讯")
|
|
|
+ //t := time.Now()
|
|
|
+ dir := "./xlsx/" + appid + "/" + key + "/"
|
|
|
+ if b, _ := PathExists(dir); !b {
|
|
|
+ err1 := os.MkdirAll(dir, os.ModePerm)
|
|
|
+ if err1 != nil {
|
|
|
+ log.Println("mkdir err", dir)
|
|
|
+ }
|
|
|
+ }
|
|
|
+ fname := key + "_" + fn + qu.GetRandom(4) + ".xlsx"
|
|
|
+ err := fx.Save(dir + fname)
|
|
|
+ if err != nil {
|
|
|
+ log.Info("xls error", appid, fname)
|
|
|
+ } else {
|
|
|
+ for i := 0; i < len(Gmails); i++ {
|
|
|
+ gmail := Gmails[i]
|
|
|
+ status := mail.GSendMail("剑鱼标讯", email, "", "", key+"_"+fn, "", dir+fname, fname, gmail)
|
|
|
+ if status {
|
|
|
+ log.Println("send mail success", appid, email)
|
|
|
+ break
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+func PathExists(path string) (bool, error) {
|
|
|
+ _, err := os.Stat(path)
|
|
|
+ if err == nil {
|
|
|
+ return true, nil
|
|
|
+ }
|
|
|
+ if os.IsNotExist(err) {
|
|
|
+ return false, nil
|
|
|
+ }
|
|
|
+ return false, err
|
|
|
+}
|