mixin_bot 0.12.1 → 1.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (57) hide show
  1. checksums.yaml +4 -4
  2. data/lib/mixin_bot/api/address.rb +21 -0
  3. data/lib/mixin_bot/api/app.rb +5 -11
  4. data/lib/mixin_bot/api/asset.rb +9 -16
  5. data/lib/mixin_bot/api/attachment.rb +27 -22
  6. data/lib/mixin_bot/api/auth.rb +34 -56
  7. data/lib/mixin_bot/api/blaze.rb +4 -3
  8. data/lib/mixin_bot/api/conversation.rb +29 -49
  9. data/lib/mixin_bot/api/encrypted_message.rb +19 -19
  10. data/lib/mixin_bot/api/inscription.rb +71 -0
  11. data/lib/mixin_bot/api/legacy_collectible.rb +140 -0
  12. data/lib/mixin_bot/api/legacy_multisig.rb +87 -0
  13. data/lib/mixin_bot/api/legacy_output.rb +50 -0
  14. data/lib/mixin_bot/api/legacy_payment.rb +31 -0
  15. data/lib/mixin_bot/api/legacy_snapshot.rb +39 -0
  16. data/lib/mixin_bot/api/legacy_transaction.rb +173 -0
  17. data/lib/mixin_bot/api/legacy_transfer.rb +42 -0
  18. data/lib/mixin_bot/api/me.rb +13 -17
  19. data/lib/mixin_bot/api/message.rb +13 -10
  20. data/lib/mixin_bot/api/multisig.rb +17 -222
  21. data/lib/mixin_bot/api/output.rb +48 -0
  22. data/lib/mixin_bot/api/payment.rb +9 -20
  23. data/lib/mixin_bot/api/pin.rb +57 -65
  24. data/lib/mixin_bot/api/rpc.rb +12 -14
  25. data/lib/mixin_bot/api/snapshot.rb +15 -29
  26. data/lib/mixin_bot/api/tip.rb +43 -0
  27. data/lib/mixin_bot/api/transaction.rb +295 -60
  28. data/lib/mixin_bot/api/transfer.rb +69 -31
  29. data/lib/mixin_bot/api/user.rb +88 -53
  30. data/lib/mixin_bot/api/withdraw.rb +52 -53
  31. data/lib/mixin_bot/api.rb +81 -46
  32. data/lib/mixin_bot/cli/api.rb +149 -5
  33. data/lib/mixin_bot/cli/utils.rb +14 -4
  34. data/lib/mixin_bot/cli.rb +13 -10
  35. data/lib/mixin_bot/client.rb +74 -127
  36. data/lib/mixin_bot/configuration.rb +98 -0
  37. data/lib/mixin_bot/nfo.rb +174 -0
  38. data/lib/mixin_bot/transaction.rb +524 -0
  39. data/lib/mixin_bot/utils/address.rb +121 -0
  40. data/lib/mixin_bot/utils/crypto.rb +218 -0
  41. data/lib/mixin_bot/utils/decoder.rb +56 -0
  42. data/lib/mixin_bot/utils/encoder.rb +63 -0
  43. data/lib/mixin_bot/utils.rb +8 -109
  44. data/lib/mixin_bot/uuid.rb +41 -0
  45. data/lib/mixin_bot/version.rb +1 -1
  46. data/lib/mixin_bot.rb +39 -14
  47. data/lib/mvm/bridge.rb +2 -19
  48. data/lib/mvm/client.rb +11 -33
  49. data/lib/mvm/nft.rb +4 -4
  50. data/lib/mvm/registry.rb +9 -9
  51. data/lib/mvm/scan.rb +3 -5
  52. data/lib/mvm.rb +5 -6
  53. metadata +77 -103
  54. data/lib/mixin_bot/api/collectible.rb +0 -138
  55. data/lib/mixin_bot/utils/nfo.rb +0 -176
  56. data/lib/mixin_bot/utils/transaction.rb +0 -478
  57. data/lib/mixin_bot/utils/uuid.rb +0 -43
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: cf2e7ef08c38a52d5d31ce1be5a0531f13680e31cb5e7f11cd6e1582436d8711
4
- data.tar.gz: '08cfa89514d3f102cdd064cfb3c3367cf2166292a3abc854481320a2fb610d15'
3
+ metadata.gz: 4257bfdffc20e27ffab5ce9da23080be113a552623f5022775f3cc8a6cc6db0c
4
+ data.tar.gz: 7f29a034845b45715e33b3b51e28be996408fcff145538025a243fb74d42b482
5
5
  SHA512:
