proxy-cheap-client 1.0.1
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 +7 -0
- data/LICENSE +21 -0
- data/README.md +166 -0
- data/lib/proxy-cheap-client.rb +4 -0
- data/lib/proxy_cheap_client/client.rb +132 -0
- data/lib/proxy_cheap_client/errors.rb +18 -0
- data/lib/proxy_cheap_client/models/balance.rb +17 -0
- data/lib/proxy_cheap_client/models/base.rb +87 -0
- data/lib/proxy_cheap_client/models/configuration.rb +20 -0
- data/lib/proxy_cheap_client/models/order.rb +57 -0
- data/lib/proxy_cheap_client/models/proxy.rb +124 -0
- data/lib/proxy_cheap_client/version.rb +3 -0
- metadata +83 -0
checksums.yaml
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
---
|
|
2
|
+
SHA256:
|
|
3
|
+
metadata.gz: 72af370a7a949355facabddfef0d1bf5ec5221303ce4314e287f66cb96b1750c
|
|
4
|
+
data.tar.gz: bd3e0d5c6cc1bfd9adbf66abe2e01dc4fd0e2156fd0fe3c3f5544692effdf7a5
|
|
5
|
+
SHA512:
|
|
6
|
+
metadata.gz: 1f51ba931aa10bfe72a7604c6681b3c63812053353ba01a6056c8854aba7904237506faea69ac0ac3739798e87bfa6284848733125fbb376e9f1d16f009b212d
|
|
7
|
+
data.tar.gz: 1f01a397a39b39380014d66bddcdf4289d508b23cb5adbce4557e39bae33745959ef43b6cb9ce96169b6d6242b485dc28c2ba79116163ee7b510d2fac5580d6a
|
data/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2025 MassProspecting
|
|
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,166 @@
|
|
|
1
|
+
# proxy-cheap-client
|
|
2
|
+
|
|
3
|
+
Ruby client for the Proxy-Cheap.com API.
|
|
4
|
+
|
|
5
|
+
[](https://rubygems.org/gems/proxy-cheap-client) [](./LICENSE.txt)
|
|
6
|
+
|
|
7
|
+
## Features
|
|
8
|
+
|
|
9
|
+
* Retrieve account balance
|
|
10
|
+
* List proxies
|
|
11
|
+
* Enable/disable auto-extend on proxies
|
|
12
|
+
* Order new residential proxies
|
|
13
|
+
|
|
14
|
+
## Requirements
|
|
15
|
+
|
|
16
|
+
* Ruby 2.7+
|
|
17
|
+
* Internet access to Proxy-Cheap.com API
|
|
18
|
+
* API key and API secret from Proxy-Cheap.com
|
|
19
|
+
|
|
20
|
+
## Installation
|
|
21
|
+
|
|
22
|
+
Install from RubyGems:
|
|
23
|
+
|
|
24
|
+
```bash
|
|
25
|
+
gem install proxy-cheap-client
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
Or add to your `Gemfile`:
|
|
29
|
+
|
|
30
|
+
```ruby
|
|
31
|
+
gem "proxy-cheap-client"
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
Then run:
|
|
35
|
+
|
|
36
|
+
```bash
|
|
37
|
+
bundle install
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
## Configuration
|
|
41
|
+
|
|
42
|
+
The client requires both an API key and API secret.
|
|
43
|
+
|
|
44
|
+
You have to pass them explicitly when initializing the client:
|
|
45
|
+
|
|
46
|
+
```ruby
|
|
47
|
+
client = ProxyCheapClient::Client.new(
|
|
48
|
+
api_key: "your_api_key_here",
|
|
49
|
+
api_secret: "your_api_secret_here"
|
|
50
|
+
)
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
## Usage Example
|
|
54
|
+
|
|
55
|
+
```ruby
|
|
56
|
+
require "proxy_cheap_client"
|
|
57
|
+
|
|
58
|
+
client = ProxyCheapClient::Client.new(
|
|
59
|
+
api_key: "your_api_key_here",
|
|
60
|
+
api_secret: "your_api_secret_here"
|
|
61
|
+
)
|
|
62
|
+
|
|
63
|
+
# 1. Get balance
|
|
64
|
+
balance = client.balance
|
|
65
|
+
puts "Balance: #{balance.amount} #{balance.currency}"
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
## Load Proxies
|
|
69
|
+
|
|
70
|
+
```ruby
|
|
71
|
+
proxies = client.proxies
|
|
72
|
+
proxies.each do |p|
|
|
73
|
+
puts "Proxy #{p.id}: #{p.ip}:#{p.port}, auto_extend=#{p.auto_extend}"
|
|
74
|
+
end
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
## Load Specific Proxy
|
|
78
|
+
|
|
79
|
+
```ruby
|
|
80
|
+
proxy = ProxyCheapClient::Proxy.load(12345)
|
|
81
|
+
puts "Proxy details: #{proxy.to_h}"
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
## Enable auto-extend for a proxy
|
|
85
|
+
|
|
86
|
+
```ruby
|
|
87
|
+
proxy.enable_auto_extend
|
|
88
|
+
puts "Auto-extend enabled"
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
## Disable auto-extend
|
|
92
|
+
|
|
93
|
+
```ruby
|
|
94
|
+
proxy.disable_auto_extend
|
|
95
|
+
puts "Auto-extend disabled"
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
## Supported Countries
|
|
99
|
+
|
|
100
|
+
```ruby
|
|
101
|
+
arr = client.countries
|
|
102
|
+
puts "Supported Countries: #{arr}"
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
## Order Residential Proxies
|
|
106
|
+
|
|
107
|
+
```ruby
|
|
108
|
+
order = client.order_static_residential_proxy(
|
|
109
|
+
country: "US",
|
|
110
|
+
proxyProtocol: "HTTP",
|
|
111
|
+
authenticationType: "USERNAME_PASSWORD"
|
|
112
|
+
)
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
## Order Proxies
|
|
116
|
+
|
|
117
|
+
```ruby
|
|
118
|
+
order.proxies
|
|
119
|
+
```
|
|
120
|
+
|
|
121
|
+
## Error Handling
|
|
122
|
+
|
|
123
|
+
The client raises specific exceptions for failure modes:
|
|
124
|
+
|
|
125
|
+
* `ProxyCheapClient::AuthenticationError` - API key or secret is missing or invalid (HTTP 401)
|
|
126
|
+
* `ProxyCheapClient::NotFoundError` - Resource does not exist (HTTP 404)
|
|
127
|
+
* `ProxyCheapClient::BadRequestError` - Invalid request parameters (HTTP 400)
|
|
128
|
+
* `ProxyCheapClient::ServerError` - Server-side error (HTTP 5xx)
|
|
129
|
+
* `ProxyCheapClient::RequestError` - General request failure
|
|
130
|
+
* `ProxyCheapClient::InvalidResponseError` - Malformed or non-JSON response
|
|
131
|
+
|
|
132
|
+
All errors inherit from `ProxyCheapClient::Error` and include `status_code` and `response_body` attributes for debugging:
|
|
133
|
+
|
|
134
|
+
```ruby
|
|
135
|
+
begin
|
|
136
|
+
client.balance
|
|
137
|
+
rescue ProxyCheapClient::NotFoundError => e
|
|
138
|
+
puts "Not found: #{e.message}"
|
|
139
|
+
puts "Status: #{e.status_code}"
|
|
140
|
+
puts "Body: #{e.response_body}"
|
|
141
|
+
rescue ProxyCheapClient::Error => e
|
|
142
|
+
puts "API failure: #{e.message}"
|
|
143
|
+
end
|
|
144
|
+
```
|
|
145
|
+
|
|
146
|
+
## Publishing
|
|
147
|
+
|
|
148
|
+
Build and push to RubyGems:
|
|
149
|
+
|
|
150
|
+
```bash
|
|
151
|
+
gem build proxy-cheap-client.gemspec
|
|
152
|
+
gem push proxy-cheap-client-#{ProxyCheapClient::VERSION}.gem
|
|
153
|
+
```
|
|
154
|
+
|
|
155
|
+
Make sure you have an account on RubyGems.org and appropriate credentials configured in `~/.gem/credentials`.
|
|
156
|
+
|
|
157
|
+
## Contributing
|
|
158
|
+
|
|
159
|
+
1. Fork the repository.
|
|
160
|
+
2. Create a feature branch: `git checkout -b feature/xyz`
|
|
161
|
+
3. Run tests (add test suite if missing).
|
|
162
|
+
4. Open a pull request with a clear description.
|
|
163
|
+
|
|
164
|
+
## License
|
|
165
|
+
|
|
166
|
+
This project is licensed under the MIT License. See `LICENSE.txt` for details.
|
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
require "faraday"
|
|
2
|
+
require "json"
|
|
3
|
+
require_relative "version"
|
|
4
|
+
require_relative "errors"
|
|
5
|
+
require_relative "models/base"
|
|
6
|
+
require_relative "models/balance"
|
|
7
|
+
require_relative "models/proxy"
|
|
8
|
+
require_relative "models/order"
|
|
9
|
+
require_relative "models/configuration"
|
|
10
|
+
|
|
11
|
+
module ProxyCheapClient
|
|
12
|
+
class Client < Base
|
|
13
|
+
API_BASE = "https://api.proxy-cheap.com"
|
|
14
|
+
|
|
15
|
+
# Initialize the client with API credentials.
|
|
16
|
+
# @param api_key [String] API key (or set PROXY_CHEAP_API_KEY env var)
|
|
17
|
+
# @param api_secret [String] API secret (or set PROXY_CHEAP_API_SECRET env var)
|
|
18
|
+
# @param timeout [Integer] Request timeout in seconds (default: 10)
|
|
19
|
+
def initialize(
|
|
20
|
+
api_key:,
|
|
21
|
+
api_secret:,
|
|
22
|
+
timeout: 10
|
|
23
|
+
)
|
|
24
|
+
@api_key = api_key
|
|
25
|
+
@api_secret = api_secret
|
|
26
|
+
|
|
27
|
+
raise AuthenticationError, "API key missing" unless @api_key && !@api_key.strip.empty?
|
|
28
|
+
raise AuthenticationError, "API secret missing" unless @api_secret && !@api_secret.strip.empty?
|
|
29
|
+
|
|
30
|
+
@conn = Faraday.new(url: API_BASE) do |f|
|
|
31
|
+
f.request :json
|
|
32
|
+
f.response :raise_error
|
|
33
|
+
f.options.timeout = timeout
|
|
34
|
+
f.headers["X-Api-Key"] = @api_key
|
|
35
|
+
f.headers["X-Api-Secret"] = @api_secret
|
|
36
|
+
f.headers["Content-Type"] = "application/json"
|
|
37
|
+
f.adapter Faraday.default_adapter
|
|
38
|
+
end
|
|
39
|
+
rescue Faraday::Error => e
|
|
40
|
+
raise RequestError, "Connection failure: #{e.message}"
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
def conn
|
|
44
|
+
@conn
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
# retrieve the array of countries with number of available proxies per country
|
|
48
|
+
def countries
|
|
49
|
+
config = self.configuration(
|
|
50
|
+
networkType: "RESIDENTIAL_STATIC",
|
|
51
|
+
ipVersion: "IPv4",
|
|
52
|
+
country: "US",
|
|
53
|
+
proxyProtocol: "HTTP",
|
|
54
|
+
authenticationType: "USERNAME_PASSWORD",
|
|
55
|
+
quantity: 1
|
|
56
|
+
)
|
|
57
|
+
config.data["supportedCountries"]
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
# Get user balance.
|
|
61
|
+
# @return [Balance]
|
|
62
|
+
def balance
|
|
63
|
+
resp = request(:get, "account/balance")
|
|
64
|
+
Balance.new(resp, self)
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
# Get all user proxies.
|
|
68
|
+
# @return [Array<Proxy>]
|
|
69
|
+
def proxies
|
|
70
|
+
resp = request(:get, "proxies")
|
|
71
|
+
# API may return proxies directly as an array or wrapped in a "data" key
|
|
72
|
+
proxy_list = resp.is_a?(Hash) && resp.key?("data") ? resp["data"] : resp
|
|
73
|
+
proxy_list = resp.is_a?(Hash) && resp.key?("proxies") ? resp["proxies"] : resp
|
|
74
|
+
Array(proxy_list).map { |p| Proxy.new(p, self) }
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
# Convenience method to order a static residential proxy.
|
|
78
|
+
# @param params [Hash] Order parameters
|
|
79
|
+
# @option params [String] :country 2 letter country code (required)
|
|
80
|
+
# @option params [String] :isp ISP id
|
|
81
|
+
# @option params [String] :proxyProtocol HTTP, HTTPS, SOCKS5 (default: HTTP)
|
|
82
|
+
# @option params [String] :authenticationType USERNAME_PASSWORD or IP_WHITELIST
|
|
83
|
+
# @option params [Integer] :quantity number of proxies (default: 1)
|
|
84
|
+
# @return [Order]
|
|
85
|
+
def order_static_residential_proxy(params = {})
|
|
86
|
+
order_params = {
|
|
87
|
+
networkType: "RESIDENTIAL_STATIC",
|
|
88
|
+
ipVersion: "IPv4"
|
|
89
|
+
}.merge(params)
|
|
90
|
+
order(order_params)
|
|
91
|
+
end # def order_static_residential_proxy
|
|
92
|
+
|
|
93
|
+
private
|
|
94
|
+
|
|
95
|
+
# Get configuration/pricing according to filter parameters.
|
|
96
|
+
# Use this to preview an order before executing it.
|
|
97
|
+
# @param params [Hash] Configuration parameters
|
|
98
|
+
# @option params [String] :networkType MOBILE, DATACENTER, RESIDENTIAL, RESIDENTIAL_STATIC
|
|
99
|
+
# @option params [String] :ipVersion IPv4, IPv6, MOBILE
|
|
100
|
+
# @option params [String] :country 2 letter country code
|
|
101
|
+
# @option params [String] :region 2 letter region code
|
|
102
|
+
# @option params [String] :isp ISP id
|
|
103
|
+
# @option params [String] :proxyProtocol HTTP, HTTPS, SOCKS5
|
|
104
|
+
# @option params [String] :authenticationType USERNAME_PASSWORD, IP_WHITELIST
|
|
105
|
+
# @option params [Array<String>] :ipWhitelist whitelisted IPs
|
|
106
|
+
# @option params [String] :package package id
|
|
107
|
+
# @option params [Integer] :quantity proxies amount
|
|
108
|
+
# @option params [String] :couponCode order promo code
|
|
109
|
+
# @option params [Integer] :bandwidth amount in GB
|
|
110
|
+
# @option params [Boolean] :isAutoExtendEnabled enables auto extend
|
|
111
|
+
# @option params [Integer] :autoExtendBandwidth how many GB to extend
|
|
112
|
+
# @return [Configuration]
|
|
113
|
+
def configuration(params = {})
|
|
114
|
+
resp = request(:post, "order/configuration", params)
|
|
115
|
+
Configuration.new(resp, self)
|
|
116
|
+
end # def configuration
|
|
117
|
+
|
|
118
|
+
# Execute an order with the given configuration.
|
|
119
|
+
# Use `configuration` first to preview the order.
|
|
120
|
+
# @param params [Hash] Same parameters as `configuration`
|
|
121
|
+
# @return [Order]
|
|
122
|
+
def order(params = {})
|
|
123
|
+
resp = request(:post, "order/execute", params)
|
|
124
|
+
# {"id"=>"019aebab-7635-79e1-ba1f-95118dc12695",
|
|
125
|
+
# "periodInMonths"=>"1",
|
|
126
|
+
# "totalPrice"=>"3.39"}
|
|
127
|
+
|
|
128
|
+
# Return order model (API returns order descriptor including id/status)
|
|
129
|
+
Order.new(resp, self)
|
|
130
|
+
end # def order
|
|
131
|
+
end # class Client
|
|
132
|
+
end # module ProxyCheapClient
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
module ProxyCheapClient
|
|
2
|
+
class Error < StandardError
|
|
3
|
+
attr_reader :status_code, :response_body
|
|
4
|
+
|
|
5
|
+
def initialize(message = nil, status_code: nil, response_body: nil)
|
|
6
|
+
@status_code = status_code
|
|
7
|
+
@response_body = response_body
|
|
8
|
+
super(message)
|
|
9
|
+
end
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
class AuthenticationError < Error; end
|
|
13
|
+
class RequestError < Error; end
|
|
14
|
+
class NotFoundError < Error; end
|
|
15
|
+
class BadRequestError < Error; end
|
|
16
|
+
class ServerError < Error; end
|
|
17
|
+
class InvalidResponseError < Error; end
|
|
18
|
+
end
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
module ProxyCheapClient
|
|
2
|
+
#module Models
|
|
3
|
+
class Balance < Base
|
|
4
|
+
attr_reader :amount, :currency, :conn
|
|
5
|
+
|
|
6
|
+
def initialize(attrs = {}, client)
|
|
7
|
+
@amount = attrs["balance"] || attrs["amount"]
|
|
8
|
+
@currency = attrs["currency"] || "USD"
|
|
9
|
+
@conn = client.conn
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
def to_h
|
|
13
|
+
{ amount: amount, currency: currency }
|
|
14
|
+
end
|
|
15
|
+
end
|
|
16
|
+
#end
|
|
17
|
+
end
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
module ProxyCheapClient
|
|
2
|
+
class Base
|
|
3
|
+
# Make an HTTP request to the API.
|
|
4
|
+
# @note Some API endpoints (whitelist, extend-period, buy-bandwidth) use GET
|
|
5
|
+
# requests with JSON body, which is non-standard but matches the official API behavior.
|
|
6
|
+
def request(method, path, body = nil)
|
|
7
|
+
response = case method.to_s.downcase.to_sym
|
|
8
|
+
when :get
|
|
9
|
+
if body
|
|
10
|
+
@conn.get(path) { |r| r.body = body.to_json }
|
|
11
|
+
else
|
|
12
|
+
@conn.get(path)
|
|
13
|
+
end
|
|
14
|
+
when :post
|
|
15
|
+
@conn.post(path) { |r| r.body = body.to_json if body }
|
|
16
|
+
when :patch
|
|
17
|
+
@conn.patch(path) { |r| r.body = body.to_json if body }
|
|
18
|
+
else
|
|
19
|
+
raise RequestError, "Unsupported HTTP method: #{method}"
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
parse_response(response)
|
|
23
|
+
rescue Faraday::UnauthorizedError => e
|
|
24
|
+
raise AuthenticationError.new(
|
|
25
|
+
"Unauthorized - check API key and secret",
|
|
26
|
+
status_code: 401,
|
|
27
|
+
response_body: extract_error_body(e)
|
|
28
|
+
)
|
|
29
|
+
rescue Faraday::ResourceNotFound => e
|
|
30
|
+
raise NotFoundError.new(
|
|
31
|
+
"Resource not found: #{path}",
|
|
32
|
+
status_code: 404,
|
|
33
|
+
response_body: extract_error_body(e)
|
|
34
|
+
)
|
|
35
|
+
rescue Faraday::BadRequestError => e
|
|
36
|
+
raise BadRequestError.new(
|
|
37
|
+
"Bad request: #{extract_error_message(e)}",
|
|
38
|
+
status_code: 400,
|
|
39
|
+
response_body: extract_error_body(e)
|
|
40
|
+
)
|
|
41
|
+
rescue Faraday::ServerError => e
|
|
42
|
+
raise ServerError.new(
|
|
43
|
+
"Server error: #{extract_error_message(e)}",
|
|
44
|
+
status_code: e.response&.dig(:status) || 500,
|
|
45
|
+
response_body: extract_error_body(e)
|
|
46
|
+
)
|
|
47
|
+
rescue Faraday::ClientError => e
|
|
48
|
+
raise RequestError.new(
|
|
49
|
+
"API request failed: #{extract_error_message(e)}",
|
|
50
|
+
status_code: e.response&.dig(:status),
|
|
51
|
+
response_body: extract_error_body(e)
|
|
52
|
+
)
|
|
53
|
+
end # request
|
|
54
|
+
|
|
55
|
+
def extract_error_body(error)
|
|
56
|
+
error.response&.dig(:body)
|
|
57
|
+
end # extract_error_body
|
|
58
|
+
|
|
59
|
+
def extract_error_message(error)
|
|
60
|
+
body = extract_error_body(error)
|
|
61
|
+
return error.message unless body
|
|
62
|
+
|
|
63
|
+
begin
|
|
64
|
+
parsed = JSON.parse(body)
|
|
65
|
+
parsed["message"] || parsed["error"] || body
|
|
66
|
+
rescue JSON::ParserError
|
|
67
|
+
body
|
|
68
|
+
end
|
|
69
|
+
end # extract_error_message
|
|
70
|
+
|
|
71
|
+
def parse_response(response)
|
|
72
|
+
return {} if response.body.nil? || response.body.empty?
|
|
73
|
+
|
|
74
|
+
begin
|
|
75
|
+
data = JSON.parse(response.body)
|
|
76
|
+
rescue JSON::ParserError
|
|
77
|
+
raise InvalidResponseError, "Response is not valid JSON"
|
|
78
|
+
end
|
|
79
|
+
|
|
80
|
+
if response.status >= 400
|
|
81
|
+
raise RequestError, "API error: #{data}"
|
|
82
|
+
end
|
|
83
|
+
|
|
84
|
+
data
|
|
85
|
+
end # parse_response
|
|
86
|
+
end # class Base
|
|
87
|
+
end # module ProxyCheapClient
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
module ProxyCheapClient
|
|
2
|
+
#module Models
|
|
3
|
+
class Configuration < Base
|
|
4
|
+
attr_reader :data, :price, :currency, :packages, :available, :conn
|
|
5
|
+
|
|
6
|
+
def initialize(attrs = {}, client)
|
|
7
|
+
@data = attrs
|
|
8
|
+
@price = attrs["price"] || attrs["totalPrice"]
|
|
9
|
+
@currency = attrs["currency"] || "USD"
|
|
10
|
+
@packages = attrs["packages"]
|
|
11
|
+
@available = attrs["available"]
|
|
12
|
+
@conn = client.conn
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
def to_h
|
|
16
|
+
data
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
#end
|
|
20
|
+
end
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
module ProxyCheapClient
|
|
2
|
+
#module Models
|
|
3
|
+
class Order < Base
|
|
4
|
+
attr_reader :data,
|
|
5
|
+
:id,
|
|
6
|
+
#:status,
|
|
7
|
+
#:proxies,
|
|
8
|
+
#:created_at,
|
|
9
|
+
:total_price,
|
|
10
|
+
#:currency,
|
|
11
|
+
:conn
|
|
12
|
+
|
|
13
|
+
def initialize(attrs = {}, client)
|
|
14
|
+
@data = attrs
|
|
15
|
+
@id = attrs["id"] || attrs["orderId"]
|
|
16
|
+
#@status = attrs["status"]
|
|
17
|
+
#@proxies = attrs["proxies"]
|
|
18
|
+
#@created_at = attrs["createdAt"] || attrs["created_at"]
|
|
19
|
+
@total_price = attrs["totalPrice"] || attrs["total_price"]
|
|
20
|
+
#@currency = attrs["currency"]
|
|
21
|
+
@conn = client.conn
|
|
22
|
+
end # initialize
|
|
23
|
+
|
|
24
|
+
def to_h
|
|
25
|
+
{
|
|
26
|
+
id: id,
|
|
27
|
+
#status: status,
|
|
28
|
+
#proxies: proxies,
|
|
29
|
+
#created_at: created_at,
|
|
30
|
+
total_price: total_price,
|
|
31
|
+
#currency: currency
|
|
32
|
+
}
|
|
33
|
+
end # to_h
|
|
34
|
+
|
|
35
|
+
# Get proxies of an order
|
|
36
|
+
# @param order_id [String] Order ID
|
|
37
|
+
# @return [Order]
|
|
38
|
+
def proxies()
|
|
39
|
+
order_id = self.id
|
|
40
|
+
resp = request(:get, "orders/#{order_id}/proxies")
|
|
41
|
+
|
|
42
|
+
# The response may be an array or wrapped in a key (e.g. "proxies" or "data").
|
|
43
|
+
proxy_data = if resp.is_a?(Hash) && resp.key?("proxies")
|
|
44
|
+
resp["proxies"]
|
|
45
|
+
elsif resp.is_a?(Hash) && resp.key?("data")
|
|
46
|
+
resp["data"]
|
|
47
|
+
else
|
|
48
|
+
resp
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
Array(proxy_data).map { |p| ProxyCheapClient::Proxy.new(p) }
|
|
52
|
+
end # proxies
|
|
53
|
+
|
|
54
|
+
|
|
55
|
+
end # class
|
|
56
|
+
#end # module
|
|
57
|
+
end # module
|
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
module ProxyCheapClient
|
|
2
|
+
#module Models
|
|
3
|
+
class Proxy < Base
|
|
4
|
+
attr_reader :data, :id, :ip, :port, :type, :expires_at,
|
|
5
|
+
#:auto_renew, :auto_extend,
|
|
6
|
+
:country, :isp, :username, :password, :protocol, :bandwidth_limit,
|
|
7
|
+
:bandwidth_used, :status, :conn
|
|
8
|
+
|
|
9
|
+
def initialize(attrs = {}, client)
|
|
10
|
+
@data = attrs
|
|
11
|
+
@id = attrs["id"]
|
|
12
|
+
@ip = attrs["ip"] || attrs["host"] || (attrs["connection"] && attrs["connection"]['connectIp'])
|
|
13
|
+
@port = attrs["port"] || (attrs["connection"] && attrs["connection"]['httpPort'])
|
|
14
|
+
@type = attrs["type"] || attrs["networkType"] || (attrs["connection"] && attrs["connection"]['ipVersion'])
|
|
15
|
+
@expires_at = attrs["expiresAt"] || attrs["expires_at"]
|
|
16
|
+
#@auto_renew = attrs["autoRenew"] || attrs["auto_renew"] || attrs["isAutoExtendEnabled"]
|
|
17
|
+
#@auto_extend = attrs["isAutoExtendEnabled"] || attrs["autoExtend"]
|
|
18
|
+
@country = attrs["countryCode"]
|
|
19
|
+
isp = attrs["metadata"]['ispName']
|
|
20
|
+
@username = attrs["username"] || (attrs["authentication"] && attrs["authentication"]['username'])
|
|
21
|
+
@password = attrs["password"] || (attrs["authentication"] && attrs["authentication"]['password'])
|
|
22
|
+
@protocol = attrs["protocol"] || attrs["proxyProtocol"] || attrs["proxyType"]
|
|
23
|
+
@bandwidth_limit = attrs["bandwidthLimit"] || attrs["bandwidth_limit"] || (attrs["bandwidth"] && attrs["bandwidth"]['total'])
|
|
24
|
+
@bandwidth_used = attrs["bandwidthUsed"] || attrs["bandwidth_used"] || (attrs["bandwidth"] && attrs["bandwidth"]['used'])
|
|
25
|
+
@status = attrs["status"]
|
|
26
|
+
@conn = client.conn
|
|
27
|
+
end # def initialize
|
|
28
|
+
|
|
29
|
+
def to_h
|
|
30
|
+
{
|
|
31
|
+
id: id,
|
|
32
|
+
ip: ip,
|
|
33
|
+
port: port,
|
|
34
|
+
type: type,
|
|
35
|
+
expires_at: expires_at,
|
|
36
|
+
#auto_renew: auto_renew,
|
|
37
|
+
#auto_extend: auto_extend,
|
|
38
|
+
country: country,
|
|
39
|
+
isp: isp,
|
|
40
|
+
username: username,
|
|
41
|
+
password: password,
|
|
42
|
+
protocol: protocol,
|
|
43
|
+
bandwidth_limit: bandwidth_limit,
|
|
44
|
+
bandwidth_used: bandwidth_used,
|
|
45
|
+
status: status
|
|
46
|
+
}
|
|
47
|
+
end # to_h
|
|
48
|
+
=begin
|
|
49
|
+
# Change whitelisted IPs for a proxy.
|
|
50
|
+
# @note The official API uses GET with request body for this operation.
|
|
51
|
+
# @param proxy_id [Integer] Proxy ID
|
|
52
|
+
# @param ips [Array<String>] List of IPs to whitelist
|
|
53
|
+
# @return [Hash] API response
|
|
54
|
+
def whitelist(proxy_id, ips = [])
|
|
55
|
+
request(:get, "proxies/#{proxy_id}/whitelist-ip", { ips: ips })
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
# Extend a proxy period.
|
|
59
|
+
# @note The official API uses GET with request body for this operation.
|
|
60
|
+
# @param proxy_id [Integer] Proxy ID
|
|
61
|
+
# @param months [Integer] Number of months to extend (minimum 1)
|
|
62
|
+
# @return [Hash] API response
|
|
63
|
+
def extend_period(proxy_id, months)
|
|
64
|
+
raise ArgumentError, "You must extend for at least 1 month" unless months && months >= 1
|
|
65
|
+
request(:get, "proxies/#{proxy_id}/extend-period", { periodInMonths: months })
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
# Buy additional bandwidth for a proxy.
|
|
69
|
+
# @note The official API uses GET with request body for this operation.
|
|
70
|
+
# @param proxy_id [Integer] Proxy ID
|
|
71
|
+
# @param bandwidth_gb [Integer] Amount of bandwidth in GB (minimum 1)
|
|
72
|
+
# @return [Hash] API response
|
|
73
|
+
def buy_bandwidth(proxy_id, bandwidth_gb)
|
|
74
|
+
raise ArgumentError, "You must buy at least 1 GB" unless bandwidth_gb && bandwidth_gb >= 1
|
|
75
|
+
request(:get, "proxies/#{proxy_id}/buy-bandwidth", { bandwidth: bandwidth_gb })
|
|
76
|
+
end
|
|
77
|
+
=end
|
|
78
|
+
# Get info on a specific proxy.
|
|
79
|
+
# @param proxy_id [Integer] Proxy ID
|
|
80
|
+
# @return [Proxy]
|
|
81
|
+
def self.load(proxy_id)
|
|
82
|
+
resp = request(:get, "proxies/#{proxy_id}")
|
|
83
|
+
Proxy.new(resp)
|
|
84
|
+
end # proxy
|
|
85
|
+
=begin
|
|
86
|
+
def auto_extend?
|
|
87
|
+
!!@data.dig("autoExtend", "isEnabled")
|
|
88
|
+
end
|
|
89
|
+
|
|
90
|
+
def get_name
|
|
91
|
+
@data["name"]
|
|
92
|
+
end
|
|
93
|
+
|
|
94
|
+
def set_name(name)
|
|
95
|
+
response = @conn.patch("proxies/#{@data['id']}") do |req|
|
|
96
|
+
req.headers['Content-Type'] = 'application/json'
|
|
97
|
+
req.body = { name: name }.to_json
|
|
98
|
+
end
|
|
99
|
+
if response.success?
|
|
100
|
+
@data["name"] = name
|
|
101
|
+
else
|
|
102
|
+
raise "Failed to set proxy name (HTTP #{response.status})"
|
|
103
|
+
end
|
|
104
|
+
end
|
|
105
|
+
=end
|
|
106
|
+
# Enable auto-extend for a proxy.
|
|
107
|
+
# @param proxy_id [Integer] Proxy ID
|
|
108
|
+
# @return [Hash] API response
|
|
109
|
+
def enable_auto_extend()
|
|
110
|
+
proxy_id = self.id
|
|
111
|
+
request(:post, "proxies/#{proxy_id}/auto-extend/enable")
|
|
112
|
+
end # enable_auto_extend
|
|
113
|
+
|
|
114
|
+
# Disable auto-extend for a proxy.
|
|
115
|
+
# @param proxy_id [Integer] Proxy ID
|
|
116
|
+
# @return [Hash] API response
|
|
117
|
+
def disable_auto_extend()
|
|
118
|
+
proxy_id = self.id
|
|
119
|
+
request(:post, "proxies/#{proxy_id}/auto-extend/disable")
|
|
120
|
+
end # disable_auto_extend
|
|
121
|
+
|
|
122
|
+
end # Proxy
|
|
123
|
+
#end # Model
|
|
124
|
+
end
|
metadata
ADDED
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
|
2
|
+
name: proxy-cheap-client
|
|
3
|
+
version: !ruby/object:Gem::Version
|
|
4
|
+
version: 1.0.1
|
|
5
|
+
platform: ruby
|
|
6
|
+
authors:
|
|
7
|
+
- Leandro Sardi
|
|
8
|
+
autorequire:
|
|
9
|
+
bindir: exe
|
|
10
|
+
cert_chain: []
|
|
11
|
+
date: 2025-12-10 00:00:00.000000000 Z
|
|
12
|
+
dependencies:
|
|
13
|
+
- !ruby/object:Gem::Dependency
|
|
14
|
+
name: faraday
|
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
|
16
|
+
requirements:
|
|
17
|
+
- - "~>"
|
|
18
|
+
- !ruby/object:Gem::Version
|
|
19
|
+
version: 2.3.0
|
|
20
|
+
type: :runtime
|
|
21
|
+
prerelease: false
|
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
23
|
+
requirements:
|
|
24
|
+
- - "~>"
|
|
25
|
+
- !ruby/object:Gem::Version
|
|
26
|
+
version: 2.3.0
|
|
27
|
+
- !ruby/object:Gem::Dependency
|
|
28
|
+
name: json
|
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
|
30
|
+
requirements:
|
|
31
|
+
- - ">="
|
|
32
|
+
- !ruby/object:Gem::Version
|
|
33
|
+
version: '0'
|
|
34
|
+
type: :runtime
|
|
35
|
+
prerelease: false
|
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
37
|
+
requirements:
|
|
38
|
+
- - ">="
|
|
39
|
+
- !ruby/object:Gem::Version
|
|
40
|
+
version: '0'
|
|
41
|
+
description: Manage balance, proxies, auto-extend, and order proxies via the Proxy-Cheap
|
|
42
|
+
API.
|
|
43
|
+
email:
|
|
44
|
+
- leandro@massprospecting.com
|
|
45
|
+
executables: []
|
|
46
|
+
extensions: []
|
|
47
|
+
extra_rdoc_files: []
|
|
48
|
+
files:
|
|
49
|
+
- LICENSE
|
|
50
|
+
- README.md
|
|
51
|
+
- lib/proxy-cheap-client.rb
|
|
52
|
+
- lib/proxy_cheap_client/client.rb
|
|
53
|
+
- lib/proxy_cheap_client/errors.rb
|
|
54
|
+
- lib/proxy_cheap_client/models/balance.rb
|
|
55
|
+
- lib/proxy_cheap_client/models/base.rb
|
|
56
|
+
- lib/proxy_cheap_client/models/configuration.rb
|
|
57
|
+
- lib/proxy_cheap_client/models/order.rb
|
|
58
|
+
- lib/proxy_cheap_client/models/proxy.rb
|
|
59
|
+
- lib/proxy_cheap_client/version.rb
|
|
60
|
+
homepage: https://github.com/massprospecting/proxy-cheap-client
|
|
61
|
+
licenses:
|
|
62
|
+
- MIT
|
|
63
|
+
metadata: {}
|
|
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: '2.7'
|
|
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.3.7
|
|
80
|
+
signing_key:
|
|
81
|
+
specification_version: 4
|
|
82
|
+
summary: Ruby client for Proxy-Cheap.com API
|
|
83
|
+
test_files: []
|