capture_page 1.0.0 → 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 +4 -4
  2. data/README.md +13 -0
  3. data/lib/capture.rb +83 -0
  4. metadata +1 -1
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 4c0646db848b7f2468b5115caed1a2101188c86f3e2fe7764eb84cb155003df1
4
- data.tar.gz: 77cb86e03ebaa2692a1c186ed9b3540c8e6600ab49f74732eb1bf9e732a23358
3
+ metadata.gz: 3217118ed9497ccaaff219c4b5fd9345320790d99d88d252d14f363921832a4e
4
+ data.tar.gz: 3c96668a060f2771e1210583c2e9aeb65fbf75b9d508d5f475c1fc4098cdd6f7
5
5
  SHA512:
6
- metadata.gz: f7070bb1dc03c587dd27f0f76dc7bb4a22fdd694707ef3026069248d11a72648c2c77139cfcf0c463423593695388415965c12066850dea2141f22c40e445909
7
- data.tar.gz: 7aa49e640f95945ad92e9de26319769b76b148c518333d636fb0957330e846b0ec50de4b8bf2c9166be8bc819d1d6f35b6399a41c0bf3349fd3143a34b29e383
6
+ metadata.gz: cf1928267a630bc2f2e26cf5fc2db0443c995e523641f86ab8816038a52a5d388c0093973d3a33f97dbf5c509e6f054575cea7b2b5658575d46e96245338a1a8
7
+ data.tar.gz: 3b62f1f2d90d24af537bd56fa87a1303eef91bb3e3e5355e2ac7a2e4027d797d46220ebf6a8c9bad97bde5440ac234497ce5e7b1441d651e5f94741bd109a1da
data/README.md CHANGED
@@ -34,6 +34,7 @@ puts image_url
34
34
  - **Content Extraction**: Extract HTML and text content from web pages
35
35
  - **Metadata Extraction**: Get page metadata (title, description, og tags, etc.)
36
36
  - **Animated GIFs**: Create animated GIFs of page interactions
37
+ - **Browser Sessions**: Create stateful browser sessions and run actions
37
38
  - **Zero Dependencies**: Uses only Ruby standard library
38
39
 
39
40
  ## Usage
@@ -132,6 +133,18 @@ gif_data = client.fetch_animated("https://example.com")
132
133
  File.binwrite("animation.gif", gif_data)
133
134
  ```
134
135
 
136
+ ### Browser Sessions
137
+
138
+ ```ruby
139
+ session = client.create_session("maxTtlSeconds" => 300)
140
+ session_id = session["session"]["id"]
141
+
142
+ client.execute_action(session_id, "goto", "url" => "https://example.com")
143
+ screenshot = client.execute_action(session_id, "screenshot", "fullPage" => true)
144
+
145
+ client.close_session(session_id)
146
+ ```
147
+
135
148
  ## Configuration Options
136
149
 
137
150
  ### Constructor Options
data/lib/capture.rb CHANGED
@@ -5,6 +5,17 @@ require "net/http"
5
5
  require "uri"
6
6
  require "json"
7
7
 
8
+ class CaptureSessionsError < StandardError
9
+ attr_reader :status, :body
10
+
11
+ def initialize(status, body)
12
+ message = body.is_a?(Hash) && body["error"].is_a?(String) ? body["error"] : "Capture Sessions API request failed with status #{status}"
13
+ super(message)
14
+ @status = status
15
+ @body = body
16
+ end
17
+ end
18
+
8
19
  class Capture
9
20
  API_URL = "https://cdn.capture.page"
10
21
  EDGE_URL = "https://edge.capture.page"
@@ -59,6 +70,28 @@ class Capture
59
70
  fetch_binary(build_animated_url(url, options))
60
71
  end
61
72
 
73
+ def create_session(options = {})
74
+ options = options.nil? ? {} : options
75
+ raise TypeError, "options must be a Hash" unless options.is_a?(Hash)
76
+
77
+ sessions_request("", :post, options)
78
+ end
79
+
80
+ def get_session(session_id)
81
+ sessions_request("/#{escape_path(session_id)}", :get)
82
+ end
83
+
84
+ def close_session(session_id)
85
+ sessions_request("/#{escape_path(session_id)}", :delete)
86
+ end
87
+
88
+ def execute_action(session_id, action_type, payload = {})
89
+ payload = payload.nil? ? {} : payload
90
+ raise TypeError, "payload must be a Hash" unless payload.is_a?(Hash)
91
+
92
+ sessions_request("/#{escape_path(session_id)}/actions", :post, "type" => action_type, "payload" => payload)
93
+ end
94
+
62
95
  private
63
96
 
64
97
  def build_url(url, request_type, options)
@@ -110,4 +143,54 @@ class Capture
110
143
 
111
144
  JSON.parse(response.body)
112
145
  end
146
+
147
+ def sessions_bearer_token
148
+ raise TypeError, "key and secret must be strings" unless @key.is_a?(String) && @secret.is_a?(String)
149
+ raise ArgumentError, "Key and Secret is required" if @key.empty? || @secret.empty?
150
+
151
+ ["#{@key}:#{@secret}"].pack("m0")
152
+ end
153
+
154
+ def session_url(path = "")
155
+ "#{EDGE_URL}/v1/sessions#{path}"
156
+ end
157
+
158
+ def sessions_request(path, method, body = nil)
159
+ uri = URI.parse(session_url(path))
160
+ request = case method
161
+ when :post then Net::HTTP::Post.new(uri)
162
+ when :get then Net::HTTP::Get.new(uri)
163
+ when :delete then Net::HTTP::Delete.new(uri)
164
+ else raise ArgumentError, "unsupported sessions request method"
165
+ end
166
+
167
+ request["Authorization"] = "Bearer #{sessions_bearer_token}"
168
+ unless body.nil?
169
+ request["Content-Type"] = "application/json"
170
+ request.body = JSON.generate(body)
171
+ end
172
+
173
+ response = Net::HTTP.start(uri.hostname, uri.port, use_ssl: uri.scheme == "https") do |http|
174
+ http.request(request)
175
+ end
176
+ response_body = parse_json_response(response.body)
177
+
178
+ raise CaptureSessionsError.new(response.code.to_i, response_body) unless response.is_a?(Net::HTTPSuccess)
179
+
180
+ response_body
181
+ end
182
+
183
+ def parse_json_response(body)
184
+ return {} if body.nil? || body.empty?
185
+
186
+ JSON.parse(body)
187
+ rescue JSON::ParserError
188
+ {}
189
+ end
190
+
191
+ def escape_path(value)
192
+ raise ArgumentError, "session_id is required" if value.nil? || value.to_s.empty?
193
+
194
+ URI.encode_www_form_component(value.to_s)
195
+ end
113
196
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: capture_page
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.0
4
+ version: 1.1.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Capture Team