6
- metadata.gz: a5f7af8574ea545b899bd2081923dd75e0b2ef2288346fb8e8d842b642ef596c626370d9a5140a695c267db4281e4c51239cce2d55f5edb87ed33127c76c379b
7
- data.tar.gz: b2393b4a392ff025b0e6d58c545018bd4cafb26e9fb130bba8938e42d4850a6f2b5d0244d887f6dae8d8f53fcb000819737ea71d999add7e175637c7e2d591d1
6
+ metadata.gz: 18e9d94005f235f827ce4e7598a2b2ddf13f48b296d9af46e4d6b2550e795c30f805c40b815352c159f7f2aa7b35c0a4e93ea0787889175c373e931720b5dc17
7
+ data.tar.gz: 56e0c4651199912fd4ed4bef7eb96cc22de1cd30842b7d8e767811ece926e880984a0f2734db19d4f1c48464c037e3b3d9c22b61be204c8a83ffd0f926203e37
@@ -0,0 +1,21 @@
1
+ # frozen_string_literal: true
2
+
3
+ module MixinBot
4
+ class API
5
+ module Address
6
+ def safe_deposit_entries(**kwargs)
7
+ path = '/safe/deposit/entries'
8
+
9
+ members = [kwargs[:members]] if kwargs[:members].is_a? String
10
+
11
+ payload = {
12
+ members:,
13
+ threshold: kwargs[:threshold] || 1,
14
+ chain_id: kwargs[:chain_id]
15
+ }
16
+
17
+ client.post path, **payload, access_token: kwargs[:access_token]
18
+ end
19
+ end
20
+ end
21
+ end
@@ -6,25 +6,19 @@ module MixinBot
6
6
  def add_favorite_app(app_id, access_token: nil)
7
7
  path = format('/apps/%<id>s/favorite', id: app_id)
8
8
 
9
- access_token ||= access_token('POST', path)
10
- authorization = format('Bearer %<access_token>s', access_token: access_token)
11
- client.post(path, headers: { 'Authorization': authorization })
9
+ client.post path, access_token:
12
10
  end
13
11
 
14
12
  def remove_favorite_app(app_id, access_token: nil)
15
13
  path = format('/apps/%<id>s/unfavorite', id: app_id)
16
14
 
17
- access_token ||= access_token('POST', path)
18
- authorization = format('Bearer %<access_token>s', access_token: access_token)
19
- client.post(path, headers: { 'Authorization': authorization })
15
+ client.post path, access_token:
20
16
  end
21
17
 
22
- def favorite_apps(user_id, access_token: nil)
23
- path = format('/users/%<id>s/apps/favorite', id: user_id)
18
+ def favorite_apps(user_id = nil, access_token: nil)
19
+ path = format('/users/%<id>s/apps/favorite', id: user_id || config.app_id)
24
20
 
25
- access_token ||= access_token('GET', path, '')
26
- authorization = format('Bearer %<access_token>s', access_token: access_token)
27
- client.get(path, headers: { 'Authorization': authorization })
21
+ client.get path, access_token:
28
22
  end
29
23
  end
30
24
  end
@@ -6,31 +6,24 @@ module MixinBot
6
6
  # https://developers.mixin.one/api/alpha-mixin-network/read-assets/
