예제 #1
0
        /// <summary>
        /// 出价 -
        /// 1. 输入价格 - 移动到输入框位置,点击,清空历史数据,输入新价格
        /// 2. 点击出价按钮 - 移动到按钮位置,点击
        /// 3. 对验证码区域截图 且 上传
        /// </summary>
        public void OfferPrice(int targetPrice, bool enableCancelFirst, Func <CaptchaAnswerImage, bool> callbackFunc = null)
        {
            // 0. 出价前,先尝试取消,防止上一步的可能的遮罩
            if (enableCancelFirst)
            {
                // this.CancelOfferedPrice();
                actionManager.ClickButtonByFenceWayRToL(actionManager.AddDelta(742, 502));
            }

            // 1. 输入价格 且 出价
            // TODO: 坐标方法 - 应该抽取出来单独管理
            actionManager.InputTextAtPoint(actionManager.AddDelta(676, 417), targetPrice.ToString(), true, "第二阶段出价");
            actionManager.ClickButtonAtPoint(actionManager.AddDelta(800, 415), true, "第二阶段出价");

            // 2. 对验证码区域截屏且上传
            // 这里尝试异步
            ThreadUtils.StartNewTaskSafe(() =>
            {
                // 这里等待会阻塞进程
                KK.Sleep(390);
                CaptchaAnswerImage img = CaptureCaptchaImage();
                UploadCaptchaImage(img);

                callbackFunc?.Invoke(img);
            }
                                         );


            // return img;
        }
예제 #2
0
        private void LoopAwaitAnswer(string imageUuid)
        {
            logger.InfoFormat("Phase1 - begin LoopAwaitAnswer");

            while (isAwaitWork)
            {
                long ss = KK.CurrentMills();
                try
                {
                    var taskContext = CaptchaTaskContext.me;
                    var answer      = taskContext.GetAnswer(imageUuid);
                    if (answer?.Length > 0)
                    {
                        phase1Manager.SubmitOfferedPrice(answer);
                        break;
                    }
                }
                catch (Exception e)
                {
                    logger.Error("LoopInquiryCaptchaAnswer error:", e);
                }
                finally
                {
                    KK.Sleep(100);
                }
            }

            logger.InfoFormat("Phase1 - end LoopAwaitAnswer");
        }
예제 #3
0
        /// <summary>
        /// 如果 isAbsolute  != true,  在相对坐标(x, y)上点击一次
        /// 否则 在绝对坐标(x, y)上点击一次
        /// </summary>
        /// <param name="p12"></param>
        /// <param name="isAbsolute"></param>
        public void ClickBtnOnceAtPoint(CoordPoint p12, string memo = "", bool isAbsolute = false, int delayMills = 0, int clickCount = 1)
        {
            if (delayMills > 0)
            {
                KK.Sleep(delayMills);
            }

            long       t1 = KK.CurrentMills();
            CoordPoint po = p12;

            if (!isAbsolute)
            {
                po = Datum.AddDelta(p12.x, p12.y);
            }

            int ret = robot.MoveTo(po.x, po.y);

            robot.LeftClick();
            if (clickCount > 1)
            {
                robot.LeftClick();
            }

            logger.InfoFormat("点击按钮#{0} @ {1} with count#{2}, elapsed {3}.", memo, po.ToString(), clickCount, KK.CurrentMills() - t1);
        }
예제 #4
0
        private void WatchSocketClient()
        {
            KK.Sleep(3 * 1000);

            while (watching)
            {
                KK.Sleep(DETECT_INTERVAL_MILLS);

                if (IsCurrentInDisabledTimeRange())
                {
                    continue;
                }

                try
                {
                    if (notifyRestarting)
                    {
                        logger.InfoFormat("already tell socket client to reconnect");
                        continue;
                    }

                    bool connected = socketClient.IsConnected();
                    // 如果已未连接,则通知重新连接
                    if (!connected)
                    {
                        TellToReconnect("already disconnected");
                        continue;
                    }

                    RawMessage msg = MessageUtils.BuildPingMessage(ClientService.AssignedClientNo);
                    socketClient.Send(msg);
                    continuousDisconnectedCount = 0;
                    counter.IncrementPing();

                    long pingCnt = counter.GetPingCount();
                    long pongCnt = counter.GetPongCount();

                    DateTime dt = DateTime.Now;
                    if (dt.Minute > 57 && dt.Second % 8 == 0)
                    {
                        logger.InfoFormat("dice socket connected#{0}, ping#{1}, pong#{2}", connected, pingCnt, pongCnt);
                    }

                    // 如果ping和pong相差超过三次,则通知重新连接
                    long delta = pingCnt - pongCnt;
                    if (delta > 3)
                    {
                        TellToReconnect("already over " + delta + " no pong response from server");
                    }
                }
                catch (Exception e)
                {
                    logger.Error("WatchSocketClient error", e);
                }
                finally
                {
                }
            }
        }
