citadel-ruby-client 0.2.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/lib/citadel.rb +194 -0
- data/lib/citadel/authenticator.rb +16 -0
- data/lib/citadel/matrix_interceptor.rb +15 -0
- data/lib/citadel/matrix_paths.rb +46 -0
- data/lib/citadel/version.rb +3 -0
- metadata +125 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 0ad7287c5b5e735b97040f7b8f6bc0cda099dbec
|
4
|
+
data.tar.gz: 01f3a8bcfeca4b2fc1aacd75ad65a68dbf9a04aa
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 19cb0f9d33f06a25663e0a1dc58cbd5dd4faca6a5660c65e17654210dc4990da836231a8f25e77211ea2eacb1614f202b8f5768dadc29c7aa1f634ec0ea4cd84
|
7
|
+
data.tar.gz: 459dbb0a94e877a2ecab91cf0d1cff63c1f0b97ef02166e0acff20d85721c809a26e0fb5833c0898e6d32a5c5af760c1d095cfbc9314d701fef41f5337634d47
|
data/lib/citadel.rb
ADDED
@@ -0,0 +1,194 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'http'
|
4
|
+
require 'json'
|
5
|
+
require 'citadel/authenticator'
|
6
|
+
require 'citadel/matrix_paths'
|
7
|
+
require 'citadel/matrix_interceptor'
|
8
|
+
|
9
|
+
module Citadel
|
10
|
+
|
11
|
+
DEFAULT_PUBLIC_ROOMS_LIMIT = 100
|
12
|
+
|
13
|
+
class << self
|
14
|
+
attr_accessor :tenant_url, :public_rooms_limit
|
15
|
+
end
|
16
|
+
|
17
|
+
class Client
|
18
|
+
def initialize(tenant_url, public_rooms_limit = DEFAULT_PUBLIC_ROOMS_LIMIT)
|
19
|
+
if tenant_url[-1,1] == '/'
|
20
|
+
Citadel.tenant_url = tenant_url[0,tenant_url.length-1]
|
21
|
+
else
|
22
|
+
Citadel.tenant_url = tenant_url
|
23
|
+
end
|
24
|
+
Citadel.public_rooms_limit = public_rooms_limit
|
25
|
+
end
|
26
|
+
|
27
|
+
#########
|
28
|
+
# AUTH #
|
29
|
+
#########
|
30
|
+
|
31
|
+
def auth_token
|
32
|
+
return @auth_token if defined? @auth_token
|
33
|
+
puts 'Citadel: You need to sign in'
|
34
|
+
return nil
|
35
|
+
end
|
36
|
+
|
37
|
+
def sign_in(login, password)
|
38
|
+
authenticator = Authenticator.new
|
39
|
+
@auth_token = 'Bearer ' + authenticator.get_token(login, password)
|
40
|
+
end
|
41
|
+
|
42
|
+
##############
|
43
|
+
# LIST ROOMS #
|
44
|
+
##############
|
45
|
+
|
46
|
+
def list_all_public_rooms
|
47
|
+
response = all_public_rooms_response
|
48
|
+
room_count = JSON.parse(response.body)['total_room_count_estimate'] - 2
|
49
|
+
result = []
|
50
|
+
(0..room_count).each do
|
51
|
+
result << JSON.parse(response.body)['chunk'][i]['room_id']
|
52
|
+
end
|
53
|
+
result
|
54
|
+
end
|
55
|
+
|
56
|
+
def list_all_joined_rooms
|
57
|
+
response = all_joined_rooms_response
|
58
|
+
rooms = JSON.parse(response.body)['joined_rooms']
|
59
|
+
rooms
|
60
|
+
end
|
61
|
+
|
62
|
+
def all_public_rooms_response
|
63
|
+
matrix_paths = MatrixPaths.new
|
64
|
+
url = matrix_paths.base_uri + matrix_paths.list_public_rooms_path
|
65
|
+
HTTP.auth(auth_token).get(url)
|
66
|
+
end
|
67
|
+
|
68
|
+
def all_joined_rooms_response
|
69
|
+
matrix_paths = MatrixPaths.new
|
70
|
+
url = matrix_paths.base_uri + matrix_paths.list_joined_rooms_path
|
71
|
+
HTTP.auth(auth_token).get(url)
|
72
|
+
end
|
73
|
+
|
74
|
+
#################
|
75
|
+
# ROOM CREATION #
|
76
|
+
#################
|
77
|
+
|
78
|
+
def create_room(room_name, topic)
|
79
|
+
matrix_paths = MatrixPaths.new
|
80
|
+
url = matrix_paths.base_uri + matrix_paths.create_room_path
|
81
|
+
room_name_alias = room_name.gsub!(' ','_')
|
82
|
+
data_hash = { creation_content: { 'm.federate': false },
|
83
|
+
name: room_name,
|
84
|
+
preset: 'public_chat',
|
85
|
+
visibility: 'public',
|
86
|
+
room_alias_name: room_name_alias,
|
87
|
+
topic: topic}
|
88
|
+
data = JSON.generate data_hash
|
89
|
+
|
90
|
+
response = HTTP.auth(auth_token).post(url, body: data)
|
91
|
+
|
92
|
+
matrix_interceptor = MatrixInterceptor.new
|
93
|
+
if matrix_interceptor.need_to_wait_and_retry(response)
|
94
|
+
response = HTTP.auth(auth_token).post(url, body: data)
|
95
|
+
end
|
96
|
+
|
97
|
+
JSON.parse(response.body)['room_id']
|
98
|
+
end
|
99
|
+
|
100
|
+
########
|
101
|
+
# SEND #
|
102
|
+
########
|
103
|
+
|
104
|
+
def send_message(room_id, message)
|
105
|
+
|
106
|
+
matrix_paths = MatrixPaths.new
|
107
|
+
randomizer = Random.new
|
108
|
+
txn = randomizer.rand(100)
|
109
|
+
url = matrix_paths.base_uri + matrix_paths.send_message_path(room_id) + txn.to_s
|
110
|
+
|
111
|
+
data_hash = { msgtype: 'm.text', body: message }
|
112
|
+
data = JSON.generate data_hash
|
113
|
+
|
114
|
+
response = HTTP.auth(auth_token).put(url, body: data)
|
115
|
+
|
116
|
+
matrix_interceptor = MatrixInterceptor.new
|
117
|
+
if matrix_interceptor.need_to_wait_and_retry(response)
|
118
|
+
response = HTTP.auth(auth_token).put(url, body: data)
|
119
|
+
end
|
120
|
+
end
|
121
|
+
|
122
|
+
##########
|
123
|
+
# INVITE #
|
124
|
+
##########
|
125
|
+
|
126
|
+
def invite_users_in_room(room_id, users)
|
127
|
+
users.each do |user|
|
128
|
+
invite_in_room(room_id, user)
|
129
|
+
end
|
130
|
+
end
|
131
|
+
|
132
|
+
def invite_in_room(room_id, user_id)
|
133
|
+
|
134
|
+
matrix_paths = MatrixPaths.new
|
135
|
+
url = matrix_paths.base_uri + matrix_paths.invite_in_room_path(room_id)
|
136
|
+
data_hash = { user_id: user_id }
|
137
|
+
data = JSON.generate data_hash
|
138
|
+
|
139
|
+
response = HTTP.auth(auth_token).post(url, body: data)
|
140
|
+
|
141
|
+
matrix_interceptor = MatrixInterceptor.new
|
142
|
+
if matrix_interceptor.need_to_wait_and_retry(response)
|
143
|
+
response = HTTP.auth(auth_token).post(url, body: data)
|
144
|
+
end
|
145
|
+
end
|
146
|
+
|
147
|
+
###################
|
148
|
+
# ROOM MEMBERSHIP #
|
149
|
+
###################
|
150
|
+
|
151
|
+
def join_room(room_id)
|
152
|
+
matrix_paths = MatrixPaths.new
|
153
|
+
url = matrix_paths.base_uri + matrix_paths.join_room_path(room_id)
|
154
|
+
|
155
|
+
response = HTTP.auth(auth_token).post(url)
|
156
|
+
|
157
|
+
matrix_interceptor = MatrixInterceptor.new
|
158
|
+
if matrix_interceptor.need_to_wait_and_retry(response)
|
159
|
+
response = HTTP.auth(auth_token).post(url)
|
160
|
+
end
|
161
|
+
end
|
162
|
+
|
163
|
+
def leave_room(room_id)
|
164
|
+
matrix_paths = MatrixPaths.new
|
165
|
+
url = matrix_paths.base_uri + matrix_paths.leave_room_path(room_id)
|
166
|
+
|
167
|
+
response = HTTP.auth(auth_token).post(url)
|
168
|
+
|
169
|
+
matrix_interceptor = MatrixInterceptor.new
|
170
|
+
if matrix_interceptor.need_to_wait_and_retry(response)
|
171
|
+
response = HTTP.auth(auth_token).post(url)
|
172
|
+
end
|
173
|
+
end
|
174
|
+
|
175
|
+
###################
|
176
|
+
# ROOM MANAGEMENT #
|
177
|
+
###################
|
178
|
+
|
179
|
+
def change_room_visibility(room_id, visibility)
|
180
|
+
matrix_paths = MatrixPaths.new
|
181
|
+
url = matrix_paths.base_uri + matrix_paths.change_room_visibility_path(room_id)
|
182
|
+
|
183
|
+
data_hash = { join_rule: visibility }
|
184
|
+
data = JSON.generate data_hash
|
185
|
+
|
186
|
+
response = HTTP.auth(auth_token).put(url, body: data)
|
187
|
+
|
188
|
+
matrix_interceptor = MatrixInterceptor.new
|
189
|
+
if matrix_interceptor.need_to_wait_and_retry(response)
|
190
|
+
response = HTTP.auth(auth_token).put(url)
|
191
|
+
end
|
192
|
+
end
|
193
|
+
end
|
194
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative 'matrix_paths'
|
4
|
+
|
5
|
+
module Citadel
|
6
|
+
class Authenticator
|
7
|
+
def get_token(login, password)
|
8
|
+
matrix_paths = MatrixPaths.new
|
9
|
+
url = matrix_paths.base_uri + matrix_paths.login_path
|
10
|
+
data_hash = { type: 'm.login.password', user: login, password: password }
|
11
|
+
data = JSON.generate data_hash
|
12
|
+
response = HTTP.post(url, body: data)
|
13
|
+
JSON.parse(response.body)['access_token']
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Citadel
|
4
|
+
class MatrixInterceptor
|
5
|
+
def need_to_wait_and_retry(response)
|
6
|
+
wait_time = JSON.parse(response.body)['retry_after_ms']
|
7
|
+
if wait_time
|
8
|
+
sleep((wait_time / 1000).ceil + 1)
|
9
|
+
return true
|
10
|
+
else
|
11
|
+
return false
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
@@ -0,0 +1,46 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Citadel
|
4
|
+
class MatrixPaths
|
5
|
+
|
6
|
+
def base_uri
|
7
|
+
Citadel.tenant_url + '/_matrix/client/r0'
|
8
|
+
end
|
9
|
+
|
10
|
+
def login_path
|
11
|
+
'/login'
|
12
|
+
end
|
13
|
+
|
14
|
+
def create_room_path
|
15
|
+
'/createRoom'
|
16
|
+
end
|
17
|
+
|
18
|
+
def send_message_path(room_id)
|
19
|
+
'/rooms/' + room_id + '/send/m.room.message/'
|
20
|
+
end
|
21
|
+
|
22
|
+
def invite_in_room_path(room_id)
|
23
|
+
'/rooms/' + room_id + '/invite'
|
24
|
+
end
|
25
|
+
|
26
|
+
def list_public_rooms_path
|
27
|
+
'/publicRooms' + '?limit=' + Citadel.public_rooms_limit
|
28
|
+
end
|
29
|
+
|
30
|
+
def list_joined_rooms_path
|
31
|
+
'/joined_rooms'
|
32
|
+
end
|
33
|
+
|
34
|
+
def join_room_path(room_id)
|
35
|
+
'/rooms/' + room_id + '/join'
|
36
|
+
end
|
37
|
+
|
38
|
+
def leave_room_path(room_id)
|
39
|
+
'/rooms/' + room_id + '/leave'
|
40
|
+
end
|
41
|
+
|
42
|
+
def change_room_visibility_path(room_id)
|
43
|
+
'/rooms/' + room_id + '/state/m.room.join_rules'
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
metadata
ADDED
@@ -0,0 +1,125 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: citadel-ruby-client
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.2.1
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Claire Dufetrelle
|
8
|
+
autorequire:
|
9
|
+
bindir: exe
|
10
|
+
cert_chain: []
|
11
|
+
date: 2018-09-21 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: bundler
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '1.16'
|
20
|
+
type: :development
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - "~>"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '1.16'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: rake
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - "~>"
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '10.0'
|
34
|
+
type: :development
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - "~>"
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '10.0'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: rspec
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - "~>"
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '3.0'
|
48
|
+
type: :development
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - "~>"
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '3.0'
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: http
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - "~>"
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '3.3'
|
62
|
+
type: :runtime
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - "~>"
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '3.3'
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: json
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
72
|
+
requirements:
|
73
|
+
- - "~>"
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
version: '2.1'
|
76
|
+
- - ">="
|
77
|
+
- !ruby/object:Gem::Version
|
78
|
+
version: 1.8.3
|
79
|
+
type: :runtime
|
80
|
+
prerelease: false
|
81
|
+
version_requirements: !ruby/object:Gem::Requirement
|
82
|
+
requirements:
|
83
|
+
- - "~>"
|
84
|
+
- !ruby/object:Gem::Version
|
85
|
+
version: '2.1'
|
86
|
+
- - ">="
|
87
|
+
- !ruby/object:Gem::Version
|
88
|
+
version: 1.8.3
|
89
|
+
description: A simple way to publish messages on Citadel
|
90
|
+
email:
|
91
|
+
- claire.dufetrelle@fabernovel.com
|
92
|
+
executables: []
|
93
|
+
extensions: []
|
94
|
+
extra_rdoc_files: []
|
95
|
+
files:
|
96
|
+
- lib/citadel.rb
|
97
|
+
- lib/citadel/authenticator.rb
|
98
|
+
- lib/citadel/matrix_interceptor.rb
|
99
|
+
- lib/citadel/matrix_paths.rb
|
100
|
+
- lib/citadel/version.rb
|
101
|
+
homepage: http://rubygems.org/gems/citadel
|
102
|
+
licenses:
|
103
|
+
- MIT
|
104
|
+
metadata: {}
|
105
|
+
post_install_message:
|
106
|
+
rdoc_options: []
|
107
|
+
require_paths:
|
108
|
+
- lib
|
109
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
110
|
+
requirements:
|
111
|
+
- - ">="
|
112
|
+
- !ruby/object:Gem::Version
|
113
|
+
version: '0'
|
114
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
115
|
+
requirements:
|
116
|
+
- - ">="
|
117
|
+
- !ruby/object:Gem::Version
|
118
|
+
version: '0'
|
119
|
+
requirements: []
|
120
|
+
rubyforge_project:
|
121
|
+
rubygems_version: 2.5.2
|
122
|
+
signing_key:
|
123
|
+
specification_version: 4
|
124
|
+
summary: Citadel Ruby client
|
125
|
+
test_files: []
|