7
7
  def assets(access_token: nil)
8
8
  path = '/assets'
9
- access_token ||= access_token('GET', path, '')
10
- authorization = format('Bearer %<access_token>s', access_token: access_token)
11
- client.get(path, headers: { 'Authorization': authorization })
9
+ client.get path, access_token:
12
10
  end
13
- alias read_assets assets
14
11
 
15
12
  # https://developers.mixin.one/api/alpha-mixin-network/read-asset/
16
13
  def asset(asset_id, access_token: nil)
17
- path = format('/assets/%<asset_id>s', asset_id: asset_id)
18
- access_token ||= access_token('GET', path, '')
19
- authorization = format('Bearer %<access_token>s', access_token: access_token)
20
- client.get(path, headers: { 'Authorization': authorization })
14
+ path = format('/assets/%<asset_id>s', asset_id:)
15
+ client.get path, access_token:
21
16
  end
22
- alias read_asset asset
23
17
 
24
18
  # https://developers.mixin.one/document/wallet/api/ticker
25
- def ticker(asset_id, offset, access_token: nil)
26
- offset = DateTime.rfc3339 offset if offset.is_a? String
19
+ def ticker(asset_id, **kwargs)
20
+ offset = kwargs[:offset]
21
+ offset = DateTime.rfc3339(offset) if offset.is_a? String
27
22
  offset = offset.rfc3339 if offset.is_a?(DateTime) || offset.is_a?(Time)
28
- path = format('/ticker?asset=%<asset_id>s&offset=%<offset>s', asset_id: asset_id, offset: offset)
29
- access_token ||= access_token('GET', path, '')
30
- authorization = format('Bearer %<access_token>s', access_token: access_token)
31
- client.get(path, headers: { 'Authorization': authorization })
23
+
24
+ path = '/ticker'
25
+ client.get path, asset_id:, offset:, access_token: kwargs[:access_token]
32
26
  end
33
- alias read_ticker ticker
34
27
  end
35
28
  end
36
29
  end
@@ -3,7 +3,6 @@
3
3
  module MixinBot
4
4
  class API
5
5
  module Attachment
6
- # https://developers.mixin.one/api/beta-mixin-message/create-attachment/
7
6
  # Sample Response
8
7
  # {
9
8
  # "data":{
@@ -14,38 +13,44 @@ module MixinBot
14
13
  # }
15
14
  # }
16
15
  # Once get the upload_url, use it to upload the your file via PUT request
17
- def create_attachment
16
+ def create_attachment(access_token: nil)
18
17
  path = '/attachments'
19
- access_token ||= access_token('POST', path, {}.to_json)
20
- authorization = format('Bearer %<access_token>s', access_token: access_token)
21
- client.post(path, headers: { 'Authorization': authorization }, json: {})
18
+ client.post path, access_token:
22
19
  end
23
20
 
24
21
  def upload_attachment(file)
25
22
  attachment = create_attachment['data']
26
23
 
27
- HTTP
28
- .timeout(connect: 5, write: 5, read: 5)
29
- .request(
30
- :put,
31
- attachment.delete('upload_url'),
32
- {
33
- body: file,
34
- headers: {
35
- 'x-amz-acl': 'public-read',
36
- 'Content-Type': 'application/octet-stream'
37
- }
38
- }
39
- )
24
+ url = attachment.delete('upload_url')
25
+ conn = Faraday.new(url:) do |f|
26
+ f.adapter :net_http
27
+
28
+ f.request :multipart
29
+ f.request :retry
30
+ f.response :raise_error
31
+ f.response :logger if config.debug
32
+ end
33
+
34
+ conn.put(url) do |req|
35
+ req.headers = {
36
+ 'x-amz-acl': 'public-read',
37
+ 'Content-Type': 'application/octet-stream'
38
+ }
39
+ req.body = Faraday::UploadIO.new(file, 'octet/stream')
40
+
41
+ if file.respond_to?(:length)
42
+ req.headers['Content-Length'] = file.length.to_s
43
+ elsif file.respond_to?(:stat)
44
+ req.headers['Content-Length'] = file.stat.size.to_s
45
+ end
46
+ end
40
47
 
