Пример #1
0
        private async Task<string> HandleCaptcha(Captcha captcha)
        {
            Brush previous = this.captchaHeader.Foreground;
            this.captchaHeader.Foreground = Brushes.Red;

            try
            {
                return await this.captcha.Solve(captcha);
            }
            catch (TaskCanceledException)
            {
                return null;
            }
            finally
            {
                this.captchaHeader.Foreground = previous;
            }
        }
Пример #2
0
        public Task<string> Solve(Captcha captcha)
        {
            Action dispose = null, initialize = null;
            EventHandler timerHandler = null;
            KeyEventHandler keyHandler = null;
            RoutedEventHandler playHandler = null;
            RoutedEventHandler solveHandler = null;
            RoutedEventHandler reloadHandler = null;
            RoutedEventHandler cancelHandler = null;
            RoutedEventHandler toAudioHandler = null;
            RoutedEventHandler toTextHandler = null;

            TaskCompletionSource<string> completion = new TaskCompletionSource<string>();
            DispatcherTimer timer = new DispatcherTimer { Interval = TimeSpan.FromSeconds(1) };

            initialize = () =>
            {
                this.panel.Visibility = Visibility.Visible;

                this.Refresh(captcha);
                this.ApplyButtons(captcha);

                this.play.Click += playHandler;
                this.solve.Click += solveHandler;
                this.solve.IsEnabled = false;
                this.reload.Click += reloadHandler;
                this.reload.IsEnabled = true;
                this.cancel.Click += cancelHandler;
                this.cancel.IsEnabled = true;
                this.toAudio.Click += toAudioHandler;
                this.toText.Click += toTextHandler;
                this.text.KeyDown += keyHandler;

                timer.Tick += timerHandler;
                timer.Start();
            };

            dispose = () =>
            {
                this.panel.Visibility = Visibility.Collapsed;

                timer.Tick -= timerHandler;
                timer.Stop();

                this.play.Click -= playHandler;
                this.solve.Click -= solveHandler;
                this.reload.Click -= reloadHandler;
                this.cancel.Click -= cancelHandler;
                this.toAudio.Click -= toAudioHandler;
                this.toText.Click -= toTextHandler;
                this.text.KeyDown -= keyHandler;

                this.image.Source = null;
                this.text.Clear();
            };

            playHandler = async (sender, args) =>
            {
                this.Lock();

                try
                {
                    await captcha.Play();
                }
                finally
                {
                    this.Unlock();
                }
            };

            solveHandler = (sender, args) =>
            {
                completion.SetResult(this.text.Text.Trim());
                dispose.Invoke();
            };

            keyHandler = (sender, args) =>
            {
                if (this.solve.IsEnabled == true && args.Key == Key.Enter)
                {
                    completion.SetResult(this.text.Text.Trim());
                    dispose.Invoke();
                }
            };

            reloadHandler = async (sender, args) =>
            {
                this.Lock();

                try
                {
                    await captcha.Reload.Invoke();
                    this.Refresh(captcha);
                }
                finally
                {
                    this.Unlock();
                }
            };

            toAudioHandler = async (sender, args) =>
            {
                this.Lock();

                try
                {
                    await captcha.ToAudio.Invoke();
                    this.Refresh(captcha);
                    this.ApplyButtons(captcha);
                }
                finally
                {
                    this.Unlock();
                }
            };

            toTextHandler = async (sender, args) =>
            {
                this.Lock();

                try
                {
                    await captcha.ToImage.Invoke();
                    this.Refresh(captcha);
                    this.ApplyButtons(captcha);
                }
                finally
                {
                    this.Unlock();
                }
            };

            cancelHandler = (sender, args) =>
            {
                dispose.Invoke();
                completion.SetResult(null);
            };

            timerHandler = (sender, args) =>
            {
                if (captcha.Cancellation.IsCancellationRequested == true)
                {
                    dispose.Invoke();
                    completion.TrySetCanceled(captcha.Cancellation);
                }
            };

            initialize.Invoke();
            return completion.Task;
        }
Пример #3
0
        private void Refresh(Captcha captcha)
        {
            if (captcha.Type == "image")
            {
                this.image.Source = captcha.ToBitmap();
                this.play.Visibility = Visibility.Collapsed;
            }

            if (captcha.Type == "audio")
            {
                this.image.Source = null;
                this.play.Visibility = Visibility.Visible;
            }
        }
Пример #4
0
        private void ApplyButtons(Captcha captcha)
        {
            int count = 3;

            if (captcha.Type == "image" && captcha.ToAudio != null)
            {
                count++;
                this.toAudio.Visibility = Visibility.Visible;
            }
            else
            {
                this.toAudio.Visibility = Visibility.Collapsed;
            }

            if (captcha.Type == "audio" && captcha.ToImage != null)
            {
                count++;
                this.toText.Visibility = Visibility.Visible;
            }
            else
            {
                this.toText.Visibility = Visibility.Collapsed;
            }

            this.text.Margin = new Thickness(0, 0, 5 + 100 * count, 0);
        }
