circuit_client 0.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/Dockerfile +9 -0
- data/Gemfile +4 -0
- data/README.md +58 -0
- data/Rakefile +14 -0
- data/bin/send-circuit +7 -0
- data/lib/circuit_client.rb +1 -0
- data/lib/circuit_client/client.rb +190 -0
- data/lib/circuit_client/send_message_cli.rb +142 -0
- metadata +123 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: c8e1508915ce91398ef199c6f21c03eb84f0c614
|
4
|
+
data.tar.gz: b94c3dd4990da34a3ac0b34a7ea5d7869214c1b2
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 177e67970945a50d5468c57adcb8530d24096b877113a048f731b2d1265f95bdc32f4675bc10ced3a1e6936040ccc2e3e5a409db8d632899acf73c939c34f7ae
|
7
|
+
data.tar.gz: 19b15b3cfb43e6799cfa2676888a2017fdfd1cb26de7c4f0b7341316ef939da1a1798ab479fb97336eb3234ae4f6258e04f7556cf15b8d7368db5d6a8a321043
|
data/Dockerfile
ADDED
data/Gemfile
ADDED
data/README.md
ADDED
@@ -0,0 +1,58 @@
|
|
1
|
+
# Circuit Client
|
2
|
+
|
3
|
+
circuit\_client is a minimal client for the Circuit REST API.
|
4
|
+
|
5
|
+
* [Circuit](https://www.circuit.com/)
|
6
|
+
* [Circuit REST API](https://circuitsandbox.net/rest/v2/swagger/ui/index.html)
|
7
|
+
|
8
|
+
It is not a full-featured API client and current only supports:
|
9
|
+
|
10
|
+
* only client\_credentials authentication
|
11
|
+
* list and create conversations
|
12
|
+
* create new messages
|
13
|
+
|
14
|
+
## API Documentation
|
15
|
+
|
16
|
+
Available at [rubydoc.info](http://www.rubydoc.info/gems/circuit_client).
|
17
|
+
|
18
|
+
## Usage
|
19
|
+
|
20
|
+
### Basic usage
|
21
|
+
|
22
|
+
```ruby
|
23
|
+
require 'circuit_client'
|
24
|
+
|
25
|
+
client = CircuitClient::Client.new do |c|
|
26
|
+
c.client_id = '<client_id>'
|
27
|
+
c.client_secret = '<client_secret>'
|
28
|
+
end
|
29
|
+
|
30
|
+
client.create_message('<convId>', 'Hello World!')
|
31
|
+
```
|
32
|
+
|
33
|
+
## Command line interface
|
34
|
+
|
35
|
+
The `send-circuit` command shipped with circuit\_client has the following options:
|
36
|
+
|
37
|
+
```
|
38
|
+
Usage: send-circuit [OPTIONS]
|
39
|
+
--help | -h display this help text
|
40
|
+
--config | -c <file> path to configuration file
|
41
|
+
(default: /etc/send-circuit.yaml)
|
42
|
+
--trace print http debug information
|
43
|
+
|
44
|
+
List conversations:
|
45
|
+
--list | -l list conversations of user
|
46
|
+
|
47
|
+
Send message:
|
48
|
+
--subject | -s <text> Set subject for message
|
49
|
+
|
50
|
+
--conversation | -c <id> Id of the conversation to send a message to
|
51
|
+
or
|
52
|
+
--new | -n creates a new conversation
|
53
|
+
--topic | -t <text> topic of the new conversation
|
54
|
+
--participant | -p
|
55
|
+
<email or id> adds a participant to the conversation
|
56
|
+
|
57
|
+
The command will read the message body from stdin.
|
58
|
+
```
|
data/Rakefile
ADDED
@@ -0,0 +1,14 @@
|
|
1
|
+
require 'rake/clean'
|
2
|
+
require 'rubygems'
|
3
|
+
require 'rubygems/package_task'
|
4
|
+
require 'rdoc/task'
|
5
|
+
|
6
|
+
spec = eval(File.read('circuit_client.gemspec'))
|
7
|
+
Gem::PackageTask.new(spec) do |pkg|
|
8
|
+
end
|
9
|
+
|
10
|
+
Rake::RDocTask.new do |rd|
|
11
|
+
rd.rdoc_files.include("lib/**/*.rb","bin/**/*")
|
12
|
+
rd.title = 'Circuit Client for REST API'
|
13
|
+
end
|
14
|
+
|
data/bin/send-circuit
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
require 'circuit_client/client'
|
@@ -0,0 +1,190 @@
|
|
1
|
+
require 'faraday'
|
2
|
+
require 'typhoeus'
|
3
|
+
require 'typhoeus/adapters/faraday'
|
4
|
+
require 'uri'
|
5
|
+
require 'json'
|
6
|
+
|
7
|
+
module CircuitClient
|
8
|
+
class Client
|
9
|
+
# Set the hostname of the circuit system
|
10
|
+
attr_accessor :host
|
11
|
+
|
12
|
+
# The base path of the API
|
13
|
+
attr_accessor :base_path
|
14
|
+
|
15
|
+
# The protocol to use 'http' or 'https'
|
16
|
+
attr_accessor :protocol
|
17
|
+
|
18
|
+
# Timeout for http requests
|
19
|
+
attr_accessor :timeout
|
20
|
+
|
21
|
+
# The client_id for authentication
|
22
|
+
attr_accessor :client_id
|
23
|
+
|
24
|
+
# The client_secret for authentication
|
25
|
+
attr_accessor :client_secret
|
26
|
+
|
27
|
+
# The authentication method to use (currently only :client_credentials supported)
|
28
|
+
attr_accessor :auth_method
|
29
|
+
|
30
|
+
# Enable tracing (outputs http requests to STDOUT)
|
31
|
+
attr_accessor :trace
|
32
|
+
|
33
|
+
# Initialize a new client
|
34
|
+
#
|
35
|
+
# Examples
|
36
|
+
#
|
37
|
+
# CircuitClient::Client.new do |c|
|
38
|
+
# c.client_id = '4de34a3...'
|
39
|
+
# c.client_secret = '234df2...'
|
40
|
+
# end
|
41
|
+
#
|
42
|
+
# Returns a new CircuitClient::Client
|
43
|
+
def initialize
|
44
|
+
@host = 'eu.yourcircuit.com'
|
45
|
+
@base_path = '/rest/v2'
|
46
|
+
@protocol = 'https'
|
47
|
+
@auth_method = :client_credentials
|
48
|
+
@timeout = 60
|
49
|
+
@trace = false
|
50
|
+
yield self
|
51
|
+
end
|
52
|
+
|
53
|
+
# The faraday http connection object
|
54
|
+
def connection
|
55
|
+
@connection ||= Faraday.new(url: base_uri.to_s) do |faraday|
|
56
|
+
faraday.response :logger if @trace
|
57
|
+
faraday.use Faraday::Response::RaiseError
|
58
|
+
faraday.adapter :typhoeus
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
# The token used for authentication
|
63
|
+
def access_token
|
64
|
+
return @access_token unless @access_token.nil?
|
65
|
+
case @auth_method
|
66
|
+
when :client_credentials
|
67
|
+
auth_client_credentials
|
68
|
+
else
|
69
|
+
raise "Unknown auth_method: #{@auth_method}"
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
# Authenticate using client_credentials method
|
74
|
+
def auth_client_credentials
|
75
|
+
raise "client_id parameter required" if @client_id.nil?
|
76
|
+
raise "client_secret parameter required" if @client_secret.nil?
|
77
|
+
response = connection.post(build_uri('/oauth/token'), {
|
78
|
+
client_id: @client_id,
|
79
|
+
client_secret: @client_secret,
|
80
|
+
grant_type: 'client_credentials',
|
81
|
+
scope: 'ALL',
|
82
|
+
} )
|
83
|
+
data = JSON.parse(response.body)
|
84
|
+
data['access_token']
|
85
|
+
end
|
86
|
+
|
87
|
+
# Return URI with path elements
|
88
|
+
def base_uri
|
89
|
+
URI("#{@protocol}://#{@host}")
|
90
|
+
end
|
91
|
+
|
92
|
+
# Returns an URI with the base_uri and the supplied path
|
93
|
+
def build_uri(path)
|
94
|
+
uri = base_uri
|
95
|
+
uri.path = path
|
96
|
+
uri.to_s
|
97
|
+
end
|
98
|
+
|
99
|
+
# Returns an URI and with a path relative to the base_path of the API
|
100
|
+
def build_api_uri(path)
|
101
|
+
build_uri("#{@base_path}#{path}")
|
102
|
+
end
|
103
|
+
|
104
|
+
# Create a new message in a existing conversation
|
105
|
+
#
|
106
|
+
# Examples
|
107
|
+
#
|
108
|
+
# client.create_message('<convId>', 'my message text...', subject: 'Todays meeting')
|
109
|
+
#
|
110
|
+
def create_message(conv, text, **options)
|
111
|
+
call(:post, "/conversations/#{conv}/messages", {
|
112
|
+
'content' => text,
|
113
|
+
**options,
|
114
|
+
} )
|
115
|
+
end
|
116
|
+
|
117
|
+
# List all conversation of the user
|
118
|
+
def list_conversations
|
119
|
+
call(:get, "/conversations")
|
120
|
+
end
|
121
|
+
|
122
|
+
# Create a new group conversation
|
123
|
+
def create_group_conversation(participants, topic)
|
124
|
+
call(:post, '/conversations/group', {
|
125
|
+
participants: participants,
|
126
|
+
topic: topic,
|
127
|
+
} )
|
128
|
+
end
|
129
|
+
|
130
|
+
# Create a new 1:1 conversation
|
131
|
+
def create_direct_conversation(participant)
|
132
|
+
call(:post, '/conversations/direct', {
|
133
|
+
participant: participant,
|
134
|
+
} )
|
135
|
+
end
|
136
|
+
|
137
|
+
# Remove participants from a conversation
|
138
|
+
def delete_group_conversation_participants(conv, participants)
|
139
|
+
call(:delete, "/conversations/group/#{conv}/participants", {
|
140
|
+
participants: participants,
|
141
|
+
} )
|
142
|
+
end
|
143
|
+
|
144
|
+
# Remove the current_user from a conversation
|
145
|
+
def leave_group_conversation(conv)
|
146
|
+
delete_group_conversation_participants(conv, [current_user['userId']])
|
147
|
+
end
|
148
|
+
|
149
|
+
# Get the profile of the connections user
|
150
|
+
def get_user_profile
|
151
|
+
call(:get, "/users/profile")
|
152
|
+
end
|
153
|
+
|
154
|
+
# A cached version of the current connections user profile
|
155
|
+
def current_user
|
156
|
+
@current_user ||= get_user_profile
|
157
|
+
end
|
158
|
+
|
159
|
+
# Get profile of a user
|
160
|
+
def get_users(id)
|
161
|
+
call(:get, "/users/#{id}")
|
162
|
+
end
|
163
|
+
|
164
|
+
# Get presence information of a user
|
165
|
+
def get_users_presence(id)
|
166
|
+
call(:get, "/users/#{id}/presence")
|
167
|
+
end
|
168
|
+
|
169
|
+
private
|
170
|
+
|
171
|
+
def call(method, path, payload = {}, headers = {})
|
172
|
+
response = connection.send(method) do |req|
|
173
|
+
req.url build_api_uri(path)
|
174
|
+
req.options.timeout = @timeout
|
175
|
+
req.headers['Accept'] = 'application/json'
|
176
|
+
req.headers['Authorization'] = "Bearer #{access_token}"
|
177
|
+
case method
|
178
|
+
when :post
|
179
|
+
req.body = payload.to_json
|
180
|
+
req.headers['Content-Type'] = 'application/json'
|
181
|
+
when :get, :delete
|
182
|
+
req.params = payload
|
183
|
+
end
|
184
|
+
end
|
185
|
+
return JSON.parse(response.body) if response.success?
|
186
|
+
end
|
187
|
+
|
188
|
+
end
|
189
|
+
end
|
190
|
+
|
@@ -0,0 +1,142 @@
|
|
1
|
+
require 'circuit_client'
|
2
|
+
require 'getoptlong'
|
3
|
+
require 'yaml'
|
4
|
+
|
5
|
+
module CircuitClient
|
6
|
+
class SendMessageCli
|
7
|
+
|
8
|
+
class Config
|
9
|
+
DEFAULTS = {
|
10
|
+
timeout: 60,
|
11
|
+
host: 'eu.yourcircuit.com',
|
12
|
+
client_id: nil,
|
13
|
+
client_secret: nil,
|
14
|
+
}
|
15
|
+
def self.load_config(path)
|
16
|
+
@@data = YAML.load_file(path)
|
17
|
+
end
|
18
|
+
def self.method_missing(method_name)
|
19
|
+
if DEFAULTS.has_key?(method_name)
|
20
|
+
@@data[method_name.to_s] || DEFAULTS[method_name]
|
21
|
+
else
|
22
|
+
super
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
def initialize
|
28
|
+
@trace = false
|
29
|
+
@list = false
|
30
|
+
@new = false
|
31
|
+
@participants = []
|
32
|
+
@config_file = '/etc/send-circuit.yaml'
|
33
|
+
@topic = ''
|
34
|
+
end
|
35
|
+
|
36
|
+
def usage
|
37
|
+
puts <<-END_USAGE
|
38
|
+
Usage: send-circuit [OPTIONS]
|
39
|
+
--help | -h display this help text
|
40
|
+
--config | -c <file> path to configuration file
|
41
|
+
(default: /etc/send-circuit.yaml)
|
42
|
+
--trace print http debug information
|
43
|
+
|
44
|
+
List conversations:
|
45
|
+
--list | -l list conversations of user
|
46
|
+
|
47
|
+
Send message:
|
48
|
+
--subject | -s <text> Set subject for message
|
49
|
+
|
50
|
+
--conversation | -c <id> Id of the conversation to send a message to
|
51
|
+
or
|
52
|
+
--new | -n creates a new conversation
|
53
|
+
--topic | -t <text> topic of the new conversation
|
54
|
+
--participant | -p
|
55
|
+
<email or id> adds a participant to the conversation
|
56
|
+
|
57
|
+
|
58
|
+
The command will read the message body from stdin.
|
59
|
+
END_USAGE
|
60
|
+
end
|
61
|
+
|
62
|
+
def getopts
|
63
|
+
opts = GetoptLong.new(
|
64
|
+
[ '--help', '-h', GetoptLong::NO_ARGUMENT ],
|
65
|
+
[ '--conversation', '-c', GetoptLong::REQUIRED_ARGUMENT ],
|
66
|
+
[ '--subject', '-s', GetoptLong::REQUIRED_ARGUMENT ],
|
67
|
+
[ '--topic', '-t', GetoptLong::REQUIRED_ARGUMENT ],
|
68
|
+
[ '--trace', GetoptLong::NO_ARGUMENT ],
|
69
|
+
[ '--list', '-l', GetoptLong::NO_ARGUMENT ],
|
70
|
+
[ '--new', '-n', GetoptLong::NO_ARGUMENT ],
|
71
|
+
[ '--participant', '-p', GetoptLong::REQUIRED_ARGUMENT ],
|
72
|
+
[ '--config', '-f', GetoptLong::REQUIRED_ARGUMENT ],
|
73
|
+
)
|
74
|
+
opts.each do |opt, arg|
|
75
|
+
case opt
|
76
|
+
when '--help'
|
77
|
+
usage
|
78
|
+
exit 0
|
79
|
+
when '--conversation'
|
80
|
+
@conversation = arg.to_s
|
81
|
+
when '--subject'
|
82
|
+
@subject = arg.to_s
|
83
|
+
when '--trace'
|
84
|
+
@trace = true
|
85
|
+
when '--list'
|
86
|
+
@list = true
|
87
|
+
when '--new'
|
88
|
+
@new = true
|
89
|
+
when '--participant'
|
90
|
+
@participants << arg.to_s
|
91
|
+
when '--config'
|
92
|
+
@config_file = arg.to_s
|
93
|
+
when '--topic'
|
94
|
+
@topic = arg.to_s
|
95
|
+
end
|
96
|
+
end
|
97
|
+
end
|
98
|
+
|
99
|
+
def run
|
100
|
+
getopts
|
101
|
+
Config.load_config(@config_file)
|
102
|
+
|
103
|
+
if @list == true
|
104
|
+
list_conversations
|
105
|
+
exit 0
|
106
|
+
end
|
107
|
+
|
108
|
+
# read msg from stdin
|
109
|
+
body = $stdin.readlines.join
|
110
|
+
|
111
|
+
if @new == true
|
112
|
+
puts "creating new group conversation..."
|
113
|
+
conv = client.create_group_conversation(@participants, @topic)['convId']
|
114
|
+
else
|
115
|
+
conv = @conversation
|
116
|
+
end
|
117
|
+
|
118
|
+
options = {}
|
119
|
+
options[:subject] = @subject unless @subject.nil?
|
120
|
+
puts "sending message to #{conv}..."
|
121
|
+
client.create_message( conv, body, **options )
|
122
|
+
end
|
123
|
+
|
124
|
+
def client
|
125
|
+
CircuitClient::Client.new do |c|
|
126
|
+
c.host = Config.host
|
127
|
+
c.client_id = Config.client_id
|
128
|
+
c.client_secret = Config.client_secret
|
129
|
+
c.trace = @trace
|
130
|
+
c.timeout = Config.timeout
|
131
|
+
end
|
132
|
+
end
|
133
|
+
|
134
|
+
def list_conversations
|
135
|
+
client.list_conversations.each do |c|
|
136
|
+
puts "- #{c['topic']} (#{c['convId']})"
|
137
|
+
end
|
138
|
+
end
|
139
|
+
|
140
|
+
end
|
141
|
+
end
|
142
|
+
|
metadata
ADDED
@@ -0,0 +1,123 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: circuit_client
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Markus Benning
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2018-02-23 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: '0'
|
20
|
+
type: :development
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - ">="
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '0'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: rdoc
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - ">="
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '0'
|
34
|
+
type: :development
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - ">="
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '0'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: aruba
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - ">="
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '0'
|
48
|
+
type: :development
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - ">="
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '0'
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: faraday
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - ">="
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '0'
|
62
|
+
type: :runtime
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - ">="
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '0'
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: typhoeus
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
72
|
+
requirements:
|
73
|
+
- - ">="
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
version: '0'
|
76
|
+
type: :runtime
|
77
|
+
prerelease: false
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
79
|
+
requirements:
|
80
|
+
- - ">="
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: '0'
|
83
|
+
description:
|
84
|
+
email: ich@markusbenning.de
|
85
|
+
executables:
|
86
|
+
- send-circuit
|
87
|
+
extensions: []
|
88
|
+
extra_rdoc_files: []
|
89
|
+
files:
|
90
|
+
- Dockerfile
|
91
|
+
- Gemfile
|
92
|
+
- README.md
|
93
|
+
- Rakefile
|
94
|
+
- bin/send-circuit
|
95
|
+
- lib/circuit_client.rb
|
96
|
+
- lib/circuit_client/client.rb
|
97
|
+
- lib/circuit_client/send_message_cli.rb
|
98
|
+
homepage: https://github.com/benningm/circuit_client
|
99
|
+
licenses:
|
100
|
+
- MIT
|
101
|
+
metadata: {}
|
102
|
+
post_install_message:
|
103
|
+
rdoc_options: []
|
104
|
+
require_paths:
|
105
|
+
- lib
|
106
|
+
- lib
|
107
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
108
|
+
requirements:
|
109
|
+
- - ">="
|
110
|
+
- !ruby/object:Gem::Version
|
111
|
+
version: '0'
|
112
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
113
|
+
requirements:
|
114
|
+
- - ">="
|
115
|
+
- !ruby/object:Gem::Version
|
116
|
+
version: '0'
|
117
|
+
requirements: []
|
118
|
+
rubyforge_project:
|
119
|
+
rubygems_version: 2.6.8
|
120
|
+
signing_key:
|
121
|
+
specification_version: 4
|
122
|
+
summary: Simple client for circuit REST API
|
123
|
+
test_files: []
|