41
48
  attachment
42
49
  end
43
50
 
44
- def read_attachment(attachment_id)
51
+ def attachment(attachment_id, access_token: nil)
45
52
  path = format('/attachments/%<id>s', id: attachment_id)
46
- access_token ||= access_token('GET', path, '')
47
- authorization = format('Bearer %<access_token>s', access_token: access_token)
48
- client.get(path, headers: { 'Authorization': authorization })
53
+ client.get path, access_token:
49
54
  end
50
55
  end
51
56
  end
@@ -3,85 +3,60 @@
3
3
  module MixinBot
4
4
  class API
5
5
  module Auth
6
- def access_token(method, uri, body = '', exp_in: 600, scp: 'FULL')
7
- sig = Digest::SHA256.hexdigest(method + uri + body.to_s)
8
- iat = Time.now.utc.to_i
9
- exp = (Time.now.utc + exp_in).to_i
10
- jti = SecureRandom.uuid
11
- payload = {
12
- uid: client_id,
13
- sid: session_id,
14
- iat: iat,
15
- exp: exp,
16
- jti: jti,
17
- sig: sig,
18
- scp: scp
19
- }
20
- case key_type
21
- when :ed25519
22
- jwk = JOSE::JWK.from_okp [:Ed25519, private_key]
23
- jws = JOSE::JWS.from({ 'alg' => 'EdDSA' })
24
- when :rsa
25
- jwk = JOSE::JWK.from_pem private_key
26
- jws = JOSE::JWS.from({ 'alg' => 'RS512' })
27
- end
28
-
29
- jwt = JOSE::JWT.from payload
30
- JOSE::JWT.sign(jwk, jws, jwt).compact
31
- end
32
-
33
6
  def oauth_token(code)
34
7
  path = 'oauth/token'
35
8
  payload = {
36
- client_id: client_id,
37
- client_secret: client_secret,
38
- code: code
9
+ client_id: config.app_id,
10
+ client_secret: config.client_secret,
11
+ code:
39
12
  }
40
- r = client.post(path, json: payload)
41
-
42
- raise r.inspect if r['error'].present?
43
-
44
- r['data']&.[]('access_token')
13
+ client.post path, **payload
45
14
  end
46
15
 
47
16
  def request_oauth(scope = nil)
48
- scope ||= (MixinBot.scope || 'PROFILE:READ')
17
+ scope ||= 'PROFILE:READ'
49
18
  format(
50
- 'https://mixin.one/oauth/authorize?client_id=%<client_id>s&scope=%<scope>s',
51
- client_id: client_id,
52
- scope: scope
19
+ 'https://mixin.one/oauth/authorize?client_id=%<app_id>s&scope=%<scope>s',
20
+ app_id: config.app_id,
21
+ scope:
53
22
  )
54
23
  end
55
24
 
56
25
  def authorize_code(**kwargs)
57
- path = '/oauth/authorize'
58
26
  data = authorization_data(
59
- kwargs[:user_id],
27
+ kwargs[:app_id],
60
28
  kwargs[:scope] || ['PROFILE:READ']
61
29
  )
62
30
 
31
+ path = '/oauth/authorize'
32
+ pin = kwargs[:pin] || config.pin
63
33
  payload = {
64
34
  authorization_id: data['authorization_id'],
65
35
  scopes: data['scopes'],
66
36
  pin_base64: encrypt_pin(kwargs[:pin])
67
37
  }
68
38
 