예제 #5
0
        public static void TryStopThreadByWait(Thread th, int mills1, int mills2, string memo)
        {
            if (th != null)
            {
                KK.Sleep(mills1);

                ThreadUtils.TryStopThread(th);
                KK.Sleep(mills2);
                logger.InfoFormat("NOW {0}#State is {1}", memo, th.ThreadState);
            }
        }
예제 #6
0
        /// <summary>
        /// 提交已出的价格
        /// </summary>
        public void SubmitOfferedPrice()
        {
            actionManager.ClickButtonByFenceWayLToR(actionManager.AddDelta(553, 500));

            // TODO: 等待, 点击完成验证码确认按钮, 会弹出 出价有效
            // TODO: 应该检测 区域 是否有 出价有效
            KK.Sleep(600);
            actionManager.ClickButtonAtPoint(actionManager.AddDelta(661, 478), false, "第一阶段提交#确定");

            // 清除以前输入的价格
            actionManager.CleanTextAtPoint(actionManager.AddDelta(676, 417), 6, true, "第一阶段提交");
        }
예제 #7
0
        public void ClickLoginButton()
        {
            // 可能有身份证输入框
            var d2 = new CoordPoint(642, 473);

            actionManager.ClickBtnOnceAtPoint(d2, "投标竞拍T2");
            KK.Sleep(200);

            // 没有身份证输入框
            var d1 = new CoordPoint(642, 427);

            actionManager.ClickBtnOnceAtPoint(d1, "投标竞拍T1");
        }
예제 #8
0
        // private int SubmitOfferedPrice(int fixSec, PriceStrategyOperate oper, string answer, PagePrice pp, int offeredPrice, int usedDelayMills, DateTime occurTime)
        private int SubmitOfferedPrice(BiddingPriceRequest req)
        {
            bool     submitted = false;
            string   memo      = "";
            DateTime occurTime = DateTime.Now;

            if (req.OperateStatus == StrategyOperateStatus.CAPTCHA_INPUTTED)
            {
                if (req.ComputedDelayMills > 0)
                {
                    KK.Sleep(req.ComputedDelayMills);
                }
                phase2Manager.SubmitOfferedPrice();
                submitted = true;

                logger.InfoFormat("strategy#{0} exec submit", req.StrategySecond);
            }
            else
            {
                string answer = CaptchaTaskContext.me.GetAnswer(req.CaptchaUuid);
                if (answer == null || answer.Length == 0)
                {
                    submitted = false;
                    logger.ErrorFormat("strategy#{0} can not exec submit, because has no captcha-answer#{1}", req.StrategySecond, req.CaptchaUuid);

                    return(-1);
                }
                else
                {
                    if (req.ComputedDelayMills > 0)
                    {
                        KK.Sleep(req.ComputedDelayMills);
                    }
                    phase2Manager.SubmitOfferedPrice(answer);

                    memo = "WiAns";

                    logger.WarnFormat("strategy#{0} exec submit and fill captcha-answer#{1}", req.StrategySecond, answer);
                }
            }

            if (submitted)
            {
                req.OperateStatus = StrategyOperateStatus.PRICE_SUBMITTED;
                biddingPriceManager.RemoveStrategy(req.StrategySecond);

                AsyncReportPriceSubbmitted(req, occurTime, memo);
            }

            return(0);
        }
