|
@@ -2,8 +2,14 @@
|
|
|
package weixin
|
|
|
|
|
|
import (
|
|
|
+ "bytes"
|
|
|
"encoding/json"
|
|
|
"fmt"
|
|
|
+ "github.com/disintegration/imaging"
|
|
|
+ "image"
|
|
|
+ "image/color"
|
|
|
+ "io"
|
|
|
+ "io/ioutil"
|
|
|
"log"
|
|
|
"math/rand"
|
|
|
util "mfw/util"
|
|
@@ -21,6 +27,11 @@ const (
|
|
|
status_rest = 0 //闲时,没有任务
|
|
|
status_working = 1 //进入工作状态
|
|
|
status_waitReply = 2 //收到验证码,等待回复
|
|
|
+ //
|
|
|
+ white = uint8(0xff)
|
|
|
+ bgImgName = "background.jpg"
|
|
|
+ newsImagWidth = 640
|
|
|
+ newsImagHeight = 320
|
|
|
)
|
|
|
|
|
|
var workLock = new(sync.Mutex)
|
|
@@ -33,7 +44,11 @@ var client *util.Client
|
|
|
type DistinguishWork struct {
|
|
|
}
|
|
|
|
|
|
-func initDgWork() {
|
|
|
+func init() {
|
|
|
+
|
|
|
+}
|
|
|
+
|
|
|
+func InitDgWork() {
|
|
|
client, _ = util.StartClient(processevent, wf.SysConfig.Msgserver, []int{util.SERVICE_DISTINGUISH}, 20)
|
|
|
client.ResetMyName("识别验证码")
|
|
|
}
|
|
@@ -41,24 +56,29 @@ func processevent(p *util.Packet) {
|
|
|
event := int(p.Event)
|
|
|
switch event {
|
|
|
case util.SERVICE_DISTINGUISH:
|
|
|
- log.Println("------从消息总线接收到了一个消息-----")
|
|
|
+ defer util.Catch()
|
|
|
//写数据
|
|
|
if ret := make(map[string]interface{}); json.Unmarshal(p.GetBusinessData(), &ret) == nil {
|
|
|
+ log.Println("验证码--接收到消息的数据msgId:", p.Msgid)
|
|
|
flag, _ := ret["flag"].(bool)
|
|
|
if flag {
|
|
|
+ img, _ := ret["img"]
|
|
|
+ if img == nil {
|
|
|
+ return
|
|
|
+ }
|
|
|
imgTmp, err := json.Marshal(ret["img"])
|
|
|
if err != nil {
|
|
|
return
|
|
|
}
|
|
|
- var img []byte
|
|
|
- err = json.Unmarshal(imgTmp, &img)
|
|
|
+ var imgbyte []byte
|
|
|
+ err = json.Unmarshal(imgTmp, &imgbyte)
|
|
|
if err != nil {
|
|
|
return
|
|
|
}
|
|
|
obj := map[string]interface{}{
|
|
|
"from": p.From,
|
|
|
"msgId": p.Msgid,
|
|
|
- "img": img,
|
|
|
+ "img": imgbyte,
|
|
|
}
|
|
|
if len(workers) == 0 {
|
|
|
waitWorks = append(waitWorks, obj)
|
|
@@ -66,6 +86,7 @@ func processevent(p *util.Packet) {
|
|
|
toWork(obj)
|
|
|
}
|
|
|
} else {
|
|
|
+ log.Println("验证码--超时处理msgId:", p.Msgid)
|
|
|
overtime(p.Msgid)
|
|
|
}
|
|
|
}
|
|
@@ -74,20 +95,26 @@ func processevent(p *util.Packet) {
|
|
|
|
|
|
//开始工作,记录工作人的相关数
|
|
|
func (a *DistinguishWork) Start(openId string) {
|
|
|
- if client == nil {
|
|
|
- initDgWork()
|
|
|
- }
|
|
|
+ defer util.Catch()
|
|
|
for _, v := range workers {
|
|
|
if v["openId"] == openId {
|
|
|
+ log.Println("验证码--", openId, "已经在工作中,重复进入")
|
|
|
return
|
|
|
}
|
|
|
}
|
|
|
+ log.Println("验证码--", openId, "进入工作")
|
|
|
workers = append(workers, map[string]interface{}{"openId": openId, "status": status_rest})
|
|
|
toWork(nil)
|
|
|
}
|
|
|
|
|
|
//结束工作,删除工作人
|
|
|
func (a *DistinguishWork) End(openId string) {
|
|
|
+ defer util.Catch()
|
|
|
+ log.Println("验证码--", openId, "退出本次工作")
|
|
|
+ end(openId)
|
|
|
+}
|
|
|
+
|
|
|
+func end(openId string) {
|
|
|
deleteWorker(openId)
|
|
|
for k, v := range workers {
|
|
|
if v["openId"] == openId {
|
|
@@ -99,6 +126,7 @@ func (a *DistinguishWork) End(openId string) {
|
|
|
|
|
|
//判断该人是否是工作模式
|
|
|
func (a *DistinguishWork) IsWorking(openId string) bool {
|
|
|
+ defer util.Catch()
|
|
|
for _, v := range workers {
|
|
|
if v["openId"] == openId {
|
|
|
return true
|
|
@@ -109,6 +137,7 @@ func (a *DistinguishWork) IsWorking(openId string) bool {
|
|
|
|
|
|
//判断该人是否在等待回复
|
|
|
func (a *DistinguishWork) IsWaitReply(openId string) bool {
|
|
|
+ defer util.Catch()
|
|
|
for _, v := range workers {
|
|
|
if v["openId"] == openId {
|
|
|
return v["status"] == status_waitReply
|
|
@@ -129,17 +158,22 @@ func overtime(msgId string) {
|
|
|
|
|
|
//回复验证码
|
|
|
func (a *DistinguishWork) Reply(openId, content string) {
|
|
|
+ defer util.Catch()
|
|
|
obj := workering[openId]
|
|
|
if obj == nil || len(obj) < 2 {
|
|
|
+ log.Println("验证码--本次回复msgId丢失")
|
|
|
return
|
|
|
}
|
|
|
+ log.Println("验证码--", openId, "回复内容:", content)
|
|
|
tmp := make(map[string]interface{})
|
|
|
tmp["content"] = content
|
|
|
tmp["msgId"] = obj[0]
|
|
|
client.WriteObj(obj[1], obj[0], util.EVENT_RECIVE_CALLBACK, util.SENDTO_TYPE_P2P, tmp)
|
|
|
deleteWorker(openId)
|
|
|
updateWorker(openId, status_rest)
|
|
|
- toWork(nil)
|
|
|
+ time.AfterFunc(2*time.Second, func() {
|
|
|
+ toWork(nil)
|
|
|
+ })
|
|
|
}
|
|
|
|
|
|
//删除工作的人
|
|
@@ -149,59 +183,106 @@ func deleteWorker(openId string) {
|
|
|
|
|
|
//进行一个任务
|
|
|
func toWork(o map[string]interface{}) {
|
|
|
- openId, obj, err := worked(o)
|
|
|
- if err == nil {
|
|
|
+ openId, obj, status := worked(o)
|
|
|
+ if status == 0 { //成功 || 该任务无效
|
|
|
+ return
|
|
|
+ }
|
|
|
+ if obj == nil || status == -1 {
|
|
|
+ deleteWorker(openId)
|
|
|
+ updateWorker(openId, status_rest)
|
|
|
+ return
|
|
|
+ }
|
|
|
+ obj["status"] = status
|
|
|
+ errorCount := qfwutil.IntAll(obj["errorCount"])
|
|
|
+ if status == -2 {
|
|
|
+ errorCount++
|
|
|
+ if errorCount >= qfwutil.IntAll(wf.SysConfig.DistinguishWork["errorCount"]) { //没有超过失败次数
|
|
|
+ deleteWorker(openId)
|
|
|
+ updateWorker(openId, status_rest)
|
|
|
+ return
|
|
|
+ }
|
|
|
+ obj["errorCount"] = errorCount
|
|
|
+ }
|
|
|
+ //把该任务放入等待队列中第一个,修改这个人的状态为空闲
|
|
|
+ var waitWorksCopy []map[string]interface{}
|
|
|
+ waitWorksCopy = append(waitWorksCopy, obj)
|
|
|
+ for _, v := range waitWorks {
|
|
|
+ waitWorksCopy = append(waitWorksCopy, v)
|
|
|
+ }
|
|
|
+ waitWorks = waitWorksCopy
|
|
|
+ //发送模板消息失败
|
|
|
+ if status == -4 {
|
|
|
+ end(openId)
|
|
|
+ toWork(obj)
|
|
|
return
|
|
|
}
|
|
|
- //如果任务在执行过程中出现异常,把该任务放入等待队列中,修改这个人的状态为空闲
|
|
|
- obj["status"] = "-1"
|
|
|
- waitWorks = append(waitWorks, obj)
|
|
|
deleteWorker(openId)
|
|
|
updateWorker(openId, status_rest)
|
|
|
}
|
|
|
|
|
|
-func worked(o map[string]interface{}) (string, map[string]interface{}, error) {
|
|
|
+func worked(o map[string]interface{}) (string, map[string]interface{}, int) {
|
|
|
openId, obj := getWorker(o)
|
|
|
- if openId == "" { //没有闲人
|
|
|
- return openId, obj, nil
|
|
|
- }
|
|
|
- from := obj["from"].(string)
|
|
|
- msgId := obj["msgId"].(string)
|
|
|
- img := obj["img"].([]byte)
|
|
|
- //生成验证码图片
|
|
|
- name, err := createImg(msgId, img)
|
|
|
+ if openId == "" || obj == nil { //没有闲人
|
|
|
+ return openId, obj, 0
|
|
|
+ }
|
|
|
+ from, ok := obj["from"].(string)
|
|
|
+ msgId, ok := obj["msgId"].(string)
|
|
|
+ img, ok := obj["img"].([]byte)
|
|
|
+ if !ok {
|
|
|
+ log.Println("验证码--获取到的数据不完整:", obj)
|
|
|
+ return openId, obj, -1
|
|
|
+ }
|
|
|
+ var name string
|
|
|
+ var err error
|
|
|
+ if imgName := obj["imgName"]; imgName != nil {
|
|
|
+ name, _ = imgName.(string)
|
|
|
+ } else {
|
|
|
+ //生成验证码图片
|
|
|
+ name, err = createImg(msgId, img)
|
|
|
+ obj["imgName"] = name
|
|
|
+ }
|
|
|
if name == "" || err != nil {
|
|
|
- log.Println("生成验证码图片出错:", err)
|
|
|
- return openId, obj, err
|
|
|
+ return openId, obj, -2
|
|
|
}
|
|
|
workering[openId] = []string{msgId, from}
|
|
|
//发送验证码图片
|
|
|
- var e error
|
|
|
+ var itm qrpc.News
|
|
|
+ itm.ToUser = openId
|
|
|
+
|
|
|
+ var als qrpc.Article
|
|
|
+ als.Title = wf.SysConfig.DistinguishWork["title"].(string)
|
|
|
+ als.Description = wf.SysConfig.DistinguishWork["description"].(string)
|
|
|
+ als.Url = wf.SysConfig.Qmxcdn + "/upload/spider/" + name
|
|
|
+ als.PicUrl = wf.SysConfig.Qmxcdn + "/upload/spider/" + name
|
|
|
+
|
|
|
+ itm.Articles = append(itm.Articles, als)
|
|
|
+
|
|
|
+ var status = 0
|
|
|
qfwutil.Try(func() {
|
|
|
client, err := rpc.DialHTTP("tcp", wf.SysConfig.Rpcserver)
|
|
|
defer client.Close()
|
|
|
if err != nil {
|
|
|
- log.Println(err.Error())
|
|
|
- e = err
|
|
|
+ log.Println("验证码--", err.Error())
|
|
|
+ status = -3
|
|
|
return
|
|
|
}
|
|
|
var repl qrpc.RpcResult
|
|
|
- err = client.Call("WeiXinRpc.SendManagerNotifyMsg", &qrpc.NotifyMsg{
|
|
|
+ err = client.Call("WeiXinRpc.SendNews", itm, &repl)
|
|
|
+ /*err = client.Call("WeiXinRpc.SendManagerNotifyMsg", &qrpc.NotifyMsg{
|
|
|
Openid: openId,
|
|
|
Title: wf.SysConfig.DistinguishWork["title"],
|
|
|
Detail: wf.SysConfig.DistinguishWork["detail"],
|
|
|
Result: wf.SysConfig.DistinguishWork["result"],
|
|
|
Url: wf.SysConfig.Qmxcdn + "/upload/spider/" + name,
|
|
|
- }, &repl)
|
|
|
+ }, &repl)*/
|
|
|
if err != nil {
|
|
|
- log.Println(err.Error())
|
|
|
- e = err
|
|
|
- return
|
|
|
+ log.Println("验证码--", err.Error())
|
|
|
+ status = -4
|
|
|
} else {
|
|
|
updateWorker(openId, status_waitReply)
|
|
|
}
|
|
|
}, func(e interface{}) {})
|
|
|
- return openId, obj, e
|
|
|
+ return openId, obj, status
|
|
|
}
|
|
|
|
|
|
//修改这个人的状态为等待回复
|
|
@@ -233,14 +314,22 @@ func getWorker(obj map[string]interface{}) (openId string, object map[string]int
|
|
|
}
|
|
|
tmp_length := len(tmp)
|
|
|
if tmp_length == 0 { //都在忙,没有闲人
|
|
|
- waitWorks = append(waitWorks, obj)
|
|
|
+ if obj != nil {
|
|
|
+ waitWorks = append(waitWorks, obj)
|
|
|
+ log.Println("验证码--都在忙,没有闲人")
|
|
|
+ }
|
|
|
return
|
|
|
}
|
|
|
tmp_index := rand.New(rand.NewSource(time.Now().UnixNano())).Intn(tmp_length)
|
|
|
workers_index := tmp[tmp_index]
|
|
|
workers[workers_index]["status"] = status_working
|
|
|
- openId = workers[workers_index]["openId"].(string)
|
|
|
+ openId, _ = workers[workers_index]["openId"].(string)
|
|
|
+ log.Println("验证码--获取到可以工作的人", openId)
|
|
|
if len(waitWorks) > 0 {
|
|
|
+ //把该任务加入等待队列
|
|
|
+ if obj != nil {
|
|
|
+ waitWorks = append(waitWorks, obj)
|
|
|
+ }
|
|
|
object = waitWorks[0]
|
|
|
//删除第一个
|
|
|
waitWorks = waitWorks[1:]
|
|
@@ -253,26 +342,100 @@ func getWorker(obj map[string]interface{}) (openId string, object map[string]int
|
|
|
//获取一个要识别的任务
|
|
|
func createImg(msgId string, img []byte) (string, error) {
|
|
|
name := msgId + "-" + fmt.Sprint(time.Now().Unix()) + ".jpg"
|
|
|
- path := wf.SysConfig.Imgpath + "/upload/spider"
|
|
|
+ path := wf.SysConfig.Imgpath + "/upload/spider/"
|
|
|
fs, err := os.Open(path)
|
|
|
if err != nil && os.MkdirAll(path, 0700) != nil {
|
|
|
- log.Println("创建文件夹出错:", err)
|
|
|
+ log.Println("验证码--创建文件夹出错:", err)
|
|
|
return "", err
|
|
|
}
|
|
|
defer fs.Close()
|
|
|
- file, err := os.Create(path + "/" + name)
|
|
|
+ go delOldImg(path)
|
|
|
+ err = processImg(path, name, bytes.NewBuffer(img), img)
|
|
|
if err != nil {
|
|
|
- log.Println("创建验证码图片出错:", err)
|
|
|
return "", err
|
|
|
}
|
|
|
- _, err = file.Write(img)
|
|
|
+ return name, nil
|
|
|
+}
|
|
|
+
|
|
|
+//删除过期的图片
|
|
|
+func delOldImg(path string) {
|
|
|
+ dir, err := ioutil.ReadDir(path)
|
|
|
if err != nil {
|
|
|
- log.Println("写入验证码图片出错:", err)
|
|
|
- return "", err
|
|
|
+ log.Println("验证码--读取文件夹出错")
|
|
|
+ return
|
|
|
}
|
|
|
- defer file.Close()
|
|
|
- return name, nil
|
|
|
+ now := time.Now()
|
|
|
+ todayStart := time.Date(now.Year(), now.Month(), now.Day(), 0, 0, 0, 0, now.Location())
|
|
|
+ for _, file := range dir {
|
|
|
+ if file.IsDir() || file.Name() == bgImgName {
|
|
|
+ continue
|
|
|
+ }
|
|
|
+ //删除今天之前的图片
|
|
|
+ if file.ModTime().Before(todayStart) {
|
|
|
+ os.Remove(path + file.Name())
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+func processImg(path, name string, file io.Reader, img []byte) error {
|
|
|
+ b_image, err := imaging.Open(path + bgImgName)
|
|
|
+ if err != nil {
|
|
|
+ b_newImg := imaging.New(newsImagWidth, newsImagHeight, color.NRGBA{white, white, white, white})
|
|
|
+ err = imaging.Save(b_newImg, path+bgImgName)
|
|
|
+ if err != nil {
|
|
|
+ log.Println("验证码--创建背景图片出错!", err)
|
|
|
+ }
|
|
|
+ b_image, err = imaging.Open(path + bgImgName)
|
|
|
+ if err != nil {
|
|
|
+ log.Println("验证码--重新打开背景图片出错!", err)
|
|
|
+ }
|
|
|
+ }
|
|
|
+ config, _, err := image.DecodeConfig(file)
|
|
|
+ if err != nil {
|
|
|
+ log.Println("验证码--获取图片config出错!", err)
|
|
|
+ return err
|
|
|
+ }
|
|
|
+ w := config.Width
|
|
|
+ h := config.Height
|
|
|
+ if w >= newsImagWidth {
|
|
|
+ return nil
|
|
|
+ }
|
|
|
+ f, err := os.Create(path + name)
|
|
|
+ if err != nil {
|
|
|
+ log.Println("验证码--创建图片出错!", err)
|
|
|
+ return err
|
|
|
+ }
|
|
|
+ _, err = f.Write(img)
|
|
|
+ if err != nil {
|
|
|
+ log.Println("验证码--写入图片出错!", err)
|
|
|
+ return err
|
|
|
+ }
|
|
|
+ f.Close()
|
|
|
+ _file, err := imaging.Open(path + name)
|
|
|
+ if err != nil {
|
|
|
+ log.Println("验证码--打开图片出错!", err)
|
|
|
+ return err
|
|
|
+ }
|
|
|
+ if h > newsImagHeight {
|
|
|
+ err = imaging.Save(imaging.Resize(_file, 0, newsImagHeight, imaging.Lanczos), path+name)
|
|
|
+ if err != nil {
|
|
|
+ log.Println("验证码--缩放图片出错!", err)
|
|
|
+ return err
|
|
|
+ }
|
|
|
+ _file, err = imaging.Open(path + name)
|
|
|
+ if err != nil {
|
|
|
+ log.Println("验证码--缩放之后重新打开图片出错!", err)
|
|
|
+ return err
|
|
|
+ }
|
|
|
+ }
|
|
|
+ err = imaging.Save(imaging.PasteCenter(b_image, _file), path+name)
|
|
|
+ if err != nil {
|
|
|
+ log.Println("验证码--合并之后创建图片出错:", err)
|
|
|
+ return err
|
|
|
+ }
|
|
|
+ return nil
|
|
|
}
|
|
|
+
|
|
|
func Monitor(w http.ResponseWriter, r *http.Request) {
|
|
|
var h_p, h_w, h_wa string
|
|
|
for _, v := range workers {
|
|
@@ -282,8 +445,10 @@ func Monitor(w http.ResponseWriter, r *http.Request) {
|
|
|
h_w += fmt.Sprint(k) + ":" + fmt.Sprint(v) + "<br>"
|
|
|
}
|
|
|
for _, v := range waitWorks {
|
|
|
+ img := v["img"]
|
|
|
delete(v, "img")
|
|
|
h_wa += fmt.Sprint(v) + "<br>"
|
|
|
+ v["img"] = img
|
|
|
}
|
|
|
if h_p == "" {
|
|
|
h_p = "无"
|