69
- access_token = kwargs[:access_token]
70
- access_token ||= access_token('POST', path, payload.to_json)
71
- authorization = format('Bearer %<access_token>s', access_token: access_token)
72
- client.post(path, headers: { 'Authorization': authorization }, json: payload)
39
+ raise ArgumentError, 'pin is required' if pin.blank?
40
+
41
+ payload[:pin_base64] = if pin.size > 6
42
+ encrypt_tip_pin(pin, 'TIP:OAUTH:APPROVE:', data['scopes'], data['authorization_id'])
43
+ else
44
+ encrypt_pin(pin)
45
+ end
46
+
47
+ client.post path, **payload, access_token: kwargs[:access_token]
73
48
  end
74
49
 
75
- def authorization_data(user_id, scope = ['PROFILE:READ'])
76
- @_client_id = user_id
50
+ def authorization_data(app_id, scope = ['PROFILE:READ'])
51
+ @_app_id = app_id
77
52
  @_scope = scope.join(' ')
78
53
  EM.run do
79
54
  start_blaze_connect do
80
- def on_open(ws, _event)
81
- ws.send write_ws_message(
55
+ def on_open(websocket, _event) # rubocop:disable Lint/NestedMethodDefinition
56
+ websocket.send write_ws_message(
82
57
  action: 'REFRESH_OAUTH_CODE',
83
58
  params: {
84
- client_id: @_client_id,
59
+ client_id: @_app_id,
85
60
  scope: @_scope,
86
61
  authorization_id: '',
87
62
  code_challenge: ''
@@ -89,18 +64,21 @@ module MixinBot
89
64
  )
90
65
  end
91
66
 
92
- def on_message(ws, event)
93
- raw = JSON.parse read_ws_message(event.data)
94
- @_data = raw['data']
95
- ws.close
67
+ def on_message(websocket, event) # rubocop:disable Lint/NestedMethodDefinition
68
+ raw = JSON.parse ws_message(event.data)
69
+ @_data = raw
70
+ websocket.close
96
71
  end
97
72
 
98
- def on_close(_ws, _event)
73
+ def on_close(_websocket, _event) # rubocop:disable Lint/NestedMethodDefinition
99
74
  EM.stop_event_loop
100
75
  end
101
76
  end
102
77
  end
103
- @_data
78
+
79
+ raise MixinBot::RequestError, @_data if @_data['error'].present?
80
+
81
+ @_data['data']
104
82
  end
105
83
  end
106
84
  end
@@ -5,9 +5,10 @@ module MixinBot
5
5
  module Blaze
6
6
  def blaze
7
7
  access_token = access_token('GET', '/', '')
8
- authorization = format('Bearer %<access_token>s', access_token: access_token)
8
+
9
+ authorization = format('Bearer %<access_token>s', access_token:)
9
10
  Faye::WebSocket::Client.new(
10
- format('wss://%<host>s/', host: blaze_host),
11
+ format('wss://%<host>s/', host: config.blaze_host),
11
12
  ['Mixin-Blaze-1'],
12
13
  headers: { 'Authorization' => authorization },
13
14
  ping: 60
@@ -31,7 +32,7 @@ module MixinBot
31
32
  if defined? on_message
32
33
  on_message ws, event
33
34
  else
34
- raw = JSON.parse read_ws_message(event.data)
35
+ raw = JSON.parse ws_message(event.data)
35
36
  p [Time.now.to_s, :message, raw&.[]('action')]
36
37
 
37
38
  ws.send acknowledge_message_receipt(raw['data']['message_id']) unless raw&.[]('data')&.[]('message_id').nil?
@@ -3,77 +3,67 @@
3
3
  module MixinBot
4
4
  class API
5
5
  module Conversation
6
- def conversation(conversation_id)
7
- path = format('/conversations/%<conversation_id>s', conversation_id: conversation_id)
8
- access_token ||= access_token('GET', path, '')
9
- authorization = format('Bearer %<access_token>s', access_token: access_token)
10
- client.get(path, headers: { 'Authorization': authorization })
6
+ def conversation(conversation_id, access_token: nil)
7
+ path = format('/conversations/%<conversation_id>s', conversation_id:)
8
+ client.get path, access_token:
11
9
  end
12
- alias read_conversation conversation
13
10
 
14
11
  def conversation_by_user_id(user_id)
15
- conversation_id = unique_conversation_id(user_id)
16
- read_conversation(conversation_id)
12
+ conversation_id = unique_uuid user_id
13
+ conversation conversation_id
17
14
  end
18
- alias read_conversation_by_user_id conversation_by_user_id
19
15
 
20
- def create_conversation(category:, conversation_id:, participants:, name: nil, access_token: nil)
16
+ def create_conversation(**kwargs)
21
17
  path = '/conversations'
22
18
  payload = {
23
- category: category,
24
- conversation_id: conversation_id || SecureRandom.uuid,
25
- name: name,
26
- participants: participants
27
- }
19
+ category: kwargs[:category],
20
+ conversation_id: kwargs[:conversation_id] || SecureRandom.uuid,
21
+ name: kwargs[:name],
22
+ participants: kwargs[:participants]
23
+ }.compact_blank
28
24
 
29
- access_token ||= access_token('POST', path, payload.to_json)
30
- authorization = format('Bearer %<access_token>s', access_token: access_token)
31
- client.post(path, headers: { 'Authorization': authorization }, json: payload)
25
+ client.post path, **payload, access_token: kwargs[:access_token]
32
26
  end
33
27
 
34
28
  def create_group_conversation(user_ids:, name:, conversation_id: nil, access_token: nil)
35
29
  create_conversation(
36
30
  category: 'GROUP',
37
- conversation_id: conversation_id,
38
- name: name,
31
+ conversation_id:,
32
+ name:,
39
33
  participants: user_ids.map(&->(participant) { { user_id: participant } }),
40
- access_token: access_token
34
+ access_token:
41
35
  )
42
36
  end
43
37
 
44
38
  def create_contact_conversation(user_id, access_token: nil)
45
39
  create_conversation(
46
40
  category: 'CONTACT',
47
- conversation_id: unique_conversation_id(user_id),
41
+ conversation_id: unique_uuid(user_id),
48
42
  participants: [
49
43
  {
50
- user_id: user_id
44
+ user_id:
51
45
  }
52
46
  ],
53
- access_token: access_token
47
+ access_token:
54
48
  )
55
49
  end
56
50
 
57
51
  def update_group_conversation_name(name:, conversation_id:, access_token: nil)
58
52
  path = format('/conversations/%<id>s', id: conversation_id)
59
53
  payload = {
60
- name: name
54
+ name:
61
55
  }
62
56
 
63
- access_token ||= access_token('POST', path, payload.to_json)
64
- authorization = format('Bearer %<access_token>s', access_token: access_token)
65
- client.post(path, headers: { 'Authorization': authorization }, json: payload)
57
+ client.post path, **payload, access_token:
66
58
  end
67
59
 
68
60
  def update_group_conversation_announcement(announcement:, conversation_id:, access_token: nil)
69
61
  path = format('/conversations/%<id>s', id: conversation_id)
70
62
  payload = {
71
- announcement: announcement
63
+ announcement:
72
64
  }
73
65
 
74
- access_token ||= access_token('POST', path, payload.to_json)
75
- authorization = format('Bearer %<access_token>s', access_token: access_token)
76
- client.post(path, headers: { 'Authorization': authorization }, json: payload)
66
+ client.post path, **payload, access_token:
77
67
  end
78
68
 
79
69
  # participants = [{ user_id: "" }]
@@ -81,9 +71,7 @@ module MixinBot
81
71
  path = format('/conversations/%<id>s/participants/ADD', id: conversation_id)
82
72
  payload = user_ids.map(&->(participant) { { user_id: participant } })
83
73
 
84
- access_token ||= access_token('POST', path, payload.to_json)
85
- authorization = format('Bearer %<access_token>s', access_token: access_token)
86
- client.post(path, headers: { 'Authorization': authorization }, json: payload)
74
+ client.post path, *payload, access_token:
87
75
  end
88
76
 
89
77
  # participants = [{ user_id: "" }]
@@ -91,25 +79,19 @@ module MixinBot
91
79
  path = format('/conversations/%<id>s/participants/REMOVE', id: conversation_id)
92
80
  payload = user_ids.map(&->(participant) { { user_id: participant } })
93
81
 
94
- access_token ||= access_token('POST', path, payload.to_json)
95
- authorization = format('Bearer %<access_token>s', access_token: access_token)
96
- client.post(path, headers: { 'Authorization': authorization }, json: payload)
82
+ client.post path, *payload, access_token:
97
83
  end
98
84
 
99
85
  def exit_conversation(conversation_id, access_token: nil)
100
86
  path = format('/conversations/%<id>s/exit', id: conversation_id)
101
87
 
102
- access_token ||= access_token('POST', path)
103
- authorization = format('Bearer %<access_token>s', access_token: access_token)
104
- client.post(path, headers: { 'Authorization': authorization })
88
+ client.post path, access_token:
105
89
  end
106
90
 
107
91
  def rotate_conversation(conversation_id, access_token: nil)
108
92
  path = format('/conversations/%<id>s/rotate', id: conversation_id)
109
93
 
110
- access_token ||= access_token('POST', path)
111
- authorization = format('Bearer %<access_token>s', access_token: access_token)
112
- client.post(path, headers: { 'Authorization': authorization })
94
+ client.post path, access_token:
113
95
  end
114
96
 
115
97
  # participants = [{ user_id: "", role: "ADMIN" }]
@@ -117,14 +99,12 @@ module MixinBot
117
99
  path = format('/conversations/%<id>s/participants/ROLE', id: conversation_id)
118
100
  payload = participants
119
101
 
120
- access_token ||= access_token('POST', path, payload.to_json)
121
- authorization = format('Bearer %<access_token>s', access_token: access_token)
122
- client.post(path, headers: { 'Authorization': authorization }, json: payload)
102
+ client.post path, *payload, access_token:
123
103
  end
124
104
 
125
105
  def unique_uuid(user_id, opponent_id = nil)
126
- opponent_id ||= client_id
127
- MixinBot::Utils.unique_uuid user_id, opponent_id
106
+ opponent_id ||= config.app_id
107
+ MixinBot.utils.unique_uuid user_id, opponent_id
128
108
  end
129
109
  alias unique_conversation_id unique_uuid
130
110
  end
@@ -90,11 +90,11 @@ module MixinBot
90
90
  category: options[:category],
91
91
  quote_message_id: options[:quote_message_id],
92
92
  message_id: options[:message_id] || SecureRandom.uuid,
93
- data_base64: data_base64,
94
- checksum: checksum,
93
+ data_base64:,
94
+ checksum:,
95
95
  recipient_sessions: session_ids.map(&->(s) { { session_id: s } }),
96
96
  silent: false
97
- }
97
+ }.compact
98
98
  end