예제 #9
0
        public void StartClient()
        {
            logger.InfoFormat("begin start socket-client with address#{0}:{1}", ip, port);

            socketStarting = true;
            working        = true;
            connectStatus  = ConnectStatusEnum.CONNECTING;
            try
            {
                IPAddress  ipAddr   = IPAddress.Parse(ip);
                IPEndPoint remoteEP = new IPEndPoint(ipAddr, port);

                // Create a TCP/IP socket.
                _client = new Socket(ipAddr.AddressFamily, SocketType.Stream, ProtocolType.Tcp);

                // Connect to the remote endpoint.
                _client.BeginConnect(remoteEP, new AsyncCallback(ConnectCallback), _client);
                while (connectStatus == ConnectStatusEnum.CONNECTING)
                {
                    KK.Sleep(100);

                    if (connectStatus == ConnectStatusEnum.CONNECT_FAILED)
                    {
                        break;
                    }
                }
                socketStarting = false;
                logger.InfoFormat("connectStatus is {0}", connectStatus);

                logger.InfoFormat("end socket-client connect with address#{0}:{1}, _client#{2}", ip, port, _client);

                this.InvokeAfterSuccessConnected();
            }
            catch (Exception e)
            {
                logger.Error("StartClient error", e);
            }
            finally
            {
                socketStarting = false;
            }


            // 无论何种情况,都应开启守护
            if (EnableSocketGuard)
            {
                KeepAliveManager.ME.RestartGuard(this);
            }
        }
예제 #10
0
        /// <summary>
        /// 提交已出的价格
        /// </summary>
        public void SubmitOfferedPrice()
        {
            // TODO: 为了尽快的点击到确定按钮,提供3种模式
            if (conf.IsConfirmModeNormal())
            {
                actionManager.ClickButtonAtPoint(actionManager.AddDelta(554, 506), false, "第二阶段提交#1");
            }
            else if (conf.IsConfirmModeMixed())
            {
                actionManager.ClickButtonAtPoint(actionManager.AddDelta(554, 506), false, "第二阶段提交#1");
                actionManager.ClickButtonByFenceWayLToR(actionManager.AddDelta(553, 500));
            }
            else if (conf.IsConfirmModeFence())
            {
                actionManager.ClickButtonByFenceWayLToR(actionManager.AddDelta(553, 500));
            }
            else
            {
                actionManager.ClickButtonByFenceWayLToR(actionManager.AddDelta(553, 500));
            }

            // TODO: 等待, 点击完成验证码确认按钮, 会弹出 出价有效
            // TODO: 应该检测 区域 是否有 出价有效
            KK.Sleep(600);

            // 尝试得到提交的结果截图, 0.6s 1.6s 2.6s
            ThreadUtils.StartNewBackgroudThread(() => {
                for (int i = 0; i < 3; i++)
                {
                    try
                    {
                        string imgPath = actionManager.CaptureFlashScreen();
                        logger.InfoFormat("result of phase2-act is {0}", imgPath);
                        KK.Sleep((i + 1) * 1000);
                    }
                    catch (Exception e)
                    {
                        logger.Error("act2 background CaptureFlashScreen error", e);
                    }
                }
            });


            actionManager.ClickButtonAtPoint(actionManager.AddDelta(661, 478), false, "第二阶段提交#确定");

            // 清除以前输入的价格
            actionManager.CleanTextAtPoint(actionManager.AddDelta(676, 417), 6, true, "第二阶段提交");
        }
예제 #11
0
        /// <summary>
        /// 出价 -
        /// 1. 输入价格 - 移动到输入框位置,点击,清空历史数据,输入新价格
        /// 2. 点击出价按钮 - 移动到按钮位置,点击
        /// 3. 对验证码区域截图 且 上传
        /// </summary>
        public CaptchaAnswerImage OfferPrice(int targetPrice, bool enableCancelFirst, bool needUploadCaptchaTask = false)
        {
            // 0. 出价前,先尝试取消,防止上一步的可能的遮罩
            if (enableCancelFirst)
            {
                actionManager.ClickButtonByFenceWayRToL(actionManager.AddDelta(742, 502));
            }

            // 1. 输入价格 且 出价
            actionManager.InputTextAtPoint(actionManager.AddDelta(676, 317), targetPrice.ToString(), true, "第一阶段出价#i1");
            actionManager.InputTextAtPoint(actionManager.AddDelta(676, 375), targetPrice.ToString(), true, "第一阶段出价#i2");
            actionManager.ClickButtonAtPoint(actionManager.AddDelta(800, 373), true, "第一阶段出价");

            // 2. 对验证码区域截屏且上传
            KK.Sleep(500);
            CaptchaAnswerImage img = CaptureCaptchaImage();

            UploadCaptchaImage(img);

            return(img);
        }
