copy_ai 0.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.
- checksums.yaml +7 -0
- data/CHANGELOG.md +6 -0
- data/MIT-LICENSE +22 -0
- data/README.md +145 -0
- data/Rakefile +34 -0
- data/bin/console +10 -0
- data/lib/copy_ai/authenticator.rb +15 -0
- data/lib/copy_ai/client.rb +72 -0
- data/lib/copy_ai/connection.rb +57 -0
- data/lib/copy_ai/errors/bad_gateway.rb +5 -0
- data/lib/copy_ai/errors/bad_request.rb +5 -0
- data/lib/copy_ai/errors/client_error.rb +5 -0
- data/lib/copy_ai/errors/connection_exception.rb +5 -0
- data/lib/copy_ai/errors/error.rb +3 -0
- data/lib/copy_ai/errors/forbidden.rb +5 -0
- data/lib/copy_ai/errors/gateway_timeout.rb +5 -0
- data/lib/copy_ai/errors/gone.rb +5 -0
- data/lib/copy_ai/errors/http_error.rb +41 -0
- data/lib/copy_ai/errors/internal_server_error.rb +5 -0
- data/lib/copy_ai/errors/network_error.rb +5 -0
- data/lib/copy_ai/errors/not_acceptable.rb +5 -0
- data/lib/copy_ai/errors/not_found.rb +5 -0
- data/lib/copy_ai/errors/payload_too_large.rb +5 -0
- data/lib/copy_ai/errors/server_error.rb +5 -0
- data/lib/copy_ai/errors/service_unavailable.rb +5 -0
- data/lib/copy_ai/errors/unauthorized.rb +5 -0
- data/lib/copy_ai/errors/unprocessable_entity.rb +5 -0
- data/lib/copy_ai/request_builder.rb +40 -0
- data/lib/copy_ai/response_parser.rb +59 -0
- data/lib/copy_ai/version.rb +3 -0
- data/lib/copy_ai/webhook.rb +30 -0
- data/lib/copy_ai.rb +2 -0
- metadata +100 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: d7dfa8e0173b3f8e9ff2c8faa3278493da38351a46b40577b4b52a2d87e5b0f4
|
4
|
+
data.tar.gz: 25e0c4672631e4cab8b6b0a1a25702db84a37f95458e44eb375714c205659e3a
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 8f17f32b94bc25eef3d9125693c1eaeb85c0c41bbff569530dd7ce06c537e9811864996b80a071efcb5abe39d9c54d7ae298443bc8aa45eab2bd16c43e91555d
|
7
|
+
data.tar.gz: 820c92832dc61a4488acbc64c888152c786cc6a1b5bc48ca917c11a1049f8b95929e9f89aced95bf6b4cb1d9433737dbc2ffbc150e51477cbd9329436f8489f5
|
data/CHANGELOG.md
ADDED
data/MIT-LICENSE
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
The MIT License (MIT)
|
2
|
+
|
3
|
+
Copyright Fernand Arioja
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
6
|
+
a copy of this software and associated documentation files (the
|
7
|
+
"Software"), to deal in the Software without restriction, including
|
8
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
9
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
10
|
+
permit persons to whom the Software is furnished to do so, subject to
|
11
|
+
the following conditions:
|
12
|
+
|
13
|
+
The above copyright notice and this permission notice shall be
|
14
|
+
included in all copies or substantial portions of the Software.
|
15
|
+
|
16
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
17
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
18
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
19
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
20
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
21
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
22
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,145 @@
|
|
1
|
+
# A [Ruby](https://www.ruby-lang.org) interface to the [Copy.ai Workflows API](https://docs.copy.ai/docs/getting-started)
|
2
|
+
|
3
|
+
## Installation
|
4
|
+
|
5
|
+
Install the gem and add to the application's Gemfile:
|
6
|
+
|
7
|
+
bundle add copy_ai
|
8
|
+
|
9
|
+
Or, to install directly:
|
10
|
+
|
11
|
+
gem install copy_ai
|
12
|
+
|
13
|
+
## Usage
|
14
|
+
|
15
|
+
First, obtain credentials from <https://docs.copy.ai/reference/authentication>.
|
16
|
+
|
17
|
+
```ruby
|
18
|
+
require "copy_ai"
|
19
|
+
|
20
|
+
copy_ai_credentials = {
|
21
|
+
api_key: "INSERT YOUR X API KEY HERE",
|
22
|
+
api_endpoint: "INSERT YOUR X API ENDPOINT HERE"
|
23
|
+
}
|
24
|
+
|
25
|
+
# Initialize a API client with your Workspace Api Key
|
26
|
+
copy_ai_client = CopyAi::Client.new(**copy_ai_credentials)
|
27
|
+
|
28
|
+
# Register webhook
|
29
|
+
# url: your site webhook URL
|
30
|
+
# event_type: https://docs.copy.ai/reference/register-webhook#event-types
|
31
|
+
# optional workflow_id: If a workflow ID is not specified, you will receive events for all workflows in your workspace.
|
32
|
+
response = CopyAi::Webook.register(copy_ai_client, url: 'https://cloud-asm.com/webhook', event_type: 'workflowRun.completed', workflow_id: <workflow-id>)
|
33
|
+
# {
|
34
|
+
"status": "success",
|
35
|
+
"data": {
|
36
|
+
"id": "<id of webhook>",
|
37
|
+
"url": "<https://mywebsite.com/webhook>",
|
38
|
+
"eventType": "workflowRun.completed",
|
39
|
+
"workflowId": "<workflow-id>"
|
40
|
+
}
|
41
|
+
}
|
42
|
+
|
43
|
+
# Starting a Workflow Run
|
44
|
+
post = copy_ai_client.post(body: {
|
45
|
+
startVariables: {
|
46
|
+
"Input 1": "<Inputs vary depending on the workflow used.>",
|
47
|
+
"Input 2": "<The best way to see an example is to try it!>"
|
48
|
+
},
|
49
|
+
"metadata": {
|
50
|
+
"api": true
|
51
|
+
}
|
52
|
+
})
|
53
|
+
# { "status": "success", "data": { "id": "<run-id>" } }
|
54
|
+
|
55
|
+
# Tracking / Poll for Progress
|
56
|
+
copy_ai_client.get
|
57
|
+
# {
|
58
|
+
"status": "success",
|
59
|
+
"data":
|
60
|
+
{
|
61
|
+
"id": "<run-id>",
|
62
|
+
"input":
|
63
|
+
{
|
64
|
+
"Input 1": "Inputs vary depending on the workflow used.",
|
65
|
+
"Input 2": "The best way to see an example is to try it!"
|
66
|
+
},
|
67
|
+
"status": "PROCESSING",
|
68
|
+
"output":
|
69
|
+
{
|
70
|
+
"Output 1": "<Outputs vary depending on the workflow used.>",
|
71
|
+
"Output 2": "<The best way to see an example is to try it!>"
|
72
|
+
},
|
73
|
+
"createdAt": "2022-11-18T20:30:07.434Z"
|
74
|
+
}
|
75
|
+
}
|
76
|
+
|
77
|
+
# Run Completion
|
78
|
+
# When the run is complete, the status will change to COMPLETE and a POST request will be sent to the registered webhooks to notify of the workflow's completion.
|
79
|
+
# {
|
80
|
+
"type": "workflowRun.completed",
|
81
|
+
"workflowRunId": "<run-id>",
|
82
|
+
"workflowId": "<workflow-id>",
|
83
|
+
"result":
|
84
|
+
{
|
85
|
+
"Output 1": "<Outputs vary depending on the workflow used.>",
|
86
|
+
"Output 2": "<The best way to see an example is to try it!>"
|
87
|
+
},
|
88
|
+
"metadata":
|
89
|
+
{
|
90
|
+
/* any metadata set on the workflow run */
|
91
|
+
},
|
92
|
+
"credits": 2
|
93
|
+
}
|
94
|
+
```
|
95
|
+
|
96
|
+
## Development
|
97
|
+
|
98
|
+
1. Checkout and repo:
|
99
|
+
|
100
|
+
git checkout git@github.com:wwwfernand/copy_ai.git
|
101
|
+
|
102
|
+
2. Enter the repo's directory:
|
103
|
+
|
104
|
+
cd copy_ai
|
105
|
+
|
106
|
+
3. Install dependencies via Bundler:
|
107
|
+
|
108
|
+
bundle install
|
109
|
+
|
110
|
+
4. Run the default Rake task to ensure all tests pass:
|
111
|
+
|
112
|
+
bundle exec rake
|
113
|
+
|
114
|
+
5. Create a new branch for your feature or bug fix:
|
115
|
+
|
116
|
+
git checkout -b my-new-branch
|
117
|
+
|
118
|
+
## Contributing
|
119
|
+
|
120
|
+
Bug reports and pull requests are welcome on GitHub at https://github.com/wwwfernand/copy_ai.
|
121
|
+
|
122
|
+
Pull requests will only be accepted if they meet all the following criteria:
|
123
|
+
|
124
|
+
1. Code must conform to [Standard Ruby](https://github.com/standardrb/standard#readme).
|
125
|
+
|
126
|
+
bundle exec rake standard
|
127
|
+
|
128
|
+
2. Code must conform to the [RuboCop rules](https://github.com/rubocop/rubocop#readme).
|
129
|
+
|
130
|
+
bundle exec rake rubocop
|
131
|
+
|
132
|
+
3. 100% LOC code coverage.
|
133
|
+
|
134
|
+
bundle exec rake test
|
135
|
+
|
136
|
+
4. 100% mutation coverage.
|
137
|
+
|
138
|
+
bundle exec rake mutant
|
139
|
+
|
140
|
+
5. RBS type signatures (in `sig/copy_ai.rbs`).
|
141
|
+
|
142
|
+
bundle exec rake steep
|
143
|
+
|
144
|
+
## License
|
145
|
+
The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
|
data/Rakefile
ADDED
@@ -0,0 +1,34 @@
|
|
1
|
+
require "bundler/gem_tasks"
|
2
|
+
require "rake/testtask"
|
3
|
+
|
4
|
+
Rake::TestTask.new(:test) do |t|
|
5
|
+
t.libs << "test"
|
6
|
+
t.libs << "lib"
|
7
|
+
t.options = "--pride"
|
8
|
+
t.test_files = FileList["test/**/*_test.rb"]
|
9
|
+
end
|
10
|
+
|
11
|
+
require "standard/rake"
|
12
|
+
require "rubocop/rake_task"
|
13
|
+
|
14
|
+
RuboCop::RakeTask.new
|
15
|
+
|
16
|
+
require "steep"
|
17
|
+
require "steep/cli"
|
18
|
+
|
19
|
+
desc "Type check with Steep"
|
20
|
+
task :steep do
|
21
|
+
Steep::CLI.new(argv: ["check"], stdout: $stdout, stderr: $stderr, stdin: $stdin).run
|
22
|
+
end
|
23
|
+
|
24
|
+
require "mutant"
|
25
|
+
|
26
|
+
desc "Run mutant"
|
27
|
+
task :mutant do
|
28
|
+
system(*%w[bundle exec mutant run]) or raise "Mutant task failed"
|
29
|
+
end
|
30
|
+
|
31
|
+
desc "Run linters"
|
32
|
+
task lint: %i[rubocop standard]
|
33
|
+
|
34
|
+
task default: %i[test lint mutant steep]
|
data/bin/console
ADDED
@@ -0,0 +1,10 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require "bundler/setup"
|
4
|
+
require "copy_ai"
|
5
|
+
|
6
|
+
# You can add fixtures and/or initialization code here to make experimenting
|
7
|
+
# with your gem easier. You can also use a different console, if you like.
|
8
|
+
|
9
|
+
require "irb"
|
10
|
+
IRB.start(__FILE__)
|
@@ -0,0 +1,72 @@
|
|
1
|
+
require "forwardable"
|
2
|
+
require_relative "authenticator"
|
3
|
+
require_relative "connection"
|
4
|
+
require_relative "request_builder"
|
5
|
+
require_relative "response_parser"
|
6
|
+
|
7
|
+
module CopyAi
|
8
|
+
class Client
|
9
|
+
extend Forwardable
|
10
|
+
|
11
|
+
attr_reader :api_key, :api_endpoint, :workflow_id
|
12
|
+
|
13
|
+
def_delegators :@connection, :open_timeout, :read_timeout, :write_timeout, :debug_output
|
14
|
+
def_delegators :@connection, :open_timeout=, :read_timeout=, :write_timeout=, :debug_output=
|
15
|
+
|
16
|
+
def initialize(api_key:, api_endpoint:,
|
17
|
+
open_timeout: Connection::DEFAULT_OPEN_TIMEOUT,
|
18
|
+
read_timeout: Connection::DEFAULT_READ_TIMEOUT,
|
19
|
+
write_timeout: Connection::DEFAULT_WRITE_TIMEOUT,
|
20
|
+
debug_output: Connection::DEFAULT_DEBUG_OUTPUT)
|
21
|
+
|
22
|
+
@api_key = api_key
|
23
|
+
@api_endpoint = api_endpoint
|
24
|
+
initialize_authenticator
|
25
|
+
initialize_workflow_id
|
26
|
+
@connection = Connection.new(open_timeout:, read_timeout:, write_timeout:, debug_output:)
|
27
|
+
@request_builder = RequestBuilder.new
|
28
|
+
@response_parser = ResponseParser.new
|
29
|
+
end
|
30
|
+
|
31
|
+
def get
|
32
|
+
execute_request(:get, body: nil)
|
33
|
+
end
|
34
|
+
|
35
|
+
def post(body:)
|
36
|
+
execute_request(:post, body:)
|
37
|
+
end
|
38
|
+
|
39
|
+
def api_key=(api_key)
|
40
|
+
@api_key = api_key
|
41
|
+
initialize_authenticator
|
42
|
+
end
|
43
|
+
|
44
|
+
def api_endpoint=(api_endpoint)
|
45
|
+
@api_endpoint = api_endpoint
|
46
|
+
initialize_workflow_id
|
47
|
+
end
|
48
|
+
|
49
|
+
private
|
50
|
+
|
51
|
+
def initialize_workflow_id
|
52
|
+
raise ArgumentError, "Missing Credentials" if api_endpoint.nil? || api_endpoint.empty?
|
53
|
+
|
54
|
+
@workflow_id = api_endpoint.split("/").at(-2)
|
55
|
+
|
56
|
+
raise ArgumentError, "Invalid Credentials" if workflow_id.nil?
|
57
|
+
end
|
58
|
+
|
59
|
+
def initialize_authenticator
|
60
|
+
raise ArgumentError, "Missing Credentials" if api_key.nil? || api_key.empty?
|
61
|
+
|
62
|
+
@authenticator = Authenticator.new(api_key:)
|
63
|
+
end
|
64
|
+
|
65
|
+
def execute_request(http_method, body:)
|
66
|
+
uri = URI(api_endpoint)
|
67
|
+
request = @request_builder.build(http_method:, uri:, body:, authenticator: @authenticator)
|
68
|
+
response = @connection.perform(request:)
|
69
|
+
@response_parser.parse(response:)
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
@@ -0,0 +1,57 @@
|
|
1
|
+
require "forwardable"
|
2
|
+
require "net/http"
|
3
|
+
require "openssl"
|
4
|
+
require "uri"
|
5
|
+
require_relative "errors/network_error"
|
6
|
+
|
7
|
+
module CopyAi
|
8
|
+
class Connection
|
9
|
+
extend Forwardable
|
10
|
+
|
11
|
+
DEFAULT_OPEN_TIMEOUT = 60 # seconds
|
12
|
+
DEFAULT_READ_TIMEOUT = 60 # seconds
|
13
|
+
DEFAULT_WRITE_TIMEOUT = 60 # seconds
|
14
|
+
DEFAULT_DEBUG_OUTPUT = File.open(File::NULL, "w")
|
15
|
+
NETWORK_ERRORS = [
|
16
|
+
Errno::ECONNREFUSED,
|
17
|
+
Errno::ECONNRESET,
|
18
|
+
Net::OpenTimeout,
|
19
|
+
Net::ReadTimeout,
|
20
|
+
OpenSSL::SSL::SSLError
|
21
|
+
].freeze
|
22
|
+
|
23
|
+
attr_accessor :open_timeout, :read_timeout, :write_timeout, :debug_output
|
24
|
+
|
25
|
+
def initialize(open_timeout: DEFAULT_OPEN_TIMEOUT, read_timeout: DEFAULT_READ_TIMEOUT,
|
26
|
+
write_timeout: DEFAULT_WRITE_TIMEOUT, debug_output: DEFAULT_DEBUG_OUTPUT)
|
27
|
+
@open_timeout = open_timeout
|
28
|
+
@read_timeout = read_timeout
|
29
|
+
@write_timeout = write_timeout
|
30
|
+
@debug_output = debug_output
|
31
|
+
end
|
32
|
+
|
33
|
+
def perform(request:)
|
34
|
+
http_client = build_http_client(request.uri.host, request.uri.port)
|
35
|
+
http_client.use_ssl = true
|
36
|
+
http_client.request(request)
|
37
|
+
rescue *NETWORK_ERRORS => e
|
38
|
+
raise NetworkError, "Network error: #{e}"
|
39
|
+
end
|
40
|
+
|
41
|
+
private
|
42
|
+
|
43
|
+
def build_http_client(host, port)
|
44
|
+
http_client = Net::HTTP.new(host, port)
|
45
|
+
configure_http_client(http_client)
|
46
|
+
end
|
47
|
+
|
48
|
+
def configure_http_client(http_client)
|
49
|
+
http_client.tap do |c|
|
50
|
+
c.open_timeout = open_timeout
|
51
|
+
c.read_timeout = read_timeout
|
52
|
+
c.write_timeout = write_timeout
|
53
|
+
c.set_debug_output(debug_output)
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
@@ -0,0 +1,41 @@
|
|
1
|
+
require "json"
|
2
|
+
require_relative "error"
|
3
|
+
|
4
|
+
module CopyAi
|
5
|
+
class HTTPError < Error
|
6
|
+
JSON_CONTENT_TYPE_REGEXP = %r{application/(problem\+|)json}
|
7
|
+
|
8
|
+
attr_reader :response, :code
|
9
|
+
|
10
|
+
def initialize(response:)
|
11
|
+
super(error_message(response))
|
12
|
+
@response = response
|
13
|
+
@code = response.code
|
14
|
+
end
|
15
|
+
|
16
|
+
def error_message(response)
|
17
|
+
if json?(response)
|
18
|
+
message_from_json_response(response)
|
19
|
+
else
|
20
|
+
response.message
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
def message_from_json_response(response)
|
25
|
+
response_object = JSON.parse(response.body)
|
26
|
+
if response_object.key?("title") && response_object.key?("detail")
|
27
|
+
"#{response_object.fetch("title")}: #{response_object.fetch("detail")}"
|
28
|
+
elsif response_object.key?("error")
|
29
|
+
response_object.fetch("error")
|
30
|
+
elsif response_object["errors"].instance_of?(Array)
|
31
|
+
response_object.fetch("errors").map { |error| error.fetch("message") }.join(", ")
|
32
|
+
else
|
33
|
+
response.message
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
def json?(response)
|
38
|
+
JSON_CONTENT_TYPE_REGEXP === response["content-type"]
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
@@ -0,0 +1,40 @@
|
|
1
|
+
require "net/http"
|
2
|
+
require "uri"
|
3
|
+
require_relative "authenticator"
|
4
|
+
require_relative "version"
|
5
|
+
|
6
|
+
module CopyAi
|
7
|
+
class RequestBuilder
|
8
|
+
DEFAULT_HEADERS = {"Content-Type" => "application/json"}.freeze
|
9
|
+
HTTP_METHODS = {
|
10
|
+
get: Net::HTTP::Get,
|
11
|
+
post: Net::HTTP::Post
|
12
|
+
}.freeze
|
13
|
+
|
14
|
+
def build(http_method:, uri:, authenticator:, body:)
|
15
|
+
raise ArgumentError, "Missing Credentials" unless authenticator
|
16
|
+
|
17
|
+
request = create_request(http_method:, uri:, body:)
|
18
|
+
add_headers(request:, header: authenticator.header)
|
19
|
+
request
|
20
|
+
end
|
21
|
+
|
22
|
+
private
|
23
|
+
|
24
|
+
def create_request(http_method:, uri:, body:)
|
25
|
+
http_method_class = HTTP_METHODS[http_method]
|
26
|
+
|
27
|
+
raise ArgumentError, "Unsupported HTTP method: #{http_method}" unless http_method_class
|
28
|
+
|
29
|
+
request = http_method_class.new(uri)
|
30
|
+
request.body = body.to_json unless body.nil?
|
31
|
+
request
|
32
|
+
end
|
33
|
+
|
34
|
+
def add_headers(request:, header:)
|
35
|
+
DEFAULT_HEADERS.merge(header).each do |key, value|
|
36
|
+
request.add_field(key, value)
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
@@ -0,0 +1,59 @@
|
|
1
|
+
require "json"
|
2
|
+
require "net/http"
|
3
|
+
require_relative "errors/bad_gateway"
|
4
|
+
require_relative "errors/bad_request"
|
5
|
+
require_relative "errors/connection_exception"
|
6
|
+
require_relative "errors/http_error"
|
7
|
+
require_relative "errors/forbidden"
|
8
|
+
require_relative "errors/gateway_timeout"
|
9
|
+
require_relative "errors/gone"
|
10
|
+
require_relative "errors/internal_server_error"
|
11
|
+
require_relative "errors/not_acceptable"
|
12
|
+
require_relative "errors/not_found"
|
13
|
+
require_relative "errors/payload_too_large"
|
14
|
+
require_relative "errors/service_unavailable"
|
15
|
+
require_relative "errors/unauthorized"
|
16
|
+
require_relative "errors/unprocessable_entity"
|
17
|
+
|
18
|
+
module CopyAi
|
19
|
+
class ResponseParser
|
20
|
+
ERROR_MAP = {
|
21
|
+
400 => BadRequest,
|
22
|
+
401 => Unauthorized,
|
23
|
+
403 => Forbidden,
|
24
|
+
404 => NotFound,
|
25
|
+
406 => NotAcceptable,
|
26
|
+
409 => ConnectionException,
|
27
|
+
410 => Gone,
|
28
|
+
413 => PayloadTooLarge,
|
29
|
+
422 => UnprocessableEntity,
|
30
|
+
500 => InternalServerError,
|
31
|
+
502 => BadGateway,
|
32
|
+
503 => ServiceUnavailable,
|
33
|
+
504 => GatewayTimeout
|
34
|
+
}.freeze
|
35
|
+
JSON_CONTENT_TYPE_REGEXP = %r{application/json}
|
36
|
+
|
37
|
+
def parse(response:)
|
38
|
+
raise error(response) unless response.is_a?(Net::HTTPSuccess)
|
39
|
+
|
40
|
+
return unless json?(response)
|
41
|
+
|
42
|
+
JSON.parse(response.body)
|
43
|
+
end
|
44
|
+
|
45
|
+
private
|
46
|
+
|
47
|
+
def error(response)
|
48
|
+
error_class(response).new(response:)
|
49
|
+
end
|
50
|
+
|
51
|
+
def error_class(response)
|
52
|
+
ERROR_MAP[Integer(response.code)] || HTTPError
|
53
|
+
end
|
54
|
+
|
55
|
+
def json?(response)
|
56
|
+
JSON_CONTENT_TYPE_REGEXP === response["content-type"]
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
module CopyAi
|
2
|
+
module Webhook
|
3
|
+
extend self
|
4
|
+
EVENT_TYPES = [
|
5
|
+
"workflowRun.started",
|
6
|
+
"workflowRun.completed",
|
7
|
+
"workflowRun.failed",
|
8
|
+
"workflowCreditLimit.reached"
|
9
|
+
].freeze
|
10
|
+
WEBHOOK_URL = "https://api.copy.ai/api/webhook".freeze
|
11
|
+
|
12
|
+
# If a workflow ID is not included, events for all workflows in your workspace will be received
|
13
|
+
def register(client, url:, event_type:, workflow_id: nil)
|
14
|
+
raise ArgumentError, "Missing Arguments" if client.nil? || url.nil? || event_type.nil?
|
15
|
+
|
16
|
+
validate!(event_type:)
|
17
|
+
webhook_client = client.dup.tap { |c| c.api_endpoint = WEBHOOK_URL }
|
18
|
+
body = {url:, eventType: event_type, workflowId: workflow_id}
|
19
|
+
webhook_client.post(body:)
|
20
|
+
end
|
21
|
+
|
22
|
+
private
|
23
|
+
|
24
|
+
def validate!(event_type:)
|
25
|
+
return if EVENT_TYPES.include?(event_type)
|
26
|
+
|
27
|
+
raise ArgumentError, "Invalid event_type: #{event_type}"
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
data/lib/copy_ai.rb
ADDED
metadata
ADDED
@@ -0,0 +1,100 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: copy_ai
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Fernand Arioja
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2024-08-19 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: rails
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '7.1'
|
20
|
+
- - ">="
|
21
|
+
- !ruby/object:Gem::Version
|
22
|
+
version: 7.1.3.4
|
23
|
+
type: :runtime
|
24
|
+
prerelease: false
|
25
|
+
version_requirements: !ruby/object:Gem::Requirement
|
26
|
+
requirements:
|
27
|
+
- - "~>"
|
28
|
+
- !ruby/object:Gem::Version
|
29
|
+
version: '7.1'
|
30
|
+
- - ">="
|
31
|
+
- !ruby/object:Gem::Version
|
32
|
+
version: 7.1.3.4
|
33
|
+
description: A Ruby client library for accessing the Copy.ai API, allowing developers
|
34
|
+
to easily integrate Copy.ai's text generation capabilities into their Ruby applications
|
35
|
+
email:
|
36
|
+
- dev.cloud.asm@gmail.com
|
37
|
+
executables: []
|
38
|
+
extensions: []
|
39
|
+
extra_rdoc_files: []
|
40
|
+
files:
|
41
|
+
- CHANGELOG.md
|
42
|
+
- MIT-LICENSE
|
43
|
+
- README.md
|
44
|
+
- Rakefile
|
45
|
+
- bin/console
|
46
|
+
- lib/copy_ai.rb
|
47
|
+
- lib/copy_ai/authenticator.rb
|
48
|
+
- lib/copy_ai/client.rb
|
49
|
+
- lib/copy_ai/connection.rb
|
50
|
+
- lib/copy_ai/errors/bad_gateway.rb
|
51
|
+
- lib/copy_ai/errors/bad_request.rb
|
52
|
+
- lib/copy_ai/errors/client_error.rb
|
53
|
+
- lib/copy_ai/errors/connection_exception.rb
|
54
|
+
- lib/copy_ai/errors/error.rb
|
55
|
+
- lib/copy_ai/errors/forbidden.rb
|
56
|
+
- lib/copy_ai/errors/gateway_timeout.rb
|
57
|
+
- lib/copy_ai/errors/gone.rb
|
58
|
+
- lib/copy_ai/errors/http_error.rb
|
59
|
+
- lib/copy_ai/errors/internal_server_error.rb
|
60
|
+
- lib/copy_ai/errors/network_error.rb
|
61
|
+
- lib/copy_ai/errors/not_acceptable.rb
|
62
|
+
- lib/copy_ai/errors/not_found.rb
|
63
|
+
- lib/copy_ai/errors/payload_too_large.rb
|
64
|
+
- lib/copy_ai/errors/server_error.rb
|
65
|
+
- lib/copy_ai/errors/service_unavailable.rb
|
66
|
+
- lib/copy_ai/errors/unauthorized.rb
|
67
|
+
- lib/copy_ai/errors/unprocessable_entity.rb
|
68
|
+
- lib/copy_ai/request_builder.rb
|
69
|
+
- lib/copy_ai/response_parser.rb
|
70
|
+
- lib/copy_ai/version.rb
|
71
|
+
- lib/copy_ai/webhook.rb
|
72
|
+
homepage: https://github.com/wwwfernand/copy_ai
|
73
|
+
licenses:
|
74
|
+
- MIT
|
75
|
+
metadata:
|
76
|
+
allowed_push_host: https://rubygems.org
|
77
|
+
homepage_uri: https://github.com/wwwfernand/copy_ai
|
78
|
+
source_code_uri: https://github.com/wwwfernand/copy_ai
|
79
|
+
changelog_uri: https://github.com/wwwfernand/copy_ai/master/CHANGELOG.md
|
80
|
+
rubygems_mfa_required: 'true'
|
81
|
+
post_install_message:
|
82
|
+
rdoc_options: []
|
83
|
+
require_paths:
|
84
|
+
- lib
|
85
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
86
|
+
requirements:
|
87
|
+
- - ">="
|
88
|
+
- !ruby/object:Gem::Version
|
89
|
+
version: 3.1.6
|
90
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
91
|
+
requirements:
|
92
|
+
- - ">="
|
93
|
+
- !ruby/object:Gem::Version
|
94
|
+
version: '0'
|
95
|
+
requirements: []
|
96
|
+
rubygems_version: 3.3.27
|
97
|
+
signing_key:
|
98
|
+
specification_version: 4
|
99
|
+
summary: A Ruby interface to the Copy.ai API
|
100
|
+
test_files: []
|