99
99
 
100
100
  def send_encrypted_messages(messages)
@@ -104,19 +104,19 @@ module MixinBot
104
104
  # http post request
105
105
  def send_encrypted_message(payload)
106
106
  path = '/encrypted_messages'
107
- payload = [payload] unless payload.is_a?(Array)
108
- access_token ||= access_token('POST', path, payload.to_json)
109
- authorization = format('Bearer %<access_token>s', access_token: access_token)
110
- client.post(path, headers: { 'Authorization': authorization }, json: payload)
107
+ payload = [payload] if payload.is_a? Hash
108
+ raise ArgumentError, 'Wrong payload format!' unless payload.is_a? Array
109
+
110
+ client.post path, *payload
111
111
  end
112
112
 
113
- def encrypt_message(data, sessions = [], sk: nil, pk: nil)
113
+ def encrypt_message(data, sessions = [], sk: nil, pk: nil) # rubocop:disable Naming/MethodParameterName
114
114
  raise ArgumentError, 'Wrong sessions format!' unless sessions.all?(&->(s) { s.key?('session_id') && s.key?('public_key') })
115
115
 
116
- sk = private_key[0...32]
117
- pk ||= private_key[32...]
116
+ sk ||= config.session_private_key[0...32]
117
+ pk ||= config.session_private_key[32...]
118
118
 