예제 #12
0
        private void TellToReconnect(string reason)
        {
            continuousDisconnectedCount++;
            // 每3次 未连接,则多停一会
            if (continuousDisconnectedCount % 3 == 0)
            {
                logger.InfoFormat("continuous disconnected count over 3 times, disconnect count is {0}", continuousDisconnectedCount);
                KK.Sleep(DETECT_INTERVAL_MILLS * 6);
            }

            if (notifyRestarting)
            {
                logger.InfoFormat("already tell socket client to reconnect");
            }
            else
            {
                logger.WarnFormat("tell try to reconnect, reason is {0}", reason);
                ThreadUtils.StartNewBackgroudThread(() => {
                    socketClient.RestartClient();
                });
                notifyRestarting = true;
            }
        }
예제 #13
0
        private void ReceiveForEver()
        {
            while (working)
            {
                try
                {
                    // TODO: 这里只能读取一个buffer大小, 后续优化
                    byte[] bytes    = new byte[1024 * 4];
                    int    bytesRec = _client.Receive(bytes);
                    byte[] data     = new byte[bytesRec];
                    ByteUtils.arraycopy(bytes, 0, data, 0, bytesRec);

                    RawMessage raw = RawMessageEncoder.me.decode(data);
                    if (raw.getMessageType() != (int)RawMessageType.PING_COMMAND)
                    {
                        logger.InfoFormat("receive data is {0}, {1}, {2}", raw.totalLength, raw.messageType, raw.bodyText);
                    }

                    MessageDispatcher.ME.Dispatch(raw);

                    this.anotherRecvCallback?.Invoke(raw);

                    // logger.InfoFormat("Echoed test = {0}", Encoding.ASCII.GetString(bytes, 0, bytesRec));
                }
                catch (Exception e)
                {
                    // logger.ErrorFormat("Receive error", e.Message);
                    logger.Error("Receive error", e);

                    // TODO: 出现错误, 先临时处理 不再接收了
                    working = false;

                    KK.Sleep(50);
                }
            }
        }
예제 #14
0
        private void _LoginBidAccount(string bidNo, string password, string idCardNo, bool clickLoginButton)
        {
            // 登录页
            var p21 = actionManager.DeltaPoint(610, 168);
            var p22 = actionManager.DeltaPoint(610, 218);
            var p23 = actionManager.DeltaPoint(610, 264);

            actionManager.InputTextAtPoint(p21, bidNo, true, "投标号");
            KK.Sleep(KK.RandomInt(100, 500));

            actionManager.InputTextAtPoint(p22, password, true, "密码");
            KK.Sleep(KK.RandomInt(100, 500));

            // 可能需要输入身份证 - 身份证
            isIdCardShow = IsIdCardNeeded();
            if (isIdCardShow)
            {
                actionManager.InputTextAtPoint(p23, idCardNo, true, "身份证");
            }
            else
            {
                var p231 = actionManager.DeltaPoint(610, 256);
                actionManager.InputTextAtPoint(p231, idCardNo, true, "身份证");
            }

            KK.Sleep(KK.RandomInt(100, 500));

            //this.inputCaptchaAtLogin(p23, "301726");
            //this.clickLoginAtLogin(p24);
            if (clickLoginButton)
            {
                ClickLoginButton();
            }

            logger.InfoFormat("login account#{0} ", bidNo);
        }
