muaraicaptcha 1.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (4) hide show
  1. checksums.yaml +7 -0
  2. data/README.md +67 -0
  3. data/lib/muaraicaptcha.rb +136 -0
  4. metadata +48 -0
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 1030792ff79fdc91401c0d9b1f0d8e6454526158bb194abdba16709a3620d191
4
+ data.tar.gz: 6266c3710a1edc4c1d59d0dd66d9dd0cc315df945c30d0600ba303d963436128
5
+ SHA512:
6
+ metadata.gz: 983ea8895eb487ff6f9e0836e7f635c61ec9a6864bba1f6cac2ee441b6b36060eb8e127e6f96cf17bcc23e4cb67139ea9dcb4ac40603cb96e2d595ec6256a281
7
+ data.tar.gz: d5cf56bdc2eff3ab4868dbfe13f9d4d680e14f333601079d96d610c4265a0c00780dc2f96b0c38cd9038a7b812e71b71d06e848b691cb042954654e92ba6c789
data/README.md ADDED
@@ -0,0 +1,67 @@
1
+ <div align="center">
2
+
3
+ # MuaraiCaptcha — Ruby SDK
4
+
5
+ Official Ruby client for the [MuaraiCaptcha](https://muaraicaptcha.com) solving API.
6
+
7
+ [![Gem](https://img.shields.io/badge/gem-muaraicaptcha-CC342D?style=flat-square)](https://rubygems.org/gems/muaraicaptcha)
8
+ [![License](https://img.shields.io/badge/license-MIT-black?style=flat-square)](../../LICENSE)
9
+
10
+ </div>
11
+
12
+ Zero dependencies — standard library only (`net/http`).
13
+
14
+ ## Install
15
+
16
+ ```bash
17
+ gem install muaraicaptcha
18
+ ```
19
+
20
+ ## Quick start
21
+
22
+ ```ruby
23
+ require "muaraicaptcha"
24
+
25
+ client = MuaraiCaptcha::Client.new("YOUR_API_KEY")
26
+
27
+ solution = client.solve(
28
+ "type" => "TurnstileTaskProxyless",
29
+ "websiteURL" => "https://example.com",
30
+ "websiteKey" => "0x4AAAAAAA..."
31
+ )
32
+ puts solution["token"]
33
+ ```
34
+
35
+ ## API
36
+
37
+ ```ruby
38
+ client = MuaraiCaptcha::Client.new(client_key, base_url: "...", timeout: 30)
39
+
40
+ client.get_balance # => Float (USD)
41
+ client.create_task(task) # => Integer taskId
42
+ client.get_task_result(task_id) # => Hash solution, or nil while processing
43
+ client.report_incorrect(task_id) # auto-refund a bad solve
44
+ client.solve(task, poll_interval: 5, timeout: 180) # create + poll
45
+ ```
46
+
47
+ ## Error handling
48
+
49
+ ```ruby
50
+ begin
51
+ client.solve(task)
52
+ rescue MuaraiCaptcha::ApiError => e
53
+ puts "#{e.code}: #{e.description}" # e.g. ERROR_ZERO_BALANCE
54
+ rescue MuaraiCaptcha::TimeoutError
55
+ puts "gave up waiting"
56
+ end
57
+ ```
58
+
59
+ ## Documentation
60
+
61
+ - [Task types & parameters](../../docs/task-types.md)
62
+ - [Error codes](../../docs/error-codes.md)
63
+ - [Full API reference](../../docs/api-reference.md)
64
+
65
+ ## License
66
+
67
+ MIT © MuaraiCaptcha
@@ -0,0 +1,136 @@
1
+ # frozen_string_literal: true
2
+
3
+ # MuaraiCaptcha — official Ruby SDK.
4
+ #
5
+ # Solve reCAPTCHA, hCaptcha, Turnstile, FunCaptcha, image captchas and more
6
+ # through the MuaraiCaptcha API (https://muaraicaptcha.com).
7
+ #
8
+ # require "muaraicaptcha"
9
+ # client = MuaraiCaptcha::Client.new("YOUR_API_KEY")
10
+ # solution = client.solve("type" => "TurnstileTaskProxyless",
11
+ # "websiteURL" => "https://example.com",
12
+ # "websiteKey" => "0x4AAAAAAA...")
13
+ # puts solution["token"]
14
+
15
+ require "json"
16
+ require "net/http"
17
+ require "uri"
18
+
19
+ module MuaraiCaptcha
20
+ VERSION = "1.1.0"
21
+ DEFAULT_BASE_URL = "https://api.muaraicaptcha.com"
22
+
23
+ # Base error for the SDK.
24
+ class Error < StandardError; end
25
+
26
+ # Raised when the API returns a non-zero errorId.
27
+ class ApiError < Error
28
+ attr_reader :code, :description
29
+
30
+ def initialize(code, description)
31
+ @code = code
32
+ @description = description
33
+ super("#{code}: #{description}")
34
+ end
35
+ end
36
+
37
+ # Raised when a job does not resolve within the timeout.
38
+ class TimeoutError < Error; end
39
+
40
+ class Client
41
+ # @param client_key [String] API key from console.muaraicaptcha.com
42
+ # @param base_url [String] override the API base URL
43
+ # @param timeout [Numeric] per-request timeout in seconds
44
+ def initialize(client_key, base_url: DEFAULT_BASE_URL, timeout: 30)
45
+ raise Error, "client_key is required" if client_key.nil? || client_key.empty?
46
+
47
+ @client_key = client_key
48
+ @base_url = base_url.sub(%r{/+\z}, "")
49
+ @timeout = timeout
50
+ end
51
+
52
+ # @return [Float] account balance in USD
53
+ def get_balance
54
+ res = post("/v1/account/balance", "clientKey" => @client_key)
55
+ res.fetch("balance", 0).to_f
56
+ end
57
+
58
+ # @param task [Hash] task object with "type" + fields
59
+ # @return [Integer] jobId
60
+ def create_job(task)
61
+ res = post("/v1/job/create", "clientKey" => @client_key, "task" => task)
62
+ res.fetch("jobId").to_i
63
+ end
64
+
65
+ # Poll once. Returns the solution Hash when ready, or nil while processing.
66
+ # Raises ApiError if the job failed.
67
+ def get_job_result(job_id)
68
+ res = post("/v1/job/result", "clientKey" => @client_key, "jobId" => job_id)
69
+ case res["status"]
70
+ when "ready"
71
+ res.fetch("solution", {})
72
+ when "failed"
73
+ raise ApiError.new(
74
+ res.fetch("errorCode", "ERROR_CAPTCHA_UNSOLVABLE"),
75
+ res.fetch("errorDescription", "Job failed")
76
+ )
77
+ end
78
+ end
79
+
80
+ # Report a bad solution — the charge is refunded automatically.
81
+ def report_incorrect(job_id)
82
+ post("/v1/job/report", "clientKey" => @client_key, "jobId" => job_id, "correct" => false)
83
+ nil
84
+ end
85
+
86
+ # Create a job and poll until solved. Returns the solution Hash.
87
+ def solve(task, poll_interval: 5, timeout: 180)
88
+ job_id = create_job(task)
89
+ deadline = monotonic + timeout
90
+ sleep([poll_interval, 3].min)
91
+ while monotonic < deadline
92
+ solution = get_job_result(job_id)
93
+ return solution if solution
94
+ sleep(poll_interval)
95
+ end
96
+ raise TimeoutError, "job #{job_id} did not resolve within #{timeout}s"
97
+ end
98
+
99
+ # --- backward-compatible aliases (deprecated, kept for 1.0.x users) ---
100
+ alias create_task create_job
101
+ alias get_task_result get_job_result
102
+
103
+ private
104
+
105
+ def monotonic
106
+ Process.clock_gettime(Process::CLOCK_MONOTONIC)
107
+ end
108
+
109
+ def post(path, body)
110
+ uri = URI.parse("#{@base_url}#{path}")
111
+ http = Net::HTTP.new(uri.host, uri.port)
112
+ http.use_ssl = (uri.scheme == "https")
113
+ http.read_timeout = @timeout
114
+ http.open_timeout = @timeout
115
+
116
+ req = Net::HTTP::Post.new(uri.request_uri)
117
+ req["Content-Type"] = "application/json"
118
+ req["Accept"] = "application/json"
119
+ req["User-Agent"] = "muaraicaptcha-ruby/#{VERSION}"
120
+ req.body = JSON.generate(body)
121
+
122
+ res = http.request(req)
123
+ payload = JSON.parse(res.body)
124
+
125
+ if payload.is_a?(Hash) && payload["errorId"].to_i != 0
126
+ raise ApiError.new(
127
+ payload.fetch("errorCode", "ERROR_UNKNOWN"),
128
+ payload.fetch("errorDescription", "Unknown error")
129
+ )
130
+ end
131
+ payload
132
+ rescue JSON::ParserError
133
+ raise Error, "invalid JSON response (HTTP #{res&.code})"
134
+ end
135
+ end
136
+ end
metadata ADDED
@@ -0,0 +1,48 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: muaraicaptcha
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.1.0
5
+ platform: ruby
6
+ authors:
7
+ - MuaraiCaptcha
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2026-07-31 00:00:00.000000000 Z
12
+ dependencies: []
13
+ description: Solve reCAPTCHA, hCaptcha, Turnstile, FunCaptcha, image captchas and
14
+ more via MuaraiCaptcha.
15
+ email:
16
+ executables: []
17
+ extensions: []
18
+ extra_rdoc_files: []
19
+ files:
20
+ - README.md
21
+ - lib/muaraicaptcha.rb
22
+ homepage: https://muaraicaptcha.com
23
+ licenses:
24
+ - MIT
25
+ metadata:
26
+ source_code_uri: https://github.com/MuaraiCaptcha/MuaraiCaptcha
27
+ documentation_uri: https://github.com/MuaraiCaptcha/MuaraiCaptcha/tree/main/docs
28
+ github_repo: https://github.com/MuaraiCaptcha/MuaraiCaptcha
29
+ post_install_message:
30
+ rdoc_options: []
31
+ require_paths:
32
+ - lib
33
+ required_ruby_version: !ruby/object:Gem::Requirement
34
+ requirements:
35
+ - - ">="
36
+ - !ruby/object:Gem::Version
37
+ version: '2.7'
38
+ required_rubygems_version: !ruby/object:Gem::Requirement
39
+ requirements:
40
+ - - ">="
41
+ - !ruby/object:Gem::Version
42
+ version: '0'
43
+ requirements: []
44
+ rubygems_version: 3.4.19
45
+ signing_key:
46
+ specification_version: 4
47
+ summary: Official Ruby SDK for the MuaraiCaptcha solving API
48
+ test_files: []