119
- checksum = Digest::MD5.hexdigest sessions.map(&->(s) { s['session_id'] }).sort.join
119
+ Digest::MD5.hexdigest sessions.map(&->(s) { s['session_id'] }).sort.join
120
120
  encrypter = OpenSSL::Cipher.new('AES-128-GCM').encrypt
121
121
  key = encrypter.random_key
122
122
  nounce = encrypter.random_iv
@@ -128,14 +128,14 @@ module MixinBot
128
128
  bytes = [1]
129
129
  bytes += [sessions.size].pack('v*').bytes
130
130
  bytes += JOSE::JWA::Ed25519.pk_to_curve25519(pk).bytes
131
-
131
+
132
132
  sessions.each do |session|
133
133
  aes_key = JOSE::JWA::X25519.shared_secret(
134
134
  Base64.urlsafe_decode64(session['public_key']),
135
135
  JOSE::JWA::Ed25519.secret_to_curve25519(sk)
136
136
  )
137
137
 
138
- padding = 16 - key.size % 16
138
+ padding = 16 - (key.size % 16)
139
139
  padtext = ([padding] * padding).pack('C*')
140
140
 
141
141
  encrypter = OpenSSL::Cipher.new('AES-256-CBC').encrypt
@@ -143,7 +143,7 @@ module MixinBot
143
143
  iv = encrypter.random_iv