Пример #5
0
        private async Task<PhantomResponse> CallPhantom(ResourceTask task)
        {
            Regex regex = new Regex(@"to wait (?<minutes>[0-9]+) minutes");
            PhantomResponse response = new PhantomResponse
            {
                Lines = new List<string>()
            };

            task.OnStatus.Invoke("starting");
            task.OnLog.Information("Starting PhantomJS.");

            ProcessStartInfo info = new ProcessStartInfo
            {
                FileName = GetPhantomPath(),
                Arguments = GetScriptPath(task.Hosting) + " download " + task.Url.ToString(),
                UseShellExecute = false,
                RedirectStandardOutput = true,
                RedirectStandardInput = true,
                CreateNoWindow = true,
                WindowStyle = ProcessWindowStyle.Hidden,
                WorkingDirectory = GetDataPath()
            };

            using (Process process = Process.Start(info))
            {
                PhantomCallback callback = new PhantomCallback
                {
                    OnDownload = url =>
                    {
                        response.DownloadUrl = url;
                        return false;
                    },
                    OnMessage = message =>
                    {
                        Match match = regex.Match(message);

                        if (match.Success == true)
                        {
                            if (match.Groups["minutes"].Success == true)
                            {
                                response.Waiting = TimeSpan.FromMinutes(Int32.Parse(match.Groups["minutes"].Value));
                            }
                        }

                        return true;
                    },
                    OnDebug = text =>
                    {
                        task.OnLog.Debug(text);
                        return true;
                    },
                    OnFatal = text =>
                    {
                        task.OnLog.Debug(text);
                        return true;
                    },
                    OnDumpImage = base64 =>
                    {
                        task.OnLog.Debug("PhantomJS dumped an image.", Convert.FromBase64String(base64), "image");
                        return true;
                    },
                    OnDumpHtml = base64 =>
                    {
                        task.OnLog.Debug("PhantomJS dumped an html content.", Convert.FromBase64String(base64), "text");
                        return true;
                    },
                    OnFileName = text => true,
                    OnFileSize = text => true,
                    OnFileStatus = text => true,
                    OnFallback = text => true,
                    OnRaw = line => { },
                };

                callback.OnCaptcha = async url =>
                {
                    string solution;

                    task.Cancellation.ThrowIfCancellationRequested();
                    task.OnLog.Information("Handling captcha.");

                    using (WebClient client = new WebClient())
                    {
                        task.OnStatus("decaptching");

                        TimeSpan timeout = TimeSpan.FromMinutes(3);
                        CancellationTokenSource source = CancellationTokenSource.CreateLinkedTokenSource(new CancellationTokenSource(timeout).Token, task.Cancellation);
                        Captcha captcha = new Captcha
                        {
                            Type = "image",
                            Data = client.DownloadData(url),
                            Cancellation = source.Token
                        };

                        Action debug = () =>
                        {
                            switch (captcha.Type)
                            {
                                case "image":
                                    task.OnLog.Debug("Got captcha image data.", captcha.Data, "image");
                                    break;

                                case "audio":
                                    task.OnLog.Debug("Got captcha audio data.", captcha.Data, "audio");
                                    break;
                            }
                        };

                        PhantomCallback local = callback.Override(new PhantomCallback
                        {
                            OnCaptcha = async reloadUrl =>
                            {
                                source = CancellationTokenSource.CreateLinkedTokenSource(new CancellationTokenSource(timeout).Token, task.Cancellation);
                                captcha.Cancellation = source.Token;
                                captcha.Data = await client.DownloadDataTaskAsync(reloadUrl);

                                debug.Invoke();
                                return false;
                            }
                        });

                        debug.Invoke();
                        captcha.Reload = async () =>
                        {
                            await process.StandardInput.WriteLineAsync("::reload::");
                            task.OnLog.Information("Reloading captcha.");
                            await this.HandleInThread(local, task.Cancellation, process);
                        };

                        captcha.ToAudio = async () =>
                        {
                            await process.StandardInput.WriteLineAsync("::audio::");
                            task.OnLog.Information("Switching to audio.");
                            captcha.Type = "audio";
                            await this.HandleInThread(local, task.Cancellation, process);
                        };

                        captcha.ToImage = async () =>
                        {
                            await process.StandardInput.WriteLineAsync("::image::");
                            task.OnLog.Information("Switching to image.");
                            captcha.Type = "image";
                            await this.HandleInThread(local, task.Cancellation, process);
                        };

                        solution = await task.OnCaptcha.Invoke(captcha);
                        task.OnStatus("working");
                    }

                    task.Cancellation.ThrowIfCancellationRequested();
                    task.OnLog.Information("Sending captcha.");

                    await process.StandardInput.WriteLineAsync(solution);
                    return true;
                };

                try
                {
                    task.OnStatus("working");
                    await this.Handle(callback, task.Cancellation, process);

                    process.WaitForExit();
                    return response;
                }
                finally
                {
                    if (process.HasExited == false)
                    {
                        process.Kill();
                    }
                }
            }
        }