예제 #15
0
        /// <summary>
        /// 循环询问验证码图片的答案
        /// </summary>
        private void LoopInquiryCaptchaAnswer()
        {
            while (isInquiryWork)
            {
                long ss = KK.CurrentMills();
                try
                {
                    var  taskContext = CaptchaTaskContext.me;
                    long s1          = KK.CurrentMills();
                    if (CaptchaTaskContext.me.IsAllImagesAnswered())
                    {
                        KK.Sleep(30);
                        continue;
                    }

                    var images = new List <CaptchaAnswerImage>(taskContext.GetImagesOfAwaitAnswer());

                    logger.DebugFormat("inquiry answer, image size is {0}. First Uuid is {1}", images.Count, images[0].Uuid);

                    foreach (var img in images)
                    {
                        if (img == null)
                        {
                            continue;
                        }

                        if (img.Answer == null || img.Answer.Length == 0)
                        {
                            var req = KK.CreateImageAnswerRequest(img.Uuid);

                            DataResult <CaptchaImageAnswerResponse> dr = HttpClients
                                                                         .PostAsJson <DataResult <CaptchaImageAnswerResponse> >(conf.GetCaptchaAnswerUrl, req);

                            if (DataResults.IsOK(dr) && dr.Data?.answer?.Length > 0)
                            {
                                img.Answer = dr.Data.answer;

                                taskContext.PutAnswer(img.Uuid, dr.Data.answer);
                                taskContext.RemoveAwaitImage(img.Uuid);

                                logger.InfoFormat("GET task#{0}'s answer is {1}", img.Uuid, dr.Data.answer);

                                // TODO:这段应该剥离出去
                                // TryInputAnswerAhead(img.Uuid, dr.Data.answer);
                                captchaInputCallbackFunc?.Invoke(img);
                            }
                        }
                        else
                        {
                            taskContext.RemoveAwaitImage(img.Uuid);
                            // captchaInputCallbackFunc?.Invoke(img);
                        }
                    }
                }
                catch (Exception e)
                {
                    logger.Error("LoopInquiryCaptchaAnswer error:", e);
                }
                finally
                {
                    KK.Sleep(30);
                }
            }

            logger.InfoFormat("END LoopInquiryCaptchaAnswer.");
        }
예제 #16
0
        private void LoopDetectPriceAndTimeInScreen()
        {
            logger.InfoFormat("begin loopDetectPriceAndTimeInScreen");
            int i = 0;

            PageTimePriceResult lastResultx = null;

            while (isCollectingWork)
            {
                long ss = KK.CurrentMills();

                try
                {
                    long s1 = KK.CurrentMills();
                    PageTimePriceResult lastResult = actionManager.DetectPriceAndTimeInScreen(lastResultx);

                    // 重复检测
                    if (lastResult.status == 300)
                    {
                        continue;
                    }

                    SetShowUpText(ToShowUpText(lastResult));

                    // 处理异常情况
                    if (lastResult.status != 0)
                    {
                        ProcessErrorDetect(lastResult);

                        // TODO: 这里也需要处理 可能需要的提交,因为远程会下发一个可能的当前秒数
                        // 目的是防止出现卡秒现象

                        continue;
                    }

                    lastResultx = lastResult;

                    PagePrice pp = lastResult.data;

                    logger.DebugFormat("detectPriceAndTimeInScreen elapsed {0}ms", KK.CurrentMills() - s1);

                    if (pp != null)
                    {
                        if (pp.pageTime.Minute == 28)
                        {
                            if (IsOneRoundStarted)
                            {
                                ResetContext();
                                IsOneRoundStarted = false;
                            }
                        }
                        else if (pp.pageTime.Minute == 29)
                        {
                            if (!IsOneRoundStarted)
                            {
                                IsOneRoundStarted = true;
                            }
                        }

                        s1 = KK.CurrentMills();
                        AfterSuccessDetectInner(pp);
                        logger.DebugFormat("afterDetect elapsed {0}ms", KK.CurrentMills() - s1);
                    }
                    else
                    {
                        // TODO:
                    }
                }
                catch (Exception e)
                {
                    logger.Error("detect price and time error", e);
                }
                finally
                {
                    // TODO: 这里可能不需要每次重置dict
                    // actionManager.ResetDictIndex();

                    KK.Sleep(12);
                }

                logger.DebugFormat("round {0} loopDetectPriceAndTimeInScreen elapsed {1}ms", i++, KK.CurrentMills() - ss);
            }

            logger.InfoFormat("END loopDetectPriceAndTimeInScreen ");
        }