selfsdk 0.0.179 → 0.0.184
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 +4 -4
- data/lib/chat/file_object.rb +97 -0
- data/lib/chat/group.rb +51 -0
- data/lib/chat/message.rb +101 -0
- data/lib/crypto.rb +78 -40
- data/lib/messages/authentication_req.rb +2 -2
- data/lib/messages/base.rb +3 -2
- data/lib/messages/chat.rb +28 -0
- data/lib/messages/chat_invite.rb +19 -0
- data/lib/messages/chat_join.rb +19 -0
- data/lib/messages/chat_message.rb +23 -0
- data/lib/messages/chat_message_delivered.rb +21 -0
- data/lib/messages/chat_message_read.rb +20 -0
- data/lib/messages/chat_remove.rb +19 -0
- data/lib/messages/fact_request.rb +5 -3
- data/lib/messages/fact_response.rb +1 -1
- data/lib/messages/message.rb +25 -1
- data/lib/messaging.rb +37 -18
- data/lib/selfsdk.rb +6 -0
- data/lib/services/chat.rb +210 -0
- data/lib/services/facts.rb +1 -0
- data/lib/services/messaging.rb +8 -9
- data/lib/sources.rb +9 -2
- metadata +14 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 2c16f1734a708b0ebd37ca4fa0cea0e48db09344d4efb0654e5b4df6a37fd2d4
|
4
|
+
data.tar.gz: 32313fa1c28a57370c43d7100bdacc06bad28f0722ba0589a63c24bd0327bfd2
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 9a015baa1ed364efcc422af5de6a54f87cbb953cdb45de7f397aa8cd2273b99c8ce4f6fbba0fc62f0ef803f38edf8155fbb1e9e14042b4f4ff76b391147da614
|
7
|
+
data.tar.gz: dfec1973db212e016774292d57bda452727cadd201ecdb80ab0f507a97ff3df244887ffde06704a618de63e0d101c75b7e8c879ff983654892d9496a50db7889
|
@@ -0,0 +1,97 @@
|
|
1
|
+
# Copyright 2020 Self Group Ltd. All Rights Reserved.
|
2
|
+
|
3
|
+
# frozen_string_literal: true
|
4
|
+
require 'open-uri'
|
5
|
+
|
6
|
+
module SelfSDK
|
7
|
+
module Chat
|
8
|
+
class FileObject
|
9
|
+
attr_accessor :link, :mime, :content, :key, :nonce, :ciphertext
|
10
|
+
|
11
|
+
def initialize(token, url)
|
12
|
+
@token = token
|
13
|
+
@url = url
|
14
|
+
end
|
15
|
+
|
16
|
+
def build_from_data(name, data, mime)
|
17
|
+
@key = SelfCrypto::Util.aead_xchacha20poly1305_ietf_keygen
|
18
|
+
@nonce = SelfCrypto::Util.aead_xchacha20poly1305_ietf_nonce
|
19
|
+
@content = data
|
20
|
+
@name = name
|
21
|
+
@mime = mime
|
22
|
+
|
23
|
+
# encrypt the object
|
24
|
+
@ciphertext = SelfCrypto::Util.aead_xchacha20poly1305_ietf_encrypt(@key, @nonce, @content)
|
25
|
+
|
26
|
+
# Upload
|
27
|
+
remote_object = upload(ciphertext)
|
28
|
+
@link = "#{@url}/v1/objects/#{remote_object["id"]}"
|
29
|
+
@expires = remote_object["expires"]
|
30
|
+
|
31
|
+
self
|
32
|
+
end
|
33
|
+
|
34
|
+
# Incoming objects
|
35
|
+
def build_from_object(input)
|
36
|
+
# Download from CDN
|
37
|
+
ciphertext = URI.open(input[:link], "Authorization" => "Bearer #{@token}").read
|
38
|
+
|
39
|
+
@content = ciphertext
|
40
|
+
@key = nil
|
41
|
+
@nonce = nil
|
42
|
+
if input.key?(:key) && !input[:key].empty?
|
43
|
+
# Decrypt
|
44
|
+
composed_key = extract_key(input[:key])
|
45
|
+
@key = composed_key[:key]
|
46
|
+
@nonce = composed_key[:nonce]
|
47
|
+
|
48
|
+
@content = SelfCrypto::Util.aead_xchacha20poly1305_ietf_decrypt(@key, @nonce, ciphertext)
|
49
|
+
end
|
50
|
+
|
51
|
+
@name = input[:name]
|
52
|
+
@link = input[:link]
|
53
|
+
@mime = input[:mime]
|
54
|
+
@expires = input[:expires]
|
55
|
+
|
56
|
+
self
|
57
|
+
end
|
58
|
+
|
59
|
+
def to_payload
|
60
|
+
{
|
61
|
+
name: @name,
|
62
|
+
link: @link,
|
63
|
+
key: build_key(@key, @nonce),
|
64
|
+
mime: @mime,
|
65
|
+
expires: @expires
|
66
|
+
}
|
67
|
+
end
|
68
|
+
|
69
|
+
def save(path)
|
70
|
+
File.open(path, 'wb') { |file| file.write(@content) }
|
71
|
+
end
|
72
|
+
|
73
|
+
private
|
74
|
+
|
75
|
+
def upload(ciphertext)
|
76
|
+
uri = URI.parse("#{@url}/v1/objects")
|
77
|
+
https = Net::HTTP.new(uri.host, uri.port)
|
78
|
+
https.use_ssl = true
|
79
|
+
req = Net::HTTP::Post.new(uri.path)
|
80
|
+
req["Authorization"] = "Bearer #{@token}"
|
81
|
+
req.body = ciphertext.force_encoding("UTF-8")
|
82
|
+
res = https.request(req)
|
83
|
+
JSON.parse(res.body)
|
84
|
+
end
|
85
|
+
|
86
|
+
def build_key(key, nonce)
|
87
|
+
Base64.urlsafe_encode64("#{key}#{nonce}", padding: false)
|
88
|
+
end
|
89
|
+
|
90
|
+
def extract_key(shareable_key)
|
91
|
+
k = Base64.urlsafe_decode64(shareable_key)
|
92
|
+
{ key: k[0, 32],
|
93
|
+
nonce: k[32, (k.length - 32)] }
|
94
|
+
end
|
95
|
+
end
|
96
|
+
end
|
97
|
+
end
|
data/lib/chat/group.rb
ADDED
@@ -0,0 +1,51 @@
|
|
1
|
+
# Copyright 2020 Self Group Ltd. All Rights Reserved.
|
2
|
+
|
3
|
+
# frozen_string_literal: true
|
4
|
+
|
5
|
+
module SelfSDK
|
6
|
+
module Chat
|
7
|
+
class Group
|
8
|
+
attr_accessor :gid, :name, :members, :payload
|
9
|
+
|
10
|
+
def initialize(chat, payload)
|
11
|
+
@chat = chat
|
12
|
+
@payload = payload
|
13
|
+
@gid = payload[:gid]
|
14
|
+
@members = payload[:members]
|
15
|
+
@name = payload[:name]
|
16
|
+
@link = payload[:link] if payload.key? :link
|
17
|
+
@key = payload[:key] if payload.key? :key
|
18
|
+
@mime = payload[:mime] if payload.key? :mime
|
19
|
+
end
|
20
|
+
|
21
|
+
# Sends an invitation to the specified user to join
|
22
|
+
# the group.
|
23
|
+
#
|
24
|
+
# @param user [String] user to be invited.
|
25
|
+
def invite(user)
|
26
|
+
raise "invalid input" if user.empty?
|
27
|
+
|
28
|
+
@members << user
|
29
|
+
@chat.invite(@gid, @name, @members)
|
30
|
+
end
|
31
|
+
|
32
|
+
# Sends a message to leave the current group.
|
33
|
+
def leave
|
34
|
+
@chat.leave(@gid, @members)
|
35
|
+
end
|
36
|
+
|
37
|
+
# Sends a confi¡rmation message that has joined the group.
|
38
|
+
def join
|
39
|
+
@chat.join(@gid, @members)
|
40
|
+
end
|
41
|
+
|
42
|
+
# Sends a message to the current group
|
43
|
+
#
|
44
|
+
# @param body [String] message body to be sent.
|
45
|
+
def message(body, opts = {})
|
46
|
+
opts[:gid] = @gid
|
47
|
+
@chat.message(@members, body, opts)
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
data/lib/chat/message.rb
ADDED
@@ -0,0 +1,101 @@
|
|
1
|
+
# Copyright 2020 Self Group Ltd. All Rights Reserved.
|
2
|
+
|
3
|
+
# frozen_string_literal: true
|
4
|
+
|
5
|
+
module SelfSDK
|
6
|
+
module Chat
|
7
|
+
class Message
|
8
|
+
attr_accessor :gid, :body, :from, :payload, :recipients, :objects
|
9
|
+
|
10
|
+
def initialize(chat, recipients, payload, auth_token, self_url)
|
11
|
+
@chat = chat
|
12
|
+
@recipients = recipients
|
13
|
+
@recipients = [@recipients] if @recipients.is_a? String
|
14
|
+
@gid = payload[:gid] if payload.key? :gid
|
15
|
+
@payload = payload
|
16
|
+
@payload[:jti] = SecureRandom.uuid unless @payload.include?(:jti)
|
17
|
+
@body = @payload[:msg]
|
18
|
+
@from = @payload[:iss]
|
19
|
+
return unless @payload.key?(:objects)
|
20
|
+
|
21
|
+
@objects = []
|
22
|
+
@payload[:objects].each do |o|
|
23
|
+
@objects << if o.key? :link
|
24
|
+
SelfSDK::Chat::FileObject.new(auth_token, self_url).build_from_object(o)
|
25
|
+
else
|
26
|
+
SelfSDK::Chat::FileObject.new(auth_token, self_url).build_from_data(o[:name], o[:data], o[:mime])
|
27
|
+
end
|
28
|
+
end
|
29
|
+
@payload[:objects] = []
|
30
|
+
@payload[:objects] = payload[:raw_objects] if payload[:raw_objects]
|
31
|
+
@objects.each do |o|
|
32
|
+
@payload[:objects] << o.to_payload
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
# delete! deletes the current message from the conversation.
|
37
|
+
def delete!
|
38
|
+
@chat.delete(@recipients, @payload[:jti], @payload[:gid])
|
39
|
+
end
|
40
|
+
|
41
|
+
# edit changes the current message body for all participants.
|
42
|
+
#
|
43
|
+
# @param body [string] the new message body.
|
44
|
+
def edit(body)
|
45
|
+
return if @recipients == [@chat.app_id]
|
46
|
+
|
47
|
+
@body = body
|
48
|
+
@chat.edit(@recipients, @payload[:jti], body, @payload[:gid])
|
49
|
+
end
|
50
|
+
|
51
|
+
# mark_as_delivered marks the current message as delivered if
|
52
|
+
# it comes from another recipient.
|
53
|
+
def mark_as_delivered
|
54
|
+
return if @recipients != [@chat.app_id]
|
55
|
+
|
56
|
+
@chat.delivered(@payload[:iss], @payload[:jti], @payload[:gid])
|
57
|
+
end
|
58
|
+
|
59
|
+
# mark_as_read marks the current message as read if it comes from
|
60
|
+
# another recipient.
|
61
|
+
def mark_as_read
|
62
|
+
return if @recipients != [@chat.app_id]
|
63
|
+
|
64
|
+
@chat.read(@payload[:iss], @payload[:jti], @payload[:gid])
|
65
|
+
end
|
66
|
+
|
67
|
+
# respond sends a direct response to the current message.
|
68
|
+
#
|
69
|
+
# @param body [string] the new message body.
|
70
|
+
#
|
71
|
+
# @return ChatMessage
|
72
|
+
def respond(body)
|
73
|
+
opts = {}
|
74
|
+
opts[:aud] = @payload[:gid] if @payload.key? :gid
|
75
|
+
opts[:gid] = @payload[:gid] if @payload.key? :gid
|
76
|
+
opts[:rid] = @payload[:jti]
|
77
|
+
|
78
|
+
to = @recipients
|
79
|
+
to = [@payload[:iss]] if @recipients == [@chat.app_id]
|
80
|
+
|
81
|
+
@chat.message(to, body, opts)
|
82
|
+
end
|
83
|
+
|
84
|
+
# message sends a new message to the same conversation as the current message.
|
85
|
+
#
|
86
|
+
# @param body [string] the new message body.
|
87
|
+
#
|
88
|
+
# @return ChatMessage
|
89
|
+
def message(body, opts = {})
|
90
|
+
opts[:aud] = @payload[:gid] if @payload.key? :gid
|
91
|
+
opts[:gid] = @payload[:gid] if @payload.key? :gid
|
92
|
+
|
93
|
+
to = opts[:recipients] if opts.key? :recipients
|
94
|
+
to = [@payload[:iss]] if @recipients == [@chat.app_id]
|
95
|
+
|
96
|
+
@chat.message(to, body, opts)
|
97
|
+
end
|
98
|
+
|
99
|
+
end
|
100
|
+
end
|
101
|
+
end
|
data/lib/crypto.rb
CHANGED
@@ -32,9 +32,82 @@ module SelfSDK
|
|
32
32
|
end
|
33
33
|
end
|
34
34
|
|
35
|
-
def encrypt(message,
|
36
|
-
|
35
|
+
def encrypt(message, recipients)
|
36
|
+
::SelfSDK.logger.debug('encrypting a message')
|
37
37
|
|
38
|
+
# create a group session and set the identity of the account youre using
|
39
|
+
::SelfSDK.logger.debug('create a group session and set the identity of the account youre using')
|
40
|
+
gs = SelfCrypto::GroupSession.new("#{@client.jwt.id}:#{@device}")
|
41
|
+
|
42
|
+
sessions = {}
|
43
|
+
::SelfSDK.logger.debug('managing sessions with all recipients')
|
44
|
+
recipients.each do |r|
|
45
|
+
session_file_name = session_path(r[:id], r[:device_id])
|
46
|
+
session_with_bob = nil
|
47
|
+
|
48
|
+
begin
|
49
|
+
session_with_bob = get_outbound_session_with_bob(r[:id], r[:device_id], session_file_name)
|
50
|
+
rescue => e
|
51
|
+
::SelfSDK.logger.warn(" there is a problem adding group participant #{r[:id]}:#{r[:device_id]}, skipping...")
|
52
|
+
::SelfSDK.logger.warn(e)
|
53
|
+
next
|
54
|
+
end
|
55
|
+
|
56
|
+
::SelfSDK.logger.debug(" adding group participant #{r[:id]}:#{r[:device_id]}")
|
57
|
+
gs.add_participant("#{r[:id]}:#{r[:device_id]}", session_with_bob)
|
58
|
+
sessions[session_file_name] = session_with_bob
|
59
|
+
end
|
60
|
+
|
61
|
+
# 5) encrypt a message
|
62
|
+
::SelfSDK.logger.debug("group encrypting message")
|
63
|
+
ct = gs.encrypt(message).to_s
|
64
|
+
|
65
|
+
# 6) store the session to a file
|
66
|
+
::SelfSDK.logger.debug("storing sessions")
|
67
|
+
sessions.each do |session_file_name, session_with_bob|
|
68
|
+
File.write(session_file_name, session_with_bob.to_pickle(@storage_key))
|
69
|
+
end
|
70
|
+
|
71
|
+
ct
|
72
|
+
end
|
73
|
+
|
74
|
+
def decrypt(message, sender, sender_device)
|
75
|
+
::SelfSDK.logger.debug("decrypting a message")
|
76
|
+
session_file_name = session_path(sender, sender_device)
|
77
|
+
|
78
|
+
::SelfSDK.logger.debug("loading sessions")
|
79
|
+
session_with_bob = get_inbound_session_with_bob(message, session_file_name)
|
80
|
+
|
81
|
+
# 8) create a group session and set the identity of the account you're using
|
82
|
+
::SelfSDK.logger.debug("create a group session and set the identity of the account #{@client.jwt.id}:#{@device}")
|
83
|
+
gs = SelfCrypto::GroupSession.new("#{@client.jwt.id}:#{@device}")
|
84
|
+
|
85
|
+
# 9) add all recipients and their sessions
|
86
|
+
::SelfSDK.logger.debug("add all recipients and their sessions #{@sender}:#{@sender_device}")
|
87
|
+
gs.add_participant("#{sender}:#{sender_device}", session_with_bob)
|
88
|
+
|
89
|
+
# 10) decrypt the message ciphertext
|
90
|
+
::SelfSDK.logger.debug("decrypt the message ciphertext")
|
91
|
+
pt = gs.decrypt("#{sender}:#{sender_device}", message).to_s
|
92
|
+
|
93
|
+
# 11) store the session to a file
|
94
|
+
::SelfSDK.logger.debug("store the session to a file")
|
95
|
+
File.write(session_file_name, session_with_bob.to_pickle(@storage_key))
|
96
|
+
|
97
|
+
pt
|
98
|
+
end
|
99
|
+
|
100
|
+
private
|
101
|
+
|
102
|
+
def account_path
|
103
|
+
"#{@storage_folder}/account.pickle"
|
104
|
+
end
|
105
|
+
|
106
|
+
def session_path(selfid, device)
|
107
|
+
"#{@storage_folder}/#{selfid}:#{device}-session.pickle"
|
108
|
+
end
|
109
|
+
|
110
|
+
def get_outbound_session_with_bob(recipient, recipient_device, session_file_name)
|
38
111
|
if File.exist?(session_file_name)
|
39
112
|
# 2a) if bob's session file exists load the pickle from the file
|
40
113
|
session_with_bob = SelfCrypto::Session.from_pickle(File.read(session_file_name), @storage_key)
|
@@ -61,24 +134,10 @@ module SelfSDK
|
|
61
134
|
session_with_bob = @account.outbound_session(curve25519_identity_key, one_time_key)
|
62
135
|
end
|
63
136
|
|
64
|
-
|
65
|
-
gs = SelfCrypto::GroupSession.new("#{@client.jwt.id}:#{@device}")
|
66
|
-
|
67
|
-
# 4) add all recipients and their sessions
|
68
|
-
gs.add_participant("#{recipient}:#{recipient_device}", session_with_bob)
|
69
|
-
|
70
|
-
# 5) encrypt a message
|
71
|
-
ct = gs.encrypt(message).to_s
|
72
|
-
|
73
|
-
# 6) store the session to a file
|
74
|
-
File.write(session_file_name, session_with_bob.to_pickle(@storage_key))
|
75
|
-
|
76
|
-
ct
|
137
|
+
session_with_bob
|
77
138
|
end
|
78
139
|
|
79
|
-
def
|
80
|
-
session_file_name = session_path(sender, sender_device)
|
81
|
-
|
140
|
+
def get_inbound_session_with_bob(message, session_file_name)
|
82
141
|
if File.exist?(session_file_name)
|
83
142
|
# 7a) if carol's session file exists load the pickle from the file
|
84
143
|
session_with_bob = SelfCrypto::Session.from_pickle(File.read(session_file_name), @storage_key)
|
@@ -113,29 +172,8 @@ module SelfSDK
|
|
113
172
|
File.write(account_path, @account.to_pickle(@storage_key))
|
114
173
|
end
|
115
174
|
|
116
|
-
|
117
|
-
gs = SelfCrypto::GroupSession.new("#{@client.jwt.id}:#{@device}")
|
118
|
-
|
119
|
-
# 9) add all recipients and their sessions
|
120
|
-
gs.add_participant("#{sender}:#{sender_device}", session_with_bob)
|
121
|
-
|
122
|
-
# 10) decrypt the message ciphertext
|
123
|
-
pt = gs.decrypt("#{sender}:#{sender_device}", message).to_s
|
124
|
-
|
125
|
-
# 11) store the session to a file
|
126
|
-
File.write(session_file_name, session_with_bob.to_pickle(@storage_key))
|
127
|
-
|
128
|
-
pt
|
175
|
+
session_with_bob
|
129
176
|
end
|
130
177
|
|
131
|
-
private
|
132
|
-
|
133
|
-
def account_path
|
134
|
-
"#{@storage_folder}/account.pickle"
|
135
|
-
end
|
136
|
-
|
137
|
-
def session_path(selfid, device)
|
138
|
-
"#{@storage_folder}/#{selfid}:#{device}-session.pickle"
|
139
|
-
end
|
140
178
|
end
|
141
179
|
end
|
@@ -43,10 +43,10 @@ module SelfSDK
|
|
43
43
|
|
44
44
|
def proto(to_device)
|
45
45
|
m = SelfMsg::Message.new
|
46
|
-
m.id =
|
46
|
+
m.id = @id
|
47
47
|
m.sender = "#{@jwt.id}:#{@messaging.device_id}"
|
48
48
|
m.recipient = "#{@to}:#{to_device}"
|
49
|
-
m.ciphertext = encrypt_message(@jwt.prepare(body), @to, to_device)
|
49
|
+
m.ciphertext = encrypt_message(@jwt.prepare(body), [{ id: @to, device_id: to_device }])
|
50
50
|
m
|
51
51
|
end
|
52
52
|
|
data/lib/messages/base.rb
CHANGED
@@ -10,6 +10,7 @@ module SelfSDK
|
|
10
10
|
:description, :sub, :exp_timeout
|
11
11
|
|
12
12
|
def initialize(messaging)
|
13
|
+
@intermediary = nil
|
13
14
|
@client = messaging.client
|
14
15
|
@jwt = @client.jwt
|
15
16
|
@messaging = messaging
|
@@ -44,8 +45,8 @@ module SelfSDK
|
|
44
45
|
res.first
|
45
46
|
end
|
46
47
|
|
47
|
-
def encrypt_message(message,
|
48
|
-
@messaging.encryption_client.encrypt(message,
|
48
|
+
def encrypt_message(message, recipients)
|
49
|
+
@messaging.encryption_client.encrypt(message, recipients)
|
49
50
|
end
|
50
51
|
|
51
52
|
def unauthorized?
|
@@ -0,0 +1,28 @@
|
|
1
|
+
# Copyright 2020 Self Group Ltd. All Rights Reserved.
|
2
|
+
|
3
|
+
# frozen_string_literal: true
|
4
|
+
|
5
|
+
require 'self_msgproto'
|
6
|
+
require_relative 'base'
|
7
|
+
require_relative '../ntptime'
|
8
|
+
|
9
|
+
module SelfSDK
|
10
|
+
module Messages
|
11
|
+
class Chat < Base
|
12
|
+
def parse(input, envelope=nil)
|
13
|
+
@input = input
|
14
|
+
@payload = get_payload input
|
15
|
+
@id = @payload[:jti]
|
16
|
+
@from = @payload[:iss]
|
17
|
+
@to = @payload[:sub]
|
18
|
+
@audience = payload[:aud]
|
19
|
+
@expires = @payload[:exp]
|
20
|
+
|
21
|
+
if envelope
|
22
|
+
issuer = envelope.sender.split(":")
|
23
|
+
@from_device = issuer.last
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
# Copyright 2020 Self Group Ltd. All Rights Reserved.
|
2
|
+
|
3
|
+
# frozen_string_literal: true
|
4
|
+
|
5
|
+
require_relative 'chat'
|
6
|
+
|
7
|
+
module SelfSDK
|
8
|
+
module Messages
|
9
|
+
class ChatInvite < Chat
|
10
|
+
MSG_TYPE = "chat.invite"
|
11
|
+
|
12
|
+
def parse(input, envelope=nil)
|
13
|
+
super
|
14
|
+
@typ = MSG_TYPE
|
15
|
+
end
|
16
|
+
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
# Copyright 2020 Self Group Ltd. All Rights Reserved.
|
2
|
+
|
3
|
+
# frozen_string_literal: true
|
4
|
+
|
5
|
+
require_relative 'chat'
|
6
|
+
|
7
|
+
module SelfSDK
|
8
|
+
module Messages
|
9
|
+
class ChatJoin < Chat
|
10
|
+
MSG_TYPE = "chat.join"
|
11
|
+
|
12
|
+
def parse(input, envelope=nil)
|
13
|
+
super
|
14
|
+
@typ = MSG_TYPE
|
15
|
+
end
|
16
|
+
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
# Copyright 2020 Self Group Ltd. All Rights Reserved.
|
2
|
+
|
3
|
+
# frozen_string_literal: true
|
4
|
+
|
5
|
+
require_relative 'chat'
|
6
|
+
|
7
|
+
module SelfSDK
|
8
|
+
module Messages
|
9
|
+
class ChatMessage < Chat
|
10
|
+
MSG_TYPE = "chat.message"
|
11
|
+
DEFAULT_EXP_TIMEOUT = 900
|
12
|
+
|
13
|
+
attr_accessor :body
|
14
|
+
|
15
|
+
def parse(input, envelope=nil)
|
16
|
+
super
|
17
|
+
@typ = MSG_TYPE
|
18
|
+
@body = @payload[:msg]
|
19
|
+
end
|
20
|
+
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
# Copyright 2020 Self Group Ltd. All Rights Reserved.
|
2
|
+
|
3
|
+
# frozen_string_literal: true
|
4
|
+
|
5
|
+
require 'self_msgproto'
|
6
|
+
require_relative 'chat'
|
7
|
+
require_relative '../ntptime'
|
8
|
+
|
9
|
+
module SelfSDK
|
10
|
+
module Messages
|
11
|
+
class ChatMessageDelivered < Chat
|
12
|
+
MSG_TYPE = "chat.message.delivered"
|
13
|
+
DEFAULT_EXP_TIMEOUT = 900
|
14
|
+
|
15
|
+
def parse(input, envelope=nil)
|
16
|
+
super
|
17
|
+
@typ = MSG_TYPE
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
# Copyright 2020 Self Group Ltd. All Rights Reserved.
|
2
|
+
|
3
|
+
# frozen_string_literal: true
|
4
|
+
|
5
|
+
require_relative 'chat'
|
6
|
+
|
7
|
+
module SelfSDK
|
8
|
+
module Messages
|
9
|
+
class ChatMessageRead < Chat
|
10
|
+
MSG_TYPE = "chat.message.read"
|
11
|
+
DEFAULT_EXP_TIMEOUT = 900
|
12
|
+
|
13
|
+
def parse(input, envelope=nil)
|
14
|
+
super
|
15
|
+
@typ = MSG_TYPE
|
16
|
+
end
|
17
|
+
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
# Copyright 2020 Self Group Ltd. All Rights Reserved.
|
2
|
+
|
3
|
+
# frozen_string_literal: true
|
4
|
+
|
5
|
+
require_relative 'chat'
|
6
|
+
|
7
|
+
module SelfSDK
|
8
|
+
module Messages
|
9
|
+
class ChatRemove < Chat
|
10
|
+
MSG_TYPE = "chat.remove"
|
11
|
+
|
12
|
+
def parse(input, envelope=nil)
|
13
|
+
super
|
14
|
+
@typ = MSG_TYPE
|
15
|
+
end
|
16
|
+
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
@@ -34,6 +34,7 @@ module SelfSDK
|
|
34
34
|
@options = opts.fetch(:options, false)
|
35
35
|
@description = opts.include?(:description) ? opts[:description] : nil
|
36
36
|
@exp_timeout = opts.fetch(:exp_timeout, DEFAULT_EXP_TIMEOUT)
|
37
|
+
@allowed_for = opts.fetch(:allowed_for, nil)
|
37
38
|
|
38
39
|
@intermediary = if opts.include?(:intermediary)
|
39
40
|
opts[:intermediary]
|
@@ -89,6 +90,7 @@ module SelfSDK
|
|
89
90
|
}
|
90
91
|
b[:options] = @options unless (@options.nil? || @options == false)
|
91
92
|
b[:description] = @description unless (@description.nil? || @description.empty?)
|
93
|
+
b[:allowed_until] = (SelfSDK::Time.now + @allowed_for).strftime('%FT%TZ') unless @allowed_for.nil?
|
92
94
|
b
|
93
95
|
end
|
94
96
|
|
@@ -98,14 +100,14 @@ module SelfSDK
|
|
98
100
|
@to_device = to_device
|
99
101
|
if @intermediary.nil?
|
100
102
|
recipient = "#{@to}:#{@to_device}"
|
101
|
-
ciphertext = encrypt_message(@jwt.prepare(body), @to, @to_device)
|
103
|
+
ciphertext = encrypt_message(@jwt.prepare(body), [{id: @to, device_id: @to_device}])
|
102
104
|
else
|
103
105
|
recipient = "#{@intermediary}:#{@to_device}"
|
104
|
-
ciphertext = encrypt_message(@jwt.prepare(body), @intermediary, @to_device)
|
106
|
+
ciphertext = encrypt_message(@jwt.prepare(body), [{id: @intermediary, device_id: @to_device}])
|
105
107
|
end
|
106
108
|
|
107
109
|
m = SelfMsg::Message.new
|
108
|
-
m.id =
|
110
|
+
m.id = @id
|
109
111
|
m.sender = "#{@jwt.id}:#{@messaging.device_id}"
|
110
112
|
m.recipient = recipient
|
111
113
|
m.ciphertext = ciphertext
|
@@ -91,7 +91,7 @@ module SelfSDK
|
|
91
91
|
id: SecureRandom.uuid,
|
92
92
|
sender: "#{@jwt.id}:#{@messaging.device_id}",
|
93
93
|
recipient: "#{@to}:#{@to_device}",
|
94
|
-
ciphertext: encrypt_message(@jwt.prepare(body), @to, @to_device)
|
94
|
+
ciphertext: encrypt_message(@jwt.prepare(body), [{id: @to, device_id: @to_device}])
|
95
95
|
)
|
96
96
|
end
|
97
97
|
end
|
data/lib/messages/message.rb
CHANGED
@@ -6,6 +6,12 @@ require_relative "fact_request"
|
|
6
6
|
require_relative "fact_response"
|
7
7
|
require_relative "authentication_resp"
|
8
8
|
require_relative "authentication_req"
|
9
|
+
require_relative "chat_message"
|
10
|
+
require_relative "chat_message_read"
|
11
|
+
require_relative "chat_message_delivered"
|
12
|
+
require_relative "chat_invite"
|
13
|
+
require_relative "chat_join"
|
14
|
+
require_relative "chat_remove"
|
9
15
|
|
10
16
|
module SelfSDK
|
11
17
|
module Messages
|
@@ -35,8 +41,26 @@ module SelfSDK
|
|
35
41
|
when "identities.authenticate.req"
|
36
42
|
m = AuthenticationReq.new(messaging)
|
37
43
|
m.parse(body, envelope)
|
44
|
+
when SelfSDK::Messages::ChatMessage::MSG_TYPE
|
45
|
+
m = ChatMessage.new(messaging)
|
46
|
+
m.parse(body, envelope)
|
47
|
+
when SelfSDK::Messages::ChatMessageDelivered::MSG_TYPE
|
48
|
+
m = ChatMessageDelivered.new(messaging)
|
49
|
+
m.parse(body, envelope)
|
50
|
+
when SelfSDK::Messages::ChatMessageRead::MSG_TYPE
|
51
|
+
m = ChatMessageRead.new(messaging)
|
52
|
+
m.parse(body, envelope)
|
53
|
+
when SelfSDK::Messages::ChatInvite::MSG_TYPE
|
54
|
+
m = ChatInvite.new(messaging)
|
55
|
+
m.parse(body, envelope)
|
56
|
+
when SelfSDK::Messages::ChatRemove::MSG_TYPE
|
57
|
+
m = ChatRemove.new(messaging)
|
58
|
+
m.parse(body, envelope)
|
59
|
+
when SelfSDK::Messages::ChatJoin::MSG_TYPE
|
60
|
+
m = ChatJoin.new(messaging)
|
61
|
+
m.parse(body, envelope)
|
38
62
|
else
|
39
|
-
raise StandardError.new("Invalid message type.")
|
63
|
+
raise StandardError.new("Invalid message type #{payload[:typ]}.")
|
40
64
|
end
|
41
65
|
return m
|
42
66
|
end
|
data/lib/messaging.rb
CHANGED
@@ -86,38 +86,56 @@ module SelfSDK
|
|
86
86
|
m.id = SecureRandom.uuid
|
87
87
|
m.sender = "#{@jwt.id}:#{@device_id}"
|
88
88
|
m.recipient = "#{recipient}:#{recipient_device}"
|
89
|
+
# TODO: this is unencrypted!!!
|
89
90
|
m.ciphertext = @jwt.prepare(request)
|
90
91
|
|
91
92
|
send_message m
|
92
93
|
end
|
93
94
|
|
95
|
+
def session?(identifier, device)
|
96
|
+
path = @encryption_client.session_path(identifier, device)
|
97
|
+
File.file?(path)
|
98
|
+
end
|
99
|
+
|
94
100
|
# Send custom mmessage
|
95
101
|
#
|
96
102
|
# @param recipient [string] selfID to be requested
|
97
103
|
# @param type [string] message type
|
98
104
|
# @param request [hash] original message requesing information
|
99
|
-
def send_custom(
|
100
|
-
|
105
|
+
def send_custom(recipients, request_body)
|
106
|
+
# convert argument into an array if is a string
|
107
|
+
recipients = [recipients] if recipients.is_a? String
|
108
|
+
|
109
|
+
# send to current identity devices except the current one.
|
110
|
+
recipients |= [@jwt.id]
|
111
|
+
|
112
|
+
# build recipients list
|
113
|
+
recs = []
|
114
|
+
recipients.each do |r|
|
115
|
+
@client.devices(r).each do |to_device|
|
116
|
+
recs << { id: r, device_id: to_device }
|
117
|
+
end
|
118
|
+
end
|
119
|
+
|
120
|
+
SelfSDK.logger.info "sending custom message #{request_body.to_json}"
|
121
|
+
current_device = "#{@jwt.id}:#{@device_id}"
|
122
|
+
|
123
|
+
recs.each do |r|
|
124
|
+
next if current_device == "#{r[:id]}:#{r[:device_id]}"
|
125
|
+
|
126
|
+
request_body[:sub] = r[:id]
|
127
|
+
request_body[:aud] = r[:id] unless request_body.key?(:aud)
|
128
|
+
ciphertext = @encryption_client.encrypt(@jwt.prepare(request_body), recs)
|
129
|
+
|
101
130
|
m = SelfMsg::Message.new
|
102
131
|
m.id = SecureRandom.uuid
|
103
|
-
m.sender =
|
104
|
-
m.recipient = "#{
|
105
|
-
m.ciphertext =
|
132
|
+
m.sender = current_device
|
133
|
+
m.recipient = "#{r[:id]}:#{r[:device_id]}"
|
134
|
+
m.ciphertext = ciphertext
|
106
135
|
|
136
|
+
SelfSDK.logger.info " -> to #{m.recipient}"
|
107
137
|
send_message m
|
108
138
|
end
|
109
|
-
|
110
|
-
@client.devices(@jwt.id).each do |to_device|
|
111
|
-
if to_device != @device_id
|
112
|
-
m = SelfMsg::Message.new
|
113
|
-
m.id = SecureRandom.uuid
|
114
|
-
m.sender = "#{@jwt.id}:#{@device_id}"
|
115
|
-
m.recipient = "#{recipient}:#{to_device}"
|
116
|
-
m.ciphertext = @jwt.prepare(request_body)
|
117
|
-
|
118
|
-
send_message m
|
119
|
-
end
|
120
|
-
end
|
121
139
|
end
|
122
140
|
|
123
141
|
# Allows incomming messages from the given identity
|
@@ -159,6 +177,7 @@ module SelfSDK
|
|
159
177
|
#
|
160
178
|
# @params msg [SelfMsg::Message] message object to be sent
|
161
179
|
def send_and_wait_for_response(msgs, original)
|
180
|
+
SelfSDK.logger.info "sending/wait for #{msgs.first.id}"
|
162
181
|
wait_for msgs.first.id, original do
|
163
182
|
msgs.each do |msg|
|
164
183
|
send_message msg
|
@@ -414,7 +433,7 @@ module SelfSDK
|
|
414
433
|
rescue StandardError => e
|
415
434
|
p "Error processing incoming message #{input.to_json}"
|
416
435
|
SelfSDK.logger.info e
|
417
|
-
p e.backtrace
|
436
|
+
# p e.backtrace
|
418
437
|
nil
|
419
438
|
end
|
420
439
|
|
data/lib/selfsdk.rb
CHANGED
@@ -20,6 +20,7 @@ require_relative 'services/auth'
|
|
20
20
|
require_relative 'services/facts'
|
21
21
|
require_relative 'services/identity'
|
22
22
|
require_relative 'services/messaging'
|
23
|
+
require_relative 'services/chat'
|
23
24
|
|
24
25
|
# Namespace for classes and modules that handle Self interactions.
|
25
26
|
module SelfSDK
|
@@ -82,6 +83,11 @@ module SelfSDK
|
|
82
83
|
@messaging ||= SelfSDK::Services::Messaging.new(@messaging_client)
|
83
84
|
end
|
84
85
|
|
86
|
+
# Provides access to SelfSDK::Services::Chat service
|
87
|
+
def chat
|
88
|
+
@chat ||= SelfSDK::Services::Chat.new(messaging, identity)
|
89
|
+
end
|
90
|
+
|
85
91
|
def app_id
|
86
92
|
client.jwt.id
|
87
93
|
end
|
@@ -0,0 +1,210 @@
|
|
1
|
+
# Copyright 2020 Self Group Ltd. All Rights Reserved.
|
2
|
+
|
3
|
+
# frozen_string_literal: true
|
4
|
+
|
5
|
+
require 'self_crypto'
|
6
|
+
require_relative '../chat/file_object'
|
7
|
+
require_relative '../chat/group'
|
8
|
+
require_relative '../chat/message'
|
9
|
+
module SelfSDK
|
10
|
+
module Services
|
11
|
+
class Chat
|
12
|
+
attr_accessor :app_id
|
13
|
+
|
14
|
+
def initialize(messaging, client)
|
15
|
+
@messaging = messaging
|
16
|
+
@client = client
|
17
|
+
@app_id = @messaging.client.client.jwt.id
|
18
|
+
@auth_token = @messaging.client.client.jwt.auth_token
|
19
|
+
@self_url = @messaging.client.client.self_url
|
20
|
+
end
|
21
|
+
|
22
|
+
# Sends a message to a list of recipients.
|
23
|
+
#
|
24
|
+
# @param recipients [array] list of recipients to send the message to.
|
25
|
+
# @param body [string] the message content to be sent
|
26
|
+
def message(recipients, body, opts = {})
|
27
|
+
payload = {
|
28
|
+
typ: "chat.message",
|
29
|
+
msg: body,
|
30
|
+
}
|
31
|
+
payload[:jti] = opts[:jti] if opts.key? :jti
|
32
|
+
payload[:aud] = opts[:gid] if opts.key? :gid
|
33
|
+
payload[:gid] = opts[:gid] if opts.key? :gid
|
34
|
+
payload[:rid] = opts[:rid] if opts.key? :rid
|
35
|
+
payload[:objects] = opts[:objects] if opts.key? :objects
|
36
|
+
|
37
|
+
m = SelfSDK::Chat::Message.new(self, recipients, payload, @auth_token, @self_url)
|
38
|
+
_req = send(m.recipients, m.payload)
|
39
|
+
|
40
|
+
m
|
41
|
+
end
|
42
|
+
|
43
|
+
# Subscribes to an incoming chat message
|
44
|
+
def on_message(opts = {}, &block)
|
45
|
+
@messaging.subscribe :chat_message do |msg|
|
46
|
+
cm = SelfSDK::Chat::Message.new(self, msg.payload[:aud], msg.payload, @auth_token, @self_url)
|
47
|
+
|
48
|
+
cm.mark_as_delivered unless opts[:mark_as_delivered] == false
|
49
|
+
cm.mark_as_read if opts[:mark_as_read] == true
|
50
|
+
|
51
|
+
block.call(cm)
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
# Sends a message to confirm a list of messages (identified by it's cids)
|
56
|
+
# have been delivered.
|
57
|
+
#
|
58
|
+
# @param recipients [array] list of recipients to send the message to.
|
59
|
+
# @param cids [array] list of message cids to be marked as delivered.
|
60
|
+
# @param gid [string] group id where the conversation ids are referenced.
|
61
|
+
def delivered(recipients, cids, gid = nil)
|
62
|
+
confirm('delivered', recipients, cids, gid)
|
63
|
+
end
|
64
|
+
|
65
|
+
# Sends a message to confirm a list of messages (identified by it's cids)
|
66
|
+
# have been read.
|
67
|
+
#
|
68
|
+
# @param recipients [array] list of recipients to send the message to.
|
69
|
+
# @param cids [array] list of message cids to be marked as read.
|
70
|
+
# @param gid [string] group id where the conversation ids are referenced.
|
71
|
+
def read(recipients, cids, gid = nil)
|
72
|
+
confirm('read', recipients, cids, gid)
|
73
|
+
end
|
74
|
+
|
75
|
+
# Modifies a previously sent message
|
76
|
+
#
|
77
|
+
# @param recipients [array] list of recipients to send the message to.
|
78
|
+
# @param cids [array] list of message cids to be marked as read.
|
79
|
+
# @param body [string] the new body to replace the previous one.
|
80
|
+
# @param gid [string] group id where the conversation ids are referenced.
|
81
|
+
def edit(recipients, cid, body, gid = nil)
|
82
|
+
send(recipients, typ: "chat.message.edit",
|
83
|
+
cid: cid,
|
84
|
+
msg: body,
|
85
|
+
gid: gid)
|
86
|
+
end
|
87
|
+
|
88
|
+
# Sends a message to delete a specific message.
|
89
|
+
#
|
90
|
+
# @param recipient [string] the recipient of the message
|
91
|
+
# @param cid [string] message cid to be marked as read.
|
92
|
+
# @param gid [string] group id where the conversation ids are referenced.
|
93
|
+
def delete(recipients, cids, gid = nil)
|
94
|
+
cids = [cids] if cids.is_a? String
|
95
|
+
send(recipients, typ: "chat.message.delete",
|
96
|
+
cids: cids,
|
97
|
+
gid: gid)
|
98
|
+
end
|
99
|
+
|
100
|
+
def on_invite(&block)
|
101
|
+
@messaging.subscribe :chat_invite do |msg|
|
102
|
+
g = SelfSDK::Chat::Group.new(self, msg.payload)
|
103
|
+
block.call(g)
|
104
|
+
end
|
105
|
+
end
|
106
|
+
|
107
|
+
def on_join(&block)
|
108
|
+
@messaging.subscribe :chat_join do |msg|
|
109
|
+
block.call(iss: msg.payload[:iss], gid: msg.payload[:gid])
|
110
|
+
end
|
111
|
+
end
|
112
|
+
|
113
|
+
def on_leave(&block)
|
114
|
+
@messaging.subscribe :chat_remove do |msg|
|
115
|
+
block.call(iss: msg.payload[:iss], gid: msg.payload[:gid])
|
116
|
+
end
|
117
|
+
end
|
118
|
+
|
119
|
+
# Invite sends group invitation to a list of members.
|
120
|
+
#
|
121
|
+
# @param gid [string] group id.
|
122
|
+
# @param name [string] name of the group.
|
123
|
+
# @param members [array] list of group members.
|
124
|
+
def invite(gid, name, members, opts = {})
|
125
|
+
payload = { typ: "chat.invite",
|
126
|
+
gid: gid,
|
127
|
+
name: name,
|
128
|
+
members: members }
|
129
|
+
|
130
|
+
if opts.key? :data
|
131
|
+
obj = SelfSDK::Chat::FileObject.new(@auth_token, @self_url)
|
132
|
+
obj_payload = obj.build_from_data("", opts[:data], opts[:mime]).to_payload
|
133
|
+
obj_payload.delete(:name)
|
134
|
+
payload.merge! obj_payload
|
135
|
+
end
|
136
|
+
|
137
|
+
@messaging.send(members, payload)
|
138
|
+
SelfSDK::Chat::Group.new(self, payload)
|
139
|
+
end
|
140
|
+
|
141
|
+
# Join a group
|
142
|
+
#
|
143
|
+
# @param gid [string] group id.
|
144
|
+
# @param members [array] list of group members.
|
145
|
+
def join(gid, members)
|
146
|
+
# Allow incoming connections from the given members
|
147
|
+
|
148
|
+
# Create missing sessions with group members.
|
149
|
+
create_missing_sessions(members)
|
150
|
+
|
151
|
+
# Send joining confirmation.
|
152
|
+
send(members, typ: 'chat.join', gid: gid, aud: gid)
|
153
|
+
end
|
154
|
+
|
155
|
+
# Leaves a group
|
156
|
+
#
|
157
|
+
# @param gid [string] group id.
|
158
|
+
# @members members [array] list of group members.
|
159
|
+
def leave(gid, members)
|
160
|
+
send(members, typ: "chat.remove", gid: gid )
|
161
|
+
end
|
162
|
+
|
163
|
+
private
|
164
|
+
|
165
|
+
# sends a confirmation for a list of messages to a list of recipients.
|
166
|
+
def confirm(action, recipients, cids, gid = nil)
|
167
|
+
cids = [cids] if cids.is_a? String
|
168
|
+
gid = recipients if gid.nil? || gid.empty?
|
169
|
+
send(recipients, typ: "chat.message.#{action}",
|
170
|
+
cids: cids,
|
171
|
+
gid: gid)
|
172
|
+
end
|
173
|
+
|
174
|
+
# sends a message to a list of recipients.
|
175
|
+
def send(recipients, body)
|
176
|
+
recipients = [recipients] if recipients.is_a? String
|
177
|
+
m = []
|
178
|
+
recipients.each do |r|
|
179
|
+
m << @messaging.send(r, body)
|
180
|
+
end
|
181
|
+
m
|
182
|
+
end
|
183
|
+
|
184
|
+
# Group invites may come with members of the group we haven't set up a session
|
185
|
+
# previously, for those identitiese need to establish a session, but only if
|
186
|
+
# our identity appears before the others in the list members.
|
187
|
+
def create_missing_sessions(members)
|
188
|
+
return if members.empty?
|
189
|
+
|
190
|
+
posterior_members = false
|
191
|
+
requests = []
|
192
|
+
|
193
|
+
members.each do |m|
|
194
|
+
if posterior_members
|
195
|
+
@client.devices(m).each do |d|
|
196
|
+
continue unless @messaging.client.session?(m, d)
|
197
|
+
|
198
|
+
requests << @messaging.send("#{m}:#{d}", {
|
199
|
+
typ: 'sessions.create',
|
200
|
+
aud: m
|
201
|
+
})
|
202
|
+
end
|
203
|
+
end
|
204
|
+
|
205
|
+
posterior_members = true if m == @app_id
|
206
|
+
end
|
207
|
+
end
|
208
|
+
end
|
209
|
+
end
|
210
|
+
end
|
data/lib/services/facts.rb
CHANGED
@@ -40,6 +40,7 @@ module SelfSDK
|
|
40
40
|
# @param [Hash] opts the options to authenticate.
|
41
41
|
# @option opts [String] :cid The unique identifier of the authentication request.
|
42
42
|
# @option opts [Integer] :exp_timeout timeout in seconds to expire the request.
|
43
|
+
# @option opts [Integer] :allowed_for number of seconds for enabling recurrent requests.
|
43
44
|
# @return [Object] SelfSDK:::Messages::FactRequest
|
44
45
|
def request(selfid, facts, opts = {}, &block)
|
45
46
|
SelfSDK.logger.info "authenticating #{selfid}"
|
data/lib/services/messaging.rb
CHANGED
@@ -77,21 +77,20 @@ module SelfSDK
|
|
77
77
|
@client.uuid_observer[cid]
|
78
78
|
end
|
79
79
|
|
80
|
-
|
81
80
|
# Send custom mmessage
|
82
81
|
#
|
83
|
-
# @param
|
82
|
+
# @param recipients [String|array] recipient for the message
|
84
83
|
# @param type [string] message type
|
85
84
|
# @param request [hash] message to be sent
|
86
|
-
def send(
|
87
|
-
request[:jti] = SecureRandom.uuid
|
85
|
+
def send(recipients, request)
|
86
|
+
request[:jti] = SecureRandom.uuid unless request.include?(:jti)
|
88
87
|
request[:iss] = @client.jwt.id
|
89
|
-
request[:
|
90
|
-
request[:
|
91
|
-
request[:
|
92
|
-
request[:cid] = SecureRandom.uuid unless request.include? :cid
|
88
|
+
request[:iat] = SelfSDK::Time.now.strftime('%FT%TZ')
|
89
|
+
request[:exp] = (SelfSDK::Time.now + 300).strftime('%FT%TZ')
|
90
|
+
request[:cid] = SecureRandom.uuid unless request.include?(:cid)
|
93
91
|
|
94
|
-
@client.send_custom(
|
92
|
+
@client.send_custom(recipients, request)
|
93
|
+
request
|
95
94
|
end
|
96
95
|
|
97
96
|
def notify(recipient, message)
|
data/lib/sources.rb
CHANGED
@@ -33,8 +33,15 @@ module SelfSDK
|
|
33
33
|
types = { authentication_request: SelfSDK::Messages::AuthenticationReq::MSG_TYPE,
|
34
34
|
authentication_response: SelfSDK::Messages::AuthenticationResp::MSG_TYPE,
|
35
35
|
fact_request: SelfSDK::Messages::FactRequest::MSG_TYPE,
|
36
|
-
fact_response: SelfSDK::Messages::FactResponse::MSG_TYPE
|
37
|
-
|
36
|
+
fact_response: SelfSDK::Messages::FactResponse::MSG_TYPE,
|
37
|
+
chat_message: SelfSDK::Messages::ChatMessage::MSG_TYPE,
|
38
|
+
chat_message_deivered: SelfSDK::Messages::ChatMessageDelivered::MSG_TYPE,
|
39
|
+
chat_message_read: SelfSDK::Messages::ChatMessageRead::MSG_TYPE,
|
40
|
+
chat_invite: SelfSDK::Messages::ChatInvite::MSG_TYPE,
|
41
|
+
chat_join: SelfSDK::Messages::ChatJoin::MSG_TYPE,
|
42
|
+
chat_remove: SelfSDK::Messages::ChatRemove::MSG_TYPE,
|
43
|
+
}
|
44
|
+
raise "invalid message type '#{s}'" unless types.key? s
|
38
45
|
return types[s]
|
39
46
|
end
|
40
47
|
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: selfsdk
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.184
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Aldgate Ventures
|
@@ -226,14 +226,14 @@ dependencies:
|
|
226
226
|
requirements:
|
227
227
|
- - "~>"
|
228
228
|
- !ruby/object:Gem::Version
|
229
|
-
version: '
|
229
|
+
version: '13.0'
|
230
230
|
type: :development
|
231
231
|
prerelease: false
|
232
232
|
version_requirements: !ruby/object:Gem::Requirement
|
233
233
|
requirements:
|
234
234
|
- - "~>"
|
235
235
|
- !ruby/object:Gem::Version
|
236
|
-
version: '
|
236
|
+
version: '13.0'
|
237
237
|
- !ruby/object:Gem::Dependency
|
238
238
|
name: rubocop
|
239
239
|
requirement: !ruby/object:Gem::Requirement
|
@@ -326,6 +326,9 @@ extra_rdoc_files: []
|
|
326
326
|
files:
|
327
327
|
- lib/acl.rb
|
328
328
|
- lib/authenticated.rb
|
329
|
+
- lib/chat/file_object.rb
|
330
|
+
- lib/chat/group.rb
|
331
|
+
- lib/chat/message.rb
|
329
332
|
- lib/client.rb
|
330
333
|
- lib/crypto.rb
|
331
334
|
- lib/jwt_service.rb
|
@@ -335,6 +338,13 @@ files:
|
|
335
338
|
- lib/messages/authentication_req.rb
|
336
339
|
- lib/messages/authentication_resp.rb
|
337
340
|
- lib/messages/base.rb
|
341
|
+
- lib/messages/chat.rb
|
342
|
+
- lib/messages/chat_invite.rb
|
343
|
+
- lib/messages/chat_join.rb
|
344
|
+
- lib/messages/chat_message.rb
|
345
|
+
- lib/messages/chat_message_delivered.rb
|
346
|
+
- lib/messages/chat_message_read.rb
|
347
|
+
- lib/messages/chat_remove.rb
|
338
348
|
- lib/messages/fact.rb
|
339
349
|
- lib/messages/fact_request.rb
|
340
350
|
- lib/messages/fact_response.rb
|
@@ -343,6 +353,7 @@ files:
|
|
343
353
|
- lib/ntptime.rb
|
344
354
|
- lib/selfsdk.rb
|
345
355
|
- lib/services/auth.rb
|
356
|
+
- lib/services/chat.rb
|
346
357
|
- lib/services/facts.rb
|
347
358
|
- lib/services/identity.rb
|
348
359
|
- lib/services/messaging.rb
|