Skip to content

Commit

Permalink
Added Captcha solvers 2captcha and capmonster for DMs
Browse files Browse the repository at this point in the history
  • Loading branch information
V4NSH4J committed Apr 4, 2022
1 parent 98b0cad commit 2e2504f
Show file tree
Hide file tree
Showing 8 changed files with 173 additions and 27 deletions.
9 changes: 5 additions & 4 deletions config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -13,12 +13,12 @@ direct_message_settings:
friend_before_DM: false
online_tokens: false
receive_messages: false
skip_failed: true
skip_failed: false
block_after_dm: false
close_dm_after_message: false

proxy_settings:
proxy_from_file: true
proxy_from_file: true
proxy_for_captcha: true
use_proxy_for_gateway: false
proxy_protocol: "http"
Expand All @@ -31,10 +31,11 @@ scraper_settings:

captcha_settings:
captcha_api_key: ""
captcha_api: "capmonster.cloud"
captcha_api: "2captcha.com"
max_captcha_wait: 60
max_captcha_retry: 3

other_settings:
max_attempt_invite_rejoin: 3
disable_keep_alives: false

suspicion_avoidance:
Expand Down
13 changes: 10 additions & 3 deletions main.go
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ import (
)

func main() {
version := "1.8.8"
version := "1.8.9"
CaptchaServices = []string{"capmonster.cloud", "anti-captcha.com", "2captcha.com", "rucaptcha.com", "deathbycaptcha.com", "anycaptcha.com", "azcaptcha.com", "solvecaptcha.com"}
rand.Seed(time.Now().UTC().UnixNano())
color.Blue(logo + " v" + version + "\n")
Expand Down Expand Up @@ -403,14 +403,14 @@ func Options() {

break
} else {
if instances[i].Rejoin >= maxattempts {
if instances[i].Retry >= maxattempts {
color.Red("[%v] Stopping token %v [Max server rejoin attempts]", time.Now().Format("15:04:05"), instances[i].Token)
break
}
err := instances[i].Invite(invite)
if err != nil {
color.Red("[%v] Error while joining server: %v", time.Now().Format("15:04:05"), err)
instances[i].Rejoin++
instances[i].Retry++
continue
}
}
Expand Down Expand Up @@ -624,6 +624,13 @@ func Options() {
failed = append(failed, member)
color.Red("[%v] Token %v is being rate limited. Sleeping for 10 seconds", time.Now().Format("15:04:05"), instances[i].Token)
time.Sleep(10 * time.Second)
} else if resp.StatusCode == 400 && strings.Contains(string(body), "captcha") {
color.Red("[%v] Token %v Captcha was attempted to solve but appeared again", time.Now().Format("15:04:05"), instances[i].Token)
instances[i].Retry++
if instances[i].Retry >= cfg.CaptchaSettings.MaxCaptcha {
color.Red("[%v] Stopping token %v max captcha solves reached", time.Now().Format("15:04:05"), instances[i].Token)
break
}
} else {
failedCount++
failed = append(failed, member)
Expand Down
112 changes: 109 additions & 3 deletions utilities/captcha.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import (
"fmt"
"io/ioutil"
"net/http"
"net/url"
"strconv"
"strings"
"time"
Expand All @@ -17,10 +18,12 @@ func (in *Instance) SolveCaptcha(sitekey string, cookie string, rqData string, r
switch true {
case Contains([]string{"capmonster.cloud", "anti-captcha.com", "anycaptcha.com"}, in.Config.CaptchaSettings.CaptchaAPI):
return in.SolveCaptchaCapmonster(sitekey, cookie, rqData)
case Contains([]string{"rucaptcha.com", "azcaptcha.com", "solvecaptcha.com", "2captcha.com"}, in.Config.CaptchaSettings.CaptchaAPI):
case Contains([]string{"rucaptcha.com", "azcaptcha.com", "solvecaptcha.com"}, in.Config.CaptchaSettings.CaptchaAPI):
return in.SolveCaptchaRucaptcha(sitekey, rqData, rqToken)
case in.Config.CaptchaSettings.CaptchaAPI == "deathbycaptcha.com":
return in.SolveCaptchaDeathByCaptcha(sitekey)
case in.Config.CaptchaSettings.CaptchaAPI == "2captcha.com":
return in.twoCaptcha(sitekey, rqData)
default:
return "", fmt.Errorf("unsupported captcha api: %s", in.Config.CaptchaSettings.CaptchaAPI)
}
Expand All @@ -37,7 +40,7 @@ func (in *Instance) SolveCaptchaCapmonster(sitekey string, cookies string, rqdat
WebsiteURL: "https://discord.com/channels/@me",
WebsiteKey: sitekey,
Cookies: cookies,
UserAgent: Useragent,
UserAgent: UserAgent,
Data: rqdata,
},
}
Expand Down Expand Up @@ -69,7 +72,7 @@ func (in *Instance) SolveCaptchaCapmonster(sitekey string, cookies string, rqdat
Type: "HCaptchaTask",
WebsiteURL: "https://discord.com/channels/@me",
WebsiteKey: sitekey,
UserAgent: Useragent,
UserAgent: UserAgent,
ProxyType: in.Config.ProxySettings.ProxyProtocol,
ProxyAddress: address,
ProxyPort: port,
Expand Down Expand Up @@ -391,3 +394,106 @@ func (in *Instance) SolveCaptchaRucaptcha(sitekey string, rqData string, rqToken
}
return "", fmt.Errorf("max retries exceeded")
}

type twoCaptchaSubmitResponse struct {
Status int `json:"status"`
Request string `json:"request"`
}

func (in *Instance) twoCaptcha(sitekey, rqdata string) (string, error) {
var solvedKey string
inEndpoint := "https://2captcha.com/in.php"
inURL, err := url.Parse(inEndpoint)
if err != nil {
return solvedKey, fmt.Errorf("error while parsing url %v", err)
}
q := inURL.Query()
if in.Config.CaptchaSettings.ClientKey == "" {
return solvedKey, fmt.Errorf("client key is empty")
}
q.Set("key", in.Config.CaptchaSettings.ClientKey)
q.Set("method", "hcaptcha")
q.Set("sitekey", sitekey)
// Page URL same as referer in headers
q.Set("pageurl", "https://discord.com/channels/@me")
q.Set("userAgent", UserAgent)
q.Set("json", "1")
q.Set("soft_id", "3359")
if rqdata != "" {
q.Set("data", rqdata)
}
if in.Config.ProxySettings.ProxyForCaptcha {
q.Set("proxy", in.Proxy)
q.Set("proxytype", in.Config.ProxySettings.ProxyProtocol)
}
inURL.RawQuery = q.Encode()
inEndpoint = inURL.String()
req, err := http.NewRequest(http.MethodGet, inEndpoint, nil)
if err != nil {
return solvedKey, fmt.Errorf("error creating request [%v]", err)
}
resp, err := http.DefaultClient.Do(req)
if err != nil {
return solvedKey, fmt.Errorf("error sending request [%v]", err)
}
defer resp.Body.Close()
body, err := ioutil.ReadAll(resp.Body)
if err != nil {
return solvedKey, fmt.Errorf("error reading response [%v]", err)
}
var inResponse twoCaptchaSubmitResponse
err = json.Unmarshal(body, &inResponse)
if err != nil {
return solvedKey, fmt.Errorf("error unmarshalling response [%v]", err)
}
if inResponse.Status != 1 {
return solvedKey, fmt.Errorf("error %v", inResponse.Request)
}
outEndpoint := "https://2captcha.com/res.php"
outURL, err := url.Parse(outEndpoint)
if err != nil {
return solvedKey, fmt.Errorf("error while parsing url %v", err)
}
q = outURL.Query()
q.Set("key", in.Config.CaptchaSettings.ClientKey)
q.Set("action", "get")
q.Set("id", inResponse.Request)
q.Set("json", "1")
outURL.RawQuery = q.Encode()
outEndpoint = outURL.String()
req, err = http.NewRequest(http.MethodGet, outEndpoint, nil)
if err != nil {
return solvedKey, fmt.Errorf("error creating request [%v]", err)
}
time.Sleep(10 * time.Second)
now := time.Now()
for {
if time.Since(now) > time.Duration(in.Config.CaptchaSettings.Timeout)*time.Second {
return solvedKey, fmt.Errorf("captcha response from 2captcha timedout")
}
resp, err := http.DefaultClient.Do(req)
if err != nil {
return solvedKey, fmt.Errorf("error sending request [%v]", err)
}
defer resp.Body.Close()
body, err := ioutil.ReadAll(resp.Body)
if err != nil {
return solvedKey, fmt.Errorf("error reading response [%v]", err)
}
var outResponse twoCaptchaSubmitResponse
err = json.Unmarshal(body, &outResponse)
if err != nil {
return solvedKey, fmt.Errorf("error unmarshalling response [%v]", err)
}
if outResponse.Request == "CAPCHA_NOT_READY" {
time.Sleep(5 * time.Second)
continue
} else if strings.Contains(string(body), "ERROR") {
return solvedKey, fmt.Errorf("error %v", outResponse.Request)
} else {
solvedKey = outResponse.Request
break
}
}
return solvedKey, nil
}
47 changes: 38 additions & 9 deletions utilities/direct_messages.go
Original file line number Diff line number Diff line change
Expand Up @@ -223,7 +223,14 @@ func (in *Instance) OpenChannel(recepientUID string) (string, error) {

return channelSnowflake.ID, nil
}
type captchaDetected struct {
CaptchaKey []string `json:"captcha_key"`
Sitekey string `json:"captcha_sitekey"`
Service string `json:"captcha_service"`
RqData string `json:"captcha_rqdata"`
RqToken string `json:"captcha_rqtoken"`

}
// Inputs the Channel snowflake and sends them the message; outputs the response code for error handling.
func (in *Instance) SendMessage(channelSnowflake string, memberid string) (http.Response, error) {
// Sending a random message incase there are multiple.
Expand All @@ -240,7 +247,6 @@ func (in *Instance) SendMessage(channelSnowflake string, memberid string) (http.
"tts": false,
"nonce": Snowflake(),
})

if err != nil {
return http.Response{}, fmt.Errorf("error while marshalling message %v %v ", index, err)
}
Expand All @@ -267,20 +273,43 @@ func (in *Instance) SendMessage(channelSnowflake string, memberid string) (http.
return http.Response{}, fmt.Errorf("error while getting send message response %v", err)
}
if res.StatusCode == 400 {
msgid, err := in.greet(channelSnowflake, cookie, fingerprint)
body, err := ioutil.ReadAll(res.Body)
if err != nil {
return http.Response{}, fmt.Errorf("error while reading body %v", err)
}
if strings.Contains(string(body), "captcha") {
color.Yellow("[%v] Captcha detected %v Solving", time.Now().Format("15:04:05"), in.Token)
}
if in.Config.CaptchaSettings.ClientKey == "" {
return http.Response{}, fmt.Errorf("captcha detected but no client key set")
}
var captchaDetect captchaDetected
err = json.Unmarshal(body, &captchaDetect)
if err != nil {
return http.Response{}, fmt.Errorf("error while unmarshalling captcha %v", err)
}
solved, err := in.SolveCaptcha(captchaDetect.Sitekey, cookie,captchaDetect.RqData, captchaDetect.RqToken)
if err != nil {
return http.Response{}, fmt.Errorf("error while solving captcha %v", err)
}
body, err = json.Marshal(&map[string]interface{}{
"content": x,
"tts": false,
"nonce": Snowflake(),
"captcha_key": solved,
"captcha_rqtoken": captchaDetect.RqToken,
})
if err != nil {
return http.Response{}, fmt.Errorf("error while opening DM %v", err)
return http.Response{}, fmt.Errorf("error while marshalling message %v %v ", index, err)
}
resp, err := in.SendMessage(channelSnowflake, memberid)
req, err = http.NewRequest("POST", url, strings.NewReader(string(body)))
if err != nil {
return http.Response{}, fmt.Errorf("error while sending message %v", err)
return http.Response{}, fmt.Errorf("error while making request to send message %v", err)
}
err = in.ungreet(channelSnowflake, cookie, fingerprint, msgid)
res, err = in.Client.Do(in.SendMessageHeaders(req, cookie, fingerprint, channelSnowflake))
if err != nil {
return http.Response{}, fmt.Errorf("error while opening DM %v", err)
return http.Response{}, fmt.Errorf("error while getting send message response %v", err)
}
in.Count++
return resp, nil
}
in.Count++
return *res, nil
Expand Down
8 changes: 5 additions & 3 deletions utilities/extra.go
Original file line number Diff line number Diff line change
Expand Up @@ -209,17 +209,21 @@ func Bypass(client *http.Client, serverid string, token string, invite string) e

type invitePayload struct {
CaptchaKey string `json:"captcha_key,omitempty"`
RqToken string `json:"captcha_rqtoken,omitempty"`
}

func (in *Instance) Invite(Code string) error {
var solvedKey string
var payload invitePayload
for i := 0; i < in.Config.OtherSettings.MaxInvite; i++ {
var rqData string
var rqToken string
for i := 0; i < in.Config.CaptchaSettings.MaxCaptcha; i++ {
if solvedKey == "" || in.Config.CaptchaSettings.CaptchaAPI == "" {
payload = invitePayload{}
} else {
payload = invitePayload{
CaptchaKey: solvedKey,
RqToken: rqToken,
}
}
payload, err := json.Marshal(payload)
Expand Down Expand Up @@ -269,8 +273,6 @@ func (in *Instance) Invite(Code string) error {
continue
}
cap := resp["captcha_sitekey"].(string)
var rqData string
var rqToken string
if strings.Contains(string(body), "captcha_rqdata") {
rqData = resp["captcha_rqdata"].(string)
}
Expand Down
3 changes: 2 additions & 1 deletion utilities/files.go
Original file line number Diff line number Diff line change
Expand Up @@ -228,10 +228,11 @@ type ScraperSettings struct {
type CaptchaSettings struct {
ClientKey string `yaml:"captcha_api_key"`
CaptchaAPI string `yaml:"captcha_api"`
Timeout int `yaml:"max_captcha_wait"`
MaxCaptcha int `yaml:"max_captcha_retry"`
}

type OtherSettings struct {
MaxInvite int `yaml:"max_attempt_invite_rejoin"`
DisableKL bool `yaml:"disable_keep_alives"`
}

Expand Down
2 changes: 1 addition & 1 deletion utilities/instance.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ type Instance struct {
LastCount int
Members []User
AllMembers []User
Rejoin int
Retry int
ScrapeCount int
ID string
Receiver bool
Expand Down
6 changes: 3 additions & 3 deletions utilities/invite.go
Original file line number Diff line number Diff line change
Expand Up @@ -73,12 +73,12 @@ func (in *Instance) Inviter(invitationCode string, mode int, cookie string, fing
contextProperties = generateXContext(channelID, channelType, guildID)
}
site = fmt.Sprintf(`https://ptb.discord.com/api/v10/invites/%v`, invitationCode)
if in.Config.OtherSettings.MaxInvite < 2 {
in.Config.OtherSettings.MaxInvite = 2
if in.Config.CaptchaSettings.MaxCaptcha < 2 {
in.Config.CaptchaSettings.MaxCaptcha = 2
}
var captchaKey string
var req *http.Request
for i := 0; i < in.Config.OtherSettings.MaxInvite; i++ {
for i := 0; i < in.Config.CaptchaSettings.MaxCaptcha; i++ {
if captchaKey == "" {
req, err = http.NewRequest(http.MethodPost, site, strings.NewReader(`{}`))
} else {
Expand Down

0 comments on commit 2e2504f

Please sign in to comment.