diff --git a/.DS_Store b/.DS_Store
new file mode 100644
index 0000000..7d58cda
Binary files /dev/null and b/.DS_Store differ
diff --git a/README.md b/README.md
index ae0d395..bba7459 100644
--- a/README.md
+++ b/README.md
@@ -1,6 +1,9 @@
# Captcha Tools
Python module to help solve captchas with Capmonster, 2Captcha and Anticaptcha API's!
+#### Go(lang)
+To see documentation for the Go implementation, [click here](https://github.com/Matthew17-21/Captcha-Tools/captchatools-go)
+
# Install
```python
pip3 install captchatools
diff --git a/captchatools-go/README.md b/captchatools-go/README.md
new file mode 100644
index 0000000..d6ad548
--- /dev/null
+++ b/captchatools-go/README.md
@@ -0,0 +1,152 @@
+# Captcha Tools (Go)
+Go package to help solve captchas with Capmonster, 2Captcha and Anticaptcha API's!
+
+# Install
+```go
+go get github.com/Matthew17-21/Captcha-Tools/captchatools-go
+```
+##### To update
+```go
+go get -u github.com/Matthew17-21/Captcha-Tools/captchatools-go
+```
+
+# How to use
+```go
+package main
+
+import (
+ "fmt"
+
+ captchatools "github.com/Matthew17-21/Captcha-Tools/captchatools-go"
+)
+
+func main() {
+ solver, err := captchatools.NewHarvester(captchatools.CapmonsterSite, &captchatools.Config{
+ Api_key: "ENTER YOUR API KEY HERE",
+ Sitekey: "6Le-wvkSAAAAAPBMRTvw0Q4Muexq9bi0DJwx_mJ-",
+ CaptchaURL: "https://www.google.com/recaptcha/api2/demo",
+ CaptchaType: "V2",
+ })
+ if err != nil {
+ panic(err)
+ }
+ fmt.Println(solver.GetToken())
+}
+
+```
+V3 Captcha Exmaple:
+```go
+func v3Example() {
+ solver, err := captchatools.NewHarvester(captchatools.AnticaptchaSite, &captchatools.Config{
+ Api_key: "ENTER YOUR API KEY HERE",
+ Sitekey: "6Le-wvkSAAAAAPBMRTvw0Q4Muexq9bi0DJwx_mJ-",
+ CaptchaURL: "..........",
+ CaptchaType: "V3",
+ Action: "submit",
+ MinScore: 0.9,
+ })
+ if err != nil {
+ panic(err)
+ }
+ fmt.Println(solver.GetToken())
+}
+
+```
+### captchatools.NewHarvester() Parameters:
+| Parameter | Required | Type | Default | Description|
+| :-------------: |:-------------:| :-----:| :-----:| :-----:|
+| solving_site | true | int| -| The captcha solving site that will be used. Refer to [the site IDs](https://github.com/Matthew17-21/Captcha-Tools/captchatools-go#site-specific-support). Alternatively, you can use shortcuts such as `captchatools.AnticaptchaSite` |
+| Config| true | captchatools.Config | - | Configurations for the captchas you are solving. |
+
+
+### Config struct fields:
+| Field | Required | Type | Default | Description|
+| :-------------: |:-------------:| :-----:| :-----:| :-----:|
+| Api_key | true | String| -| The API Key for the captcha solving site|
+| Sitekey| true | String | - | Sitekey from the site where captcha is loaded|
+| CaptchaURL | true| String | - | URL where the captcha is located|
+| CaptchaType| true| String | - | Type of captcha you are solving. Either captcha `v2`, `v3` or `hcaptcha` (`hcap` works aswell)|
+| Action | false | String | - | Action that is associated with the V3 captcha.
__This param is only required when solving V3 captchas__|
+| IsInvisibleCaptcha| false | bool | - | If the captcha is invisible or not.
__This param is only required when solving invisible captchas__|
+| MinScore | false | float32 | - | Minimum score for v3 captchas.
__This param is only required when solving V3 and it needs a higher / lower score__|
+
+
+
+# Supported Sites
+- **[Capmonster](https://capmonster.cloud/)**
+- **[2Captcha](https://www.2captcha.com/)**
+- **[Anticaptcha](https://www.anti-captcha.com/)**
+
+##### Site-Specific Support:
+| Site |Site ID| Captcha Types Supported | Task Types Supported|
+| :-------------: |:-------------:|:-------------:| :-----:|
+| Capmonster |1| Recaptcha V2,
Recaptcha V3,
HCaptcha | RecaptchaV2TaskProxyless,
RecaptchaV3TaskProxyless,
HCaptchaTaskProxyless |
+| Anticaptcha |2| Recaptcha V2,
Recaptcha V3,
HCaptcha | RecaptchaV2TaskProxyless,
RecaptchaV3TaskProxyless,
HCaptchaTaskProxyless |
+| 2Captcha |3| Recaptcha V2,
Recaptcha V3,
HCaptcha | - |
+
+
+# Recommendations
+1. For 2Captcha, don't run more than 60 tasks per API key.
+2. Handle errors appropriately.
+ * If a `ErrNoBalance` is thrown, tasks should stop. Some sites will temporarily ban IP's if constant requests come in.
+
+# Errors
+| Errors | Raised |
+| :--------:| :-----:|
+| `ErrNoBalance` | Balance is below 0 for captcha solving site|
+| `ErrWrongAPIKey` | Incorrect API Key for captcha solving site|
+| `ErrWrongSitekey` | Incorrect sitekey |
+| `ErrIncorrectCapType` | Incorrectly chose a captcha type. When initializing a new harvester. Refer to [the captcha types](https://github.com/Matthew17-21/Captcha-Tools/captchatools-go#how-to-use) |
+| `ErrNoHarvester` | When the user did not / incorrectly chose a captcha harvester. Refer to the [guide](https://github.com/Matthew17-21/Captcha-Tools/captchatools-go#how-to-use) |
+
+```go
+package main
+
+import (
+ "fmt"
+
+ captchatools "github.com/Matthew17-21/Captcha-Tools/captchatools-go"
+)
+
+func main() {
+ solver, err := captchatools.NewHarvester(captchatools.AnticaptchaSite, &captchatools.Config{
+ Api_key: "ENTER YOUR API KEY HERE",
+ Sitekey: "6Le-wvkSAAAAAPBMRTvw0Q4Muexq9bi0DJwx_mJ-",
+ CaptchaURL: "https://www.google.com/recaptcha/api2/demo",
+ CaptchaType: "V2",
+ })
+ if err != nil {
+ switch err {
+ case captchatools.ErrNoBalance:
+ fmt.Println("No balance.")
+ panic(err)
+ }
+ }
+ fmt.Println(solver.GetToken())
+}
+
+```
+
+
+# TO DO
+1. [] Document code better
+2. [] 2Captcha
+ * [] Clean up code
+ * [] Proxy support
+ * [] Cookie support
+ * [] User Agent Support
+ * [] Different type of captchas
+3. [] Anticaptcha
+ * [] Clean up code
+ * [] Proxy support
+ * [] Cookie support
+ * [] User Agent Support
+ * [] Different type of captchas
+4. [] Capmonster
+ * [] Clean up code
+ * [] Proxy support
+ * [] Cookie support
+ * [] User Agent Support
+ * [] Different type of captchas
+5. [] Add DeathByCaptcha
+6. [] Allow for refunds
\ No newline at end of file
diff --git a/captchatools-go/anticaptcha.go b/captchatools-go/anticaptcha.go
new file mode 100644
index 0000000..d77cae5
--- /dev/null
+++ b/captchatools-go/anticaptcha.go
@@ -0,0 +1,128 @@
+package captchatoolsgo
+
+import (
+ "bytes"
+ "encoding/json"
+ "fmt"
+ "io/ioutil"
+ "net/http"
+ "time"
+)
+
+// This file will contain the code to interact with anticaptcha.com API
+
+func (t *Anticaptcha) GetToken() (string, error) {
+ return t.getCaptchaAnswer()
+}
+
+// Method to get Queue ID from the API.
+func (t *Anticaptcha) getID() (int, error) {
+ // Get Payload
+ payload, _ := t.createPayload()
+
+ // Make request to get answer
+ response := &capmonsterIDResponse{}
+ for {
+ resp, err := http.Post("https://api.anti-captcha.com/createTask", "application/json", bytes.NewBuffer([]byte(payload)))
+ if err != nil {
+ time.Sleep(3 * time.Second)
+ continue
+ }
+ body, _ := ioutil.ReadAll(resp.Body)
+ resp.Body.Close()
+ json.Unmarshal(body, response)
+
+ // Parse the response
+ if response.ErrorID == 0 { // Means there was no error
+ return response.TaskID, nil
+ }
+ switch response.ErrorCode {
+ case "ERROR_ZERO_BALANCE":
+ return 0, ErrNoBalance
+ case "ERROR_RECAPTCHA_INVALID_SITEKEY":
+ return 0, ErrWrongSitekey
+ case "ERROR_KEY_DOES_NOT_EXIST":
+ return 0, ErrWrongAPIKey
+ }
+
+ }
+}
+
+// This method gets the captcha token from the Capmonster API
+func (t *Anticaptcha) getCaptchaAnswer() (string, error) {
+ // Get Queue ID
+ queueID, err := t.getID()
+ if err != nil {
+ return "", err
+ }
+
+ // Get Captcha Answer
+ payload, _ := json.Marshal(capmonsterCapAnswerPayload{
+ ClientKey: t.config.Api_key,
+ TaskID: queueID,
+ })
+ response := &capmonsterTokenResponse{}
+ for {
+ resp, err := http.Post("https://api.anti-captcha.com/getTaskResult", "application/json", bytes.NewBuffer([]byte(payload)))
+ if err != nil {
+ time.Sleep(3 * time.Second)
+ continue
+ }
+
+ // Parse Response
+ body, _ := ioutil.ReadAll(resp.Body)
+ resp.Body.Close()
+ fmt.Println(string(body))
+ json.Unmarshal(body, response)
+ if response.Status == "ready" {
+ return response.Solution.GRecaptchaResponse, nil
+ } else if response.ErrorID == 12 || response.ErrorID == 16 { // Captcha unsolvable || TaskID doesn't exist
+ t.GetToken()
+ }
+ time.Sleep(3 * time.Second)
+ }
+}
+
+/*
+ createPayload returns the payloads required to interact with the API.
+
+ Possible errors that can be returned:
+ 1) ErrIncorrectCapType
+*/
+func (t *Anticaptcha) createPayload() (string, error) {
+ // Define the payload we are going to send to the API
+ payload := capmonsterIDPayload{
+ ClientKey: t.config.Api_key,
+ Task: struct {
+ WebsiteURL string "json:\"websiteURL\""
+ WebsiteKey string "json:\"websiteKey\""
+ Type string "json:\"type\""
+ IsInvisible bool "json:\"isInvisible,omitempty\""
+ MinScore float32 "json:\"minScore,omitempty\""
+ PageAction string "json:\"pageAction,omitempty\""
+ }{
+ WebsiteURL: t.config.CaptchaURL,
+ WebsiteKey: t.config.Sitekey,
+ Type: t.config.CaptchaType,
+ },
+ }
+
+ // Add any other keys to the payload
+ switch t.config.CaptchaType {
+ case "v2":
+ payload.Task.Type = "NoCaptchaTaskProxyless"
+ if t.config.IsInvisibleCaptcha {
+ payload.Task.IsInvisible = t.config.IsInvisibleCaptcha
+ }
+ case "v3":
+ payload.Task.Type = "RecaptchaV3TaskProxyless"
+ payload.Task.MinScore = t.config.MinScore
+ payload.Task.PageAction = t.config.Action
+ case "hcaptcha", "hcap":
+ payload.Task.Type = "HCaptchaTaskProxyless"
+ default:
+ return "", ErrIncorrectCapType
+ }
+ encoded, _ := json.Marshal(payload)
+ return string(encoded), nil
+}
diff --git a/captchatools-go/capmonster.go b/captchatools-go/capmonster.go
new file mode 100644
index 0000000..66af24b
--- /dev/null
+++ b/captchatools-go/capmonster.go
@@ -0,0 +1,128 @@
+package captchatoolsgo
+
+import (
+ "bytes"
+ "encoding/json"
+ "io/ioutil"
+ "net/http"
+ "time"
+)
+
+/*
+ This file will contain the code to interact with capmonster.cloud API
+*/
+
+func (t *Capmonster) GetToken() (string, error) {
+ return t.getCaptchaAnswer()
+}
+
+// Method to get Queue ID from the API.
+func (t *Capmonster) getID() (int, error) {
+ // Get Payload
+ payload, _ := t.createPayload()
+
+ // Make request to get answer
+ for {
+ resp, err := http.Post("https://api.capmonster.cloud/createTask", "application/json", bytes.NewBuffer([]byte(payload)))
+ if err != nil {
+ time.Sleep(3 * time.Second)
+ continue
+ }
+ body, _ := ioutil.ReadAll(resp.Body)
+ response := &capmonsterIDResponse{}
+ resp.Body.Close()
+ json.Unmarshal(body, response)
+
+ // Parse the response
+ if response.ErrorID == 0 { // Means there was no error
+ return response.TaskID, nil
+ }
+ switch response.ErrorCode {
+ case "ERROR_ZERO_BALANCE":
+ return 0, ErrNoBalance
+ case "ERROR_RECAPTCHA_INVALID_SITEKEY":
+ return 0, ErrWrongSitekey
+ case "ERROR_KEY_DOES_NOT_EXIST":
+ return 0, ErrWrongAPIKey
+ }
+
+ }
+}
+
+// This method gets the captcha token from the Capmonster API
+func (t *Capmonster) getCaptchaAnswer() (string, error) {
+ // Get Queue ID
+ queueID, err := t.getID()
+ if err != nil {
+ return "", err
+ }
+
+ // Get Captcha Answer
+ payload, _ := json.Marshal(capmonsterCapAnswerPayload{
+ ClientKey: t.config.Api_key,
+ TaskID: queueID,
+ })
+ response := &capmonsterTokenResponse{}
+ for {
+ resp, err := http.Post("https://api.capmonster.cloud/getTaskResult", "application/json", bytes.NewBuffer([]byte(payload)))
+ if err != nil {
+ time.Sleep(3 * time.Second)
+ continue
+ }
+
+ // Parse Response
+ body, _ := ioutil.ReadAll(resp.Body)
+ resp.Body.Close()
+ json.Unmarshal(body, response)
+ if response.Status == "ready" {
+ return response.Solution.GRecaptchaResponse, nil
+ } else if response.ErrorID == 12 || response.ErrorID == 16 { // Captcha unsolvable || TaskID doesn't exist
+ t.GetToken()
+ }
+ time.Sleep(3 * time.Second)
+ }
+}
+
+/*
+ createPayload returns the payloads required to interact with the API.
+
+ Possible errors that can be returned:
+ 1) ErrIncorrectCapType
+*/
+func (t *Capmonster) createPayload() (string, error) {
+ // Define the payload we are going to send to the API
+ payload := capmonsterIDPayload{
+ ClientKey: t.config.Api_key,
+ Task: struct {
+ WebsiteURL string "json:\"websiteURL\""
+ WebsiteKey string "json:\"websiteKey\""
+ Type string "json:\"type\""
+ IsInvisible bool "json:\"isInvisible,omitempty\""
+ MinScore float32 "json:\"minScore,omitempty\""
+ PageAction string "json:\"pageAction,omitempty\""
+ }{
+ WebsiteURL: t.config.CaptchaURL,
+ WebsiteKey: t.config.Sitekey,
+ Type: t.config.CaptchaType,
+ },
+ }
+
+ // Add any other keys to the payload
+ switch t.config.CaptchaType {
+ case "v2":
+ payload.Task.Type = "NoCaptchaTaskProxyless"
+ if t.config.IsInvisibleCaptcha {
+ payload.Task.IsInvisible = t.config.IsInvisibleCaptcha
+ }
+ case "v3":
+ payload.Task.Type = "RecaptchaV3TaskProxyless"
+ payload.Task.MinScore = t.config.MinScore
+ payload.Task.PageAction = t.config.Action
+ case "hcaptcha", "hcap":
+ payload.Task.Type = "HCaptchaTaskProxyless"
+ default:
+ return "", ErrIncorrectCapType
+ }
+ encoded, _ := json.Marshal(payload)
+ return string(encoded), nil
+}
diff --git a/captchatools-go/go.mod b/captchatools-go/go.mod
new file mode 100644
index 0000000..e9b8caa
--- /dev/null
+++ b/captchatools-go/go.mod
@@ -0,0 +1,3 @@
+module github.com/Matthew17-21/Captcha-Tools/captchatools-go
+
+go 1.16
diff --git a/captchatools-go/harvester.go b/captchatools-go/harvester.go
new file mode 100644
index 0000000..bfe1c42
--- /dev/null
+++ b/captchatools-go/harvester.go
@@ -0,0 +1,45 @@
+package captchatoolsgo
+
+import "strings"
+
+/*
+ NewHarvester returns a captcha harvester based on the info given
+ by the caller. An error is returned if there is no proper
+ solving_site argument.
+
+ To make the implementation similiar to the Python version,
+ this function was needed.
+
+ For documentation on how to use this, checkout
+ https://github.com/Matthew17-21/Captcha-Tools
+*/
+func NewHarvester(solving_site int, config *Config) (*Harvester, error) {
+ h := &Harvester{}
+ config.CaptchaType = strings.ToLower(config.CaptchaType)
+ config.CaptchaURL = strings.ToLower(config.CaptchaURL)
+
+ // Check for any errors
+ switch strings.ToLower(config.CaptchaType) {
+ case "hcaptcha", "hcap", "v2", "v3":
+ default:
+ return nil, ErrIncorrectCapType
+ }
+
+ // Get A Harvester
+ switch solving_site {
+ case AnticaptchaSite:
+ h.childHarvester = &Anticaptcha{config: config}
+ case CapmonsterSite:
+ h.childHarvester = &Capmonster{config: config}
+ case TwoCaptchaSite:
+ h.childHarvester = &Twocaptcha{config: config}
+ default:
+ return nil, ErrNoHarvester
+ }
+ return h, nil
+}
+
+// GetToken returns a captcha token from the selected solving site
+func (h *Harvester) GetToken() (string, error) {
+ return h.childHarvester.GetToken()
+}
diff --git a/captchatools-go/twocaptcha.go b/captchatools-go/twocaptcha.go
new file mode 100644
index 0000000..fa46634
--- /dev/null
+++ b/captchatools-go/twocaptcha.go
@@ -0,0 +1,121 @@
+package captchatoolsgo
+
+import (
+ "bytes"
+ "encoding/json"
+ "fmt"
+ "io/ioutil"
+ "net/http"
+ "time"
+)
+
+// This file will contain the code to interact with anticaptcha.com API
+
+func (t *Twocaptcha) GetToken() (string, error) {
+ return t.getCaptchaAnswer()
+}
+
+// Method to get Queue ID from the API.
+func (t *Twocaptcha) getID() (string, error) {
+ // Get Payload
+ payload, _ := t.createPayload()
+
+ // Make request to get answer
+ for {
+ resp, err := http.Post("http://2captcha.com/in.php", "application/json", bytes.NewBuffer([]byte(payload)))
+ if err != nil {
+ time.Sleep(3 * time.Second)
+ continue
+ }
+ body, _ := ioutil.ReadAll(resp.Body)
+ response := &twocaptchaResponse{}
+ resp.Body.Close()
+ json.Unmarshal(body, response)
+
+ // Parse the response
+ if response.Status == 1 { // Means there was no error
+ return response.Request, nil
+ }
+ switch response.Request {
+ case "ERROR_ZERO_BALANCE":
+ return "", ErrNoBalance
+ case "ERROR_WRONG_GOOGLEKEY":
+ return "", ErrWrongSitekey
+ case "ERROR_WRONG_USER_KEY", "ERROR_KEY_DOES_NOT_EXIST":
+ return "", ErrWrongAPIKey
+ }
+
+ }
+}
+
+// This method gets the captcha token from the Capmonster API
+func (t *Twocaptcha) getCaptchaAnswer() (string, error) {
+ // Get Queue ID
+ queueID, err := t.getID()
+ if err != nil {
+ return "", err
+ }
+
+ // Get Captcha Answer
+ response := &twocaptchaResponse{}
+ urlToAnswer := fmt.Sprintf(
+ "http://2captcha.com/res.php?key=%v&action=get&id=%v&json=1",
+ t.config.Api_key,
+ queueID,
+ )
+ for {
+ resp, err := http.Get(urlToAnswer)
+ if err != nil {
+ time.Sleep(3 * time.Second)
+ continue
+ }
+
+ // Parse Response
+ body, _ := ioutil.ReadAll(resp.Body)
+ resp.Body.Close()
+ json.Unmarshal(body, response)
+ if response.Status == 1 {
+ return response.Request, nil
+ } else if response.Request == "ERROR_CAPTCHA_UNSOLVABLE" {
+ t.GetToken()
+ }
+ time.Sleep(3 * time.Second)
+ }
+}
+
+/*
+ createPayload returns the payloads required to interact with the API.
+
+ Possible errors that can be returned:
+ 1) ErrIncorrectCapType
+*/
+func (t *Twocaptcha) createPayload() (string, error) {
+ // Define the payload we are going to send to the API
+ payload := twoCapIDPayload{
+ Key: t.config.Api_key,
+ Pageurl: t.config.CaptchaURL,
+ JSON: 1,
+ Method: "userrecaptcha",
+ }
+
+ // Add any other keys to the payload
+ switch t.config.CaptchaType {
+ case "v2":
+ payload.Googlekey = t.config.Sitekey
+ if t.config.IsInvisibleCaptcha {
+ payload.Invisible = 1
+ }
+ case "v3":
+ payload.Googlekey = t.config.Sitekey
+ payload.Version = "v3"
+ payload.Action = t.config.Action
+ payload.MinScore = t.config.MinScore
+ case "hcaptcha", "hcap":
+ payload.Method = "hcaptcha"
+ payload.Sitekey = t.config.Sitekey
+ default:
+ return "", ErrIncorrectCapType
+ }
+ encoded, _ := json.Marshal(payload)
+ return string(encoded), nil
+}
diff --git a/captchatools-go/types.go b/captchatools-go/types.go
new file mode 100644
index 0000000..ddf4ddd
--- /dev/null
+++ b/captchatools-go/types.go
@@ -0,0 +1,126 @@
+package captchatoolsgo
+
+import "errors"
+
+// General type declarations
+const (
+ MODULE_VERSION string = "1.2.0" // Current version of this module
+
+ // The int 1 will represent Capmonter
+ CapmonsterSite int = 1
+
+ // The int 2 will represent Anticaptcha
+ AnticaptchaSite int = 2
+
+ // The int 3 will represent 2captcha
+ TwoCaptchaSite int = 3
+)
+
+type (
+ // Configurations for the captchas you are solving.
+ // For more a detailed documentation, visit
+ // https://github.com/Matthew17-21/Captcha-Tools
+ Config struct {
+ Api_key string // The API Key for the captcha solving site.
+ Sitekey string // Sitekey from the site where captcha is loaded.
+ CaptchaURL string // URL where the captcha is located.
+ CaptchaType string // Type of captcha you are solving. Visit https://github.com/Matthew17-21/Captcha-Tools for types
+ Action string // Action that is associated with the V3 captcha.
+ IsInvisibleCaptcha bool // If the captcha is invisible or not.
+ MinScore float32 // Minimum score for v3 captchas.
+ }
+
+ /*
+ - type Harvester will be used to represent a captcha harvester.
+
+ - In order to to have the same functionality/implementation as the
+ Python version, type Harvester has the `childHarvester` field, which is of type interface.
+ This allows us to set the field as a pointer to a real captcha harvester
+ and use the `GetToken` method that each captcha harvester struct has.
+ (Polymorphism)
+
+ - For documentation, visit https://github.com/Matthew17-21/Captcha-Tools
+ */
+ Harvester struct {
+ childHarvester GetTokenFunc
+ }
+
+ // GetTokenFunc will allow us to interact with the `GetToken` struct method
+ // that each captcha harvester has.
+ GetTokenFunc interface {
+ GetToken() (string, error)
+ }
+
+ Anticaptcha struct {
+ config *Config
+ }
+
+ Capmonster struct {
+ config *Config
+ }
+
+ Twocaptcha struct {
+ config *Config
+ }
+)
+
+// Payload type declarations
+type (
+ // This struct will be the payload to get the queue ID from capmonster
+ capmonsterIDPayload struct {
+ ClientKey string `json:"clientKey"`
+ Task struct {
+ WebsiteURL string `json:"websiteURL"`
+ WebsiteKey string `json:"websiteKey"`
+ Type string `json:"type"`
+ IsInvisible bool `json:"isInvisible,omitempty"`
+ MinScore float32 `json:"minScore,omitempty"`
+ PageAction string `json:"pageAction,omitempty"`
+ } `json:"task"`
+ }
+ capmonsterCapAnswerPayload struct {
+ ClientKey string `json:"clientKey"`
+ TaskID int `json:"taskId"`
+ }
+)
+
+// Response type declarations
+type (
+ capmonsterIDResponse struct {
+ ErrorID int `json:"errorId"`
+ ErrorCode string `json:"errorCode"`
+ TaskID int `json:"taskId"`
+ }
+
+ capmonsterTokenResponse struct {
+ ErrorID int `json:"errorId"`
+ Solution struct {
+ GRecaptchaResponse string `json:"gRecaptchaResponse"`
+ } `json:"solution"`
+ Status string `json:"status"`
+ }
+
+ twoCapIDPayload struct {
+ Key string `json:"key"`
+ Method string `json:"method"`
+ Googlekey string `json:"googlekey"`
+ Pageurl string `json:"pageurl"`
+ JSON int `json:"json"`
+ Sitekey string `json:"sitekey,omitempty"`
+ Invisible int `json:"invisible,omitempty"`
+ Version string `json:"version,omitempty"`
+ Action string `json:"action,omitempty"`
+ MinScore float32 `json:"min_score,omitempty"`
+ }
+ twocaptchaResponse struct {
+ Status int `json:"status"`
+ Request string `json:"request"`
+ }
+)
+
+// Error type declarations
+var ErrNoBalance error = errors.New("no balance on site")
+var ErrWrongAPIKey error = errors.New("incorrect API Key for captcha solving site")
+var ErrWrongSitekey = errors.New("incorrect API Key for captcha solving site")
+var ErrNoHarvester = errors.New("incorrectly chose a captcha harvester. Refer to guide")
+var ErrIncorrectCapType = errors.New("incorrectly chose a captcha type. Refer to guide")