144
144
  encrypter.iv = iv
145
145
 
146
- bytes += (MixinBot::Utils::UUID.new(hex: session['session_id']).packed + iv).bytes
146
+ bytes += (MixinBot::UUID.new(hex: session['session_id']).packed + iv).bytes
147
147
  bytes += encrypter.update(key + padtext).bytes
148
148
  end
149
149
 
@@ -153,22 +153,22 @@ module MixinBot
153
153
  Base64.urlsafe_encode64 bytes.pack('C*'), padding: false
154
154
  end
155
155
 
156
- def decrypt_message(data, sk: nil, si: nil)
156
+ def decrypt_message(data, sk: nil, si: nil) # rubocop:disable Naming/MethodParameterName
157
157
  bytes = Base64.urlsafe_decode64(data).bytes
158
158
 
159
- si ||= session_id
160
- sk ||= private_key[0...32]
159
+ si ||= config.session_id
160
+ sk ||= config.session_private_key[0...32]
161
161
 
162
162
  size = 16 + 48
163
163
  return '' if bytes.size < 1 + 2 + 32 + size + 12
164
164
 
165
165
  session_length = bytes[1...3].pack('v*').unpack1('C*')
166
- prefix_size = 35 + session_length * size
166
+ prefix_size = 35 + (session_length * size)
167
167
 
168
168
  i = 35
169
169
  key = ''
170
170
  while i < prefix_size
171
- uuid = MixinBot::Utils::UUID.new(raw: bytes[i...(i + 16)].pack('C*')).unpacked
171
+ uuid = MixinBot::UUID.new(raw: bytes[i...(i + 16)].pack('C*')).unpacked
172
172
  if uuid == si
173
173
  pub = bytes[3...35]
174
174
  aes_key = JOSE::JWA::X25519.shared_secret(