antybrowser 1.0.2

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.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: bff1786517371078f55df991001650e41795454d0ccb713a31f5c15b2c6593f2
4
+ data.tar.gz: a8b2ec507cad13e46b9b0d98d8e852f0c654df29fea8a304aa591bd63e3d4dfd
5
+ SHA512:
6
+ metadata.gz: 1cf03735d5855d81f3cd41cf09cb9430ead5baa7dd4e82795925eaed08dcf87c863bf817f31594ba2d3bef1f675f4171c22aa341572c4b83e1c4c549ab3954a6
7
+ data.tar.gz: '0955ef66029fabebe6f54b1c921f94d20d8416db28bf31aa412315ab0842b98a4d9a62326879ed5487f64b145dbf6fd61826fa2c0c4c443e00f556656dfc7740'
data/LICENSE.txt ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 AntyBrowser
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,69 @@
1
+ # antybrowser (Ruby)
2
+
3
+ Official Antybrowser Ruby SDK for the Local API.
4
+
5
+ ## Installation
6
+
7
+ ```bash
8
+ gem install antybrowser
9
+ ```
10
+
11
+ Or in your Gemfile:
12
+
13
+ ```ruby
14
+ gem "antybrowser"
15
+ ```
16
+
17
+ ## Quick Start
18
+
19
+ ```ruby
20
+ require "antybrowser"
21
+
22
+ client = Antybrowser::Client.new("your_api_key")
23
+
24
+ # List profiles
25
+ profiles = client.get_profiles
26
+ profiles.each { |p| puts "#{p.name} (status: #{p.status})" }
27
+
28
+ # Start a profile
29
+ result = client.start_profile(123)
30
+ puts "Debug port: #{result['data']['debugPort']}"
31
+ ```
32
+
33
+ ## Configuration
34
+
35
+ ```ruby
36
+ # Default (port 5173)
37
+ client = Antybrowser::Client.new("my_key")
38
+
39
+ # Custom port
40
+ client = Antybrowser::Client.new("my_key", port: 5174)
41
+
42
+ # Custom base URL
43
+ client = Antybrowser::Client.new("my_key", base_url: "http://10.0.0.5:5173")
44
+ ```
45
+
46
+ ## Error Handling
47
+
48
+ ```ruby
49
+ begin
50
+ client.get_profiles
51
+ rescue Antybrowser::AntybrowserError => e
52
+ puts "Status: #{e.status_code}"
53
+ puts "Body: #{e.response_body}"
54
+ end
55
+ ```
56
+
57
+ ## Available Methods
58
+
59
+ - `get_status` / `get_settings` / `get_sync_status` / `refresh_sync`
60
+ - `get_profiles` / `create_profile` / `update_profile` / `delete_profile`
61
+ - `start_profile` / `stop_profile` / `duplicate_profile`
62
+ - `get_automations` / `run_automation`
63
+ - `get_groups` / `create_group` / `update_group` / `delete_group`
64
+ - `get_proxies` / `create_proxy` / `check_proxy` / `check_proxies_bulk` / `delete_proxy`
65
+ - `get_extensions` / `delete_extension` / `get_profile_extensions` / `set_profile_extensions`
66
+
67
+ ## License
68
+
69
+ MIT
@@ -0,0 +1,27 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "lib/antybrowser/version"
4
+
5
+ Gem::Specification.new do |spec|
6
+ spec.name = "antybrowser"
7
+ spec.version = Antybrowser::VERSION
8
+ spec.authors = ["Antybrowser Team"]
9
+ spec.email = ["support@antybrowser.com"]
10
+
11
+ spec.summary = "Official Antybrowser SDK — Ruby client for the Local API"
12
+ spec.description = "Manage browser profiles, proxies, automations, groups, and extensions via the Antybrowser Local API."
13
+ spec.homepage = "https://antybrowser.com"
14
+ spec.license = "MIT"
15
+
16
+ spec.required_ruby_version = ">= 3.0"
17
+
18
+ spec.metadata["homepage_uri"] = spec.homepage
19
+ spec.metadata["source_code_uri"] = "https://github.com/antybrowser/SDK"
20
+ spec.metadata["changelog_uri"] = "https://github.com/antybrowser/SDK/blob/main/ruby/CHANGELOG.md"
21
+
22
+ spec.files = Dir["lib/**/*.rb"] + ["antybrowser.gemspec", "README.md", "LICENSE.txt"]
23
+ spec.require_paths = ["lib"]
24
+
25
+ spec.add_development_dependency "rake", "~> 13.0"
26
+ spec.add_development_dependency "rspec", "~> 3.0"
27
+ end
@@ -0,0 +1,211 @@
1
+ require "net/http"
2
+ require "json"
3
+ require "uri"
4
+
5
+ module Antybrowser
6
+ class Client
7
+ attr_reader :base_url, :api_key
8
+
9
+ def initialize(api_key, port: 5173, base_url: nil, timeout: 30)
10
+ @api_key = api_key
11
+ @base_url = base_url || "http://127.0.0.1:#{port}"
12
+ @timeout = timeout
13
+ end
14
+
15
+ # ─── System ──────────────────────────────────────────────────────────
16
+
17
+ def get_status
18
+ get("/api/status")
19
+ end
20
+
21
+ def get_settings
22
+ get("/api/settings")
23
+ end
24
+
25
+ def get_sync_status
26
+ SyncStatus.new(get("/api/sync/status"))
27
+ end
28
+
29
+ def refresh_sync(profile_id: nil)
30
+ body = profile_id ? { "profileId" => profile_id } : {}
31
+ post("/api/sync/refresh", body)
32
+ end
33
+
34
+ # ─── Profiles ────────────────────────────────────────────────────────
35
+
36
+ def get_profiles
37
+ get("/api/profiles").map { |d| Profile.new(d) }
38
+ end
39
+
40
+ def create_profile(data)
41
+ Profile.new(post("/api/profiles", data))
42
+ end
43
+
44
+ def update_profile(id, data)
45
+ Profile.new(put("/api/profiles/#{id}", data))
46
+ end
47
+
48
+ def delete_profile(id)
49
+ delete("/api/profiles/#{id}")
50
+ end
51
+
52
+ def start_profile(id)
53
+ result = post("/api/profiles/#{id}/start", {})
54
+ { "success" => result["success"], "data" => result["data"] }
55
+ end
56
+
57
+ def stop_profile(id)
58
+ post("/api/profiles/#{id}/stop", {})
59
+ end
60
+
61
+ def duplicate_profile(id, name: nil, directory_name: nil)
62
+ body = {}
63
+ body["name"] = name if name
64
+ body["directoryName"] = directory_name if directory_name
65
+ Profile.new(post("/api/profiles/#{id}/duplicate", body))
66
+ end
67
+
68
+ # ─── Automations ─────────────────────────────────────────────────────
69
+
70
+ def get_automations
71
+ get("/api/automations").map { |d| Automation.new(d) }
72
+ end
73
+
74
+ def run_automation(id, profile_id:, delete_cookies: nil, variables: nil)
75
+ body = { "profileId" => profile_id }
76
+ body["deleteCookies"] = delete_cookies unless delete_cookies.nil?
77
+ body["variables"] = variables if variables
78
+ result = post("/api/automations/#{id}/run", body)
79
+ {
80
+ "success" => result["success"],
81
+ "message" => result["message"],
82
+ "variables" => result["variables"],
83
+ }
84
+ end
85
+
86
+ # ─── Groups ──────────────────────────────────────────────────────────
87
+
88
+ def get_groups
89
+ get("/api/groups").map { |d| Group.new(d) }
90
+ end
91
+
92
+ def create_group(data)
93
+ Group.new(post("/api/groups", data))
94
+ end
95
+
96
+ def update_group(id, data)
97
+ Group.new(put("/api/groups/#{id}", data))
98
+ end
99
+
100
+ def delete_group(id)
101
+ delete("/api/groups/#{id}")
102
+ end
103
+
104
+ # ─── Proxies ─────────────────────────────────────────────────────────
105
+
106
+ def get_proxies
107
+ get("/api/proxies").map { |d| Proxy.new(d) }
108
+ end
109
+
110
+ def create_proxy(data)
111
+ Proxy.new(post("/api/proxies", data))
112
+ end
113
+
114
+ def check_proxy(host:, port:, username: nil, password: nil, type: nil)
115
+ body = { "host" => host, "port" => port }
116
+ body["username"] = username if username
117
+ body["password"] = password if password
118
+ body["type"] = type if type
119
+ ProxyCheckResult.new(post("/api/proxies/check", body))
120
+ end
121
+
122
+ def check_proxies_bulk(proxies)
123
+ result = post("/api/proxies/check-bulk", { "proxies" => proxies })
124
+ results = result["results"] || result
125
+ results.map { |r| ProxyCheckResult.new(r) }
126
+ end
127
+
128
+ def delete_proxy(id)
129
+ delete("/api/proxies/#{id}")
130
+ end
131
+
132
+ # ─── Extensions ──────────────────────────────────────────────────────
133
+
134
+ def get_extensions
135
+ get("/api/extensions").map { |d| Extension.new(d) }
136
+ end
137
+
138
+ def delete_extension(id)
139
+ delete("/api/extensions/#{id}")
140
+ end
141
+
142
+ def get_profile_extensions(profile_id, details: false)
143
+ get("/api/profiles/#{profile_id}/extensions?details=#{details}").map { |d| Extension.new(d) }
144
+ end
145
+
146
+ def set_profile_extensions(profile_id, extension_ids)
147
+ post("/api/profiles/#{profile_id}/extensions", { "extensionIds" => extension_ids })
148
+ end
149
+
150
+ private
151
+
152
+ def get(path)
153
+ request(Net::HTTP::Get, path)
154
+ end
155
+
156
+ def post(path, body)
157
+ request(Net::HTTP::Post, path, body)
158
+ end
159
+
160
+ def put(path, body)
161
+ request(Net::HTTP::Put, path, body)
162
+ end
163
+
164
+ def delete(path)
165
+ request(Net::HTTP::Delete, path)
166
+ end
167
+
168
+ def request(method_class, path, body = nil)
169
+ uri = URI.parse("#{@base_url}#{path}")
170
+ http = Net::HTTP.new(uri.host, uri.port)
171
+ http.open_timeout = @timeout
172
+ http.read_timeout = @timeout
173
+
174
+ req = method_class.new(uri.request_uri)
175
+ req["x-api-key"] = @api_key
176
+ req["Content-Type"] = "application/json"
177
+ req.body = body.to_json if body
178
+
179
+ begin
180
+ response = http.request(req)
181
+ rescue StandardError => e
182
+ raise AntybrowserError, "Failed to connect to Antybrowser: #{e.message}"
183
+ end
184
+
185
+ parse_response(response)
186
+ end
187
+
188
+ def parse_response(response)
189
+ code = response.code.to_i
190
+ body = response.body || ""
191
+
192
+ if code < 200 || code >= 300
193
+ raise AntybrowserError.new(
194
+ "API request failed with status #{code}",
195
+ status_code: code,
196
+ response_body: body
197
+ )
198
+ end
199
+
200
+ return {} if body.strip.empty?
201
+
202
+ JSON.parse(body)
203
+ rescue JSON::ParserError
204
+ raise AntybrowserError.new(
205
+ "Invalid JSON response from API",
206
+ status_code: response.code.to_i,
207
+ response_body: body
208
+ )
209
+ end
210
+ end
211
+ end
@@ -0,0 +1,11 @@
1
+ module Antybrowser
2
+ class AntybrowserError < StandardError
3
+ attr_reader :status_code, :response_body
4
+
5
+ def initialize(message, status_code: nil, response_body: nil)
6
+ super(message)
7
+ @status_code = status_code
8
+ @response_body = response_body
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,136 @@
1
+ module Antybrowser
2
+ class Profile
3
+ attr_reader :id, :name, :directory_name, :group_id, :proxy_id,
4
+ :browser_type, :browser_version, :os_fingerprint,
5
+ :screen_resolution, :language, :accept_language, :timezone,
6
+ :use_fingerprint, :fingerprint_id, :restore_session,
7
+ :low_bandwidth, :notes, :status, :debug_port,
8
+ :created_at, :updated_at, :extra
9
+
10
+ def initialize(data)
11
+ @id = data["id"]
12
+ @name = data["name"]
13
+ @directory_name = data["directoryName"]
14
+ @group_id = data["groupId"]
15
+ @proxy_id = data["proxyId"]
16
+ @browser_type = data["browserType"]
17
+ @browser_version = data["browserVersion"]
18
+ @os_fingerprint = data["osFingerprint"]
19
+ @screen_resolution = data["screenResolution"]
20
+ @language = data["language"]
21
+ @accept_language = data["acceptLanguage"]
22
+ @timezone = data["timezone"]
23
+ @use_fingerprint = data["useFingerprint"]
24
+ @fingerprint_id = data["fingerprintId"]
25
+ @restore_session = data["restoreSession"]
26
+ @low_bandwidth = data["lowBandwidth"]
27
+ @notes = data["notes"]
28
+ @status = data["status"]
29
+ @debug_port = data["debugPort"]
30
+ @created_at = data["createdAt"]
31
+ @updated_at = data["updatedAt"]
32
+ @extra = data.reject { |k, _v| known_keys.include?(k) }
33
+ end
34
+
35
+ private
36
+
37
+ def known_keys
38
+ %w[id name directoryName groupId proxyId browserType browserVersion
39
+ osFingerprint screenResolution language acceptLanguage timezone
40
+ useFingerprint fingerprintId restoreSession lowBandwidth notes
41
+ status debugPort createdAt updatedAt]
42
+ end
43
+ end
44
+
45
+ class Proxy
46
+ attr_reader :id, :name, :type, :host, :port, :username, :status,
47
+ :country_code, :ip, :country, :timezone, :asn, :isp, :extra
48
+
49
+ def initialize(data)
50
+ @id = data["id"]
51
+ @name = data["name"]
52
+ @type = data["type"]
53
+ @host = data["host"]
54
+ @port = data["port"]
55
+ @username = data["username"]
56
+ @status = data["status"]
57
+ @country_code = data["countryCode"]
58
+ @ip = data["ip"]
59
+ @country = data["country"]
60
+ @timezone = data["timezone"]
61
+ @asn = data["asn"]
62
+ @isp = data["isp"]
63
+ @extra = data.reject { |k, _v| known_keys.include?(k) }
64
+ end
65
+
66
+ private
67
+
68
+ def known_keys
69
+ %w[id name type host port username status countryCode ip country timezone asn isp]
70
+ end
71
+ end
72
+
73
+ class Group
74
+ attr_reader :id, :name, :description, :color, :display_order, :created_at, :updated_at
75
+
76
+ def initialize(data)
77
+ @id = data["id"]
78
+ @name = data["name"]
79
+ @description = data["description"]
80
+ @color = data["color"]
81
+ @display_order = data["displayOrder"]
82
+ @created_at = data["createdAt"]
83
+ @updated_at = data["updatedAt"]
84
+ end
85
+ end
86
+
87
+ class Extension
88
+ attr_reader :id, :name, :path, :description, :icon, :created_at
89
+
90
+ def initialize(data)
91
+ @id = data["id"]
92
+ @name = data["name"]
93
+ @path = data["path"]
94
+ @description = data["description"]
95
+ @icon = data["icon"]
96
+ @created_at = data["createdAt"]
97
+ end
98
+ end
99
+
100
+ class Automation
101
+ attr_reader :id, :name, :description, :status, :last_run, :created_at, :updated_at
102
+
103
+ def initialize(data)
104
+ @id = data["id"]
105
+ @name = data["name"]
106
+ @description = data["description"]
107
+ @status = data["status"]
108
+ @last_run = data["lastRun"]
109
+ @created_at = data["createdAt"]
110
+ @updated_at = data["updatedAt"]
111
+ end
112
+ end
113
+
114
+ class SyncStatus
115
+ attr_reader :total, :completed, :is_syncing, :active, :errors, :progress
116
+
117
+ def initialize(data)
118
+ @total = data["total"] || 0
119
+ @completed = data["completed"] || 0
120
+ @is_syncing = data["isSyncing"] || false
121
+ @active = data["active"] || []
122
+ @errors = data["errors"] || {}
123
+ @progress = data["progress"] || {}
124
+ end
125
+ end
126
+
127
+ class ProxyCheckResult
128
+ attr_reader :success, :details, :error_message
129
+
130
+ def initialize(data)
131
+ @success = data["success"] || false
132
+ @details = data["details"]
133
+ @error_message = data["errorMessage"]
134
+ end
135
+ end
136
+ end
@@ -0,0 +1,3 @@
1
+ module Antybrowser
2
+ VERSION = "1.0.2"
3
+ end
@@ -0,0 +1,4 @@
1
+ require_relative "antybrowser/version"
2
+ require_relative "antybrowser/error"
3
+ require_relative "antybrowser/models"
4
+ require_relative "antybrowser/client"
metadata ADDED
@@ -0,0 +1,83 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: antybrowser
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.0.2
5
+ platform: ruby
6
+ authors:
7
+ - Antybrowser Team
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2026-09-06 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: rake
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '13.0'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '13.0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: rspec
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '3.0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '3.0'
41
+ description: Manage browser profiles, proxies, automations, groups, and extensions
42
+ via the Antybrowser Local API.
43
+ email:
44
+ - support@antybrowser.com
45
+ executables: []
46
+ extensions: []
47
+ extra_rdoc_files: []
48
+ files:
49
+ - LICENSE.txt
50
+ - README.md
51
+ - antybrowser.gemspec
52
+ - lib/antybrowser.rb
53
+ - lib/antybrowser/client.rb
54
+ - lib/antybrowser/error.rb
55
+ - lib/antybrowser/models.rb
56
+ - lib/antybrowser/version.rb
57
+ homepage: https://antybrowser.com
58
+ licenses:
59
+ - MIT
60
+ metadata:
61
+ homepage_uri: https://antybrowser.com
62
+ source_code_uri: https://github.com/antybrowser/SDK
63
+ changelog_uri: https://github.com/antybrowser/SDK/blob/main/ruby/CHANGELOG.md
64
+ post_install_message:
65
+ rdoc_options: []
66
+ require_paths:
67
+ - lib
68
+ required_ruby_version: !ruby/object:Gem::Requirement
69
+ requirements:
70
+ - - ">="
71
+ - !ruby/object:Gem::Version
72
+ version: '3.0'
73
+ required_rubygems_version: !ruby/object:Gem::Requirement
74
+ requirements:
75
+ - - ">="
76
+ - !ruby/object:Gem::Version
77
+ version: '0'
78
+ requirements: []
79
+ rubygems_version: 3.5.22
80
+ signing_key:
81
+ specification_version: 4
82
+ summary: Official Antybrowser SDK — Ruby client for the Local API
83
+ test_files: []