mixin_bot 0.0.1.4 → 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/bin/mixinbot +6 -0
- data/lib/mixin_bot.rb +14 -6
- data/lib/mixin_bot/api.rb +49 -7
- data/lib/mixin_bot/api/app.rb +31 -0
- data/lib/mixin_bot/api/attachment.rb +32 -0
- data/lib/mixin_bot/api/auth.rb +24 -8
- data/lib/mixin_bot/api/blaze.rb +62 -0
- data/lib/mixin_bot/api/conversation.rb +25 -14
- data/lib/mixin_bot/api/me.rb +25 -16
- data/lib/mixin_bot/api/message.rb +286 -34
- data/lib/mixin_bot/api/multisig.rb +335 -0
- data/lib/mixin_bot/api/payment.rb +16 -16
- data/lib/mixin_bot/api/pin.rb +58 -22
- data/lib/mixin_bot/api/snapshot.rb +32 -17
- data/lib/mixin_bot/api/transfer.rb +17 -17
- data/lib/mixin_bot/api/user.rb +61 -13
- data/lib/mixin_bot/api/withdraw.rb +78 -0
- data/lib/mixin_bot/cli.rb +128 -0
- data/lib/mixin_bot/cli/me.rb +40 -0
- data/lib/mixin_bot/cli/multisig.rb +11 -0
- data/lib/mixin_bot/cli/node.rb +107 -0
- data/lib/mixin_bot/client.rb +37 -38
- data/lib/mixin_bot/errors.rb +3 -1
- data/lib/mixin_bot/version.rb +3 -1
- metadata +150 -27
@@ -1,29 +1,29 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module MixinBot
|
2
4
|
class API
|
3
5
|
module Payment
|
4
6
|
def pay_url(options)
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
7
|
+
format(
|
8
|
+
'https://mixin.one/pay?recipient=%<recipient_id>s&asset=%<asset>s&amount=%<amount>s&trace=%<trace>s&memo=%<memo>s',
|
9
|
+
recipient_id: options[:recipient_id],
|
10
|
+
asset: options[:asset_id],
|
11
|
+
amount: options[:amount].to_s,
|
12
|
+
trace: options[:trace],
|
13
|
+
memo: options[:memo]
|
14
|
+
)
|
12
15
|
end
|
13
16
|
|
17
|
+
# https://developers.mixin.one/api/alpha-mixin-network/verify-payment/
|
14
18
|
def verify_payment(options)
|
15
|
-
options = options.with_indifferent_access
|
16
|
-
recipient_id = options.fetch('recipient_id')
|
17
|
-
asset_id = options.fetch('asset_id')
|
18
|
-
amount = options.fetch('amount')
|
19
|
-
trace = options.fetch('trace')
|
20
19
|
path = 'payments'
|
21
20
|
payload = {
|
22
|
-
asset_id: asset_id,
|
23
|
-
opponent_id:
|
24
|
-
amount: amount,
|
25
|
-
trace_id: trace
|
21
|
+
asset_id: options[:asset_id],
|
22
|
+
opponent_id: options[:opponent_id],
|
23
|
+
amount: options[:amount].to_s,
|
24
|
+
trace_id: options[:trace]
|
26
25
|
}
|
26
|
+
|
27
27
|
client.post(path, json: payload)
|
28
28
|
end
|
29
29
|
end
|
data/lib/mixin_bot/api/pin.rb
CHANGED
@@ -1,56 +1,92 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module MixinBot
|
2
4
|
class API
|
3
5
|
module Pin
|
4
|
-
|
6
|
+
# https://developers.mixin.one/api/alpha-mixin-network/verify-pin/
|
7
|
+
def verify_pin(pin_code)
|
5
8
|
path = '/pin/verify'
|
6
9
|
payload = {
|
7
10
|
pin: encrypt_pin(pin_code)
|
8
11
|
}
|
9
12
|
|
10
|
-
access_token
|
11
|
-
authorization = format('Bearer
|
13
|
+
access_token = access_token('POST', path, payload.to_json)
|
14
|
+
authorization = format('Bearer %<access_token>s', access_token: access_token)
|
15
|
+
client.post(path, headers: { 'Authorization': authorization }, json: payload)
|
16
|
+
end
|
17
|
+
|
18
|
+
# https://developers.mixin.one/api/alpha-mixin-network/create-pin/
|
19
|
+
def update_pin(old_pin:, pin:)
|
20
|
+
path = '/pin/update'
|
21
|
+
encrypted_old_pin = old_pin.nil? ? '' : encrypt_pin(old_pin, iterator: Time.now.utc.to_i)
|
22
|
+
encrypted_pin = encrypt_pin(pin, iterator: Time.now.utc.to_i + 1)
|
23
|
+
payload = {
|
24
|
+
old_pin: encrypted_old_pin,
|
25
|
+
pin: encrypted_pin
|
26
|
+
}
|
27
|
+
|
28
|
+
access_token = access_token('POST', path, payload.to_json)
|
29
|
+
authorization = format('Bearer %<access_token>s', access_token: access_token)
|
12
30
|
client.post(path, headers: { 'Authorization': authorization }, json: payload)
|
13
31
|
end
|
14
32
|
|
33
|
+
# decrypt the encrpted pin, just for test
|
15
34
|
def decrypt_pin(msg)
|
16
35
|
msg = Base64.strict_decode64 msg
|
17
36
|
iv = msg[0..15]
|
18
37
|
cipher = msg[16..47]
|
19
|
-
aes_key = JOSE::JWA::PKCS1::rsaes_oaep_decrypt('SHA256', pin_token, private_key, session_id)
|
20
38
|
alg = 'AES-256-CBC'
|
21
39
|
decode_cipher = OpenSSL::Cipher.new(alg)
|
22
40
|
decode_cipher.decrypt
|
23
41
|
decode_cipher.iv = iv
|
24
|
-
decode_cipher.key =
|
25
|
-
|
26
|
-
|
42
|
+
decode_cipher.key = _generate_aes_key
|
43
|
+
decoded = decode_cipher.update(cipher)
|
44
|
+
decoded[0..5]
|
27
45
|
end
|
28
46
|
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
47
|
+
# https://developers.mixin.one/api/alpha-mixin-network/encrypted-pin/
|
48
|
+
# use timestamp(timestamp) for iterator as default: must be bigger than the previous, the first time must be greater than 0. After a new session created, it will be reset to 0.
|
49
|
+
def encrypt_pin(pin_code, iterator: nil)
|
50
|
+
iterator ||= Time.now.utc.to_i
|
51
|
+
tszero = iterator % 0x100
|
52
|
+
tsone = (iterator % 0x10000) >> 8
|
53
|
+
tstwo = (iterator % 0x1000000) >> 16
|
54
|
+
tsthree = (iterator % 0x100000000) >> 24
|
55
|
+
tsstring = "#{tszero.chr}#{tsone.chr}#{tstwo.chr}#{tsthree.chr}\u0000\u0000\u0000\u0000"
|
37
56
|
encrypt_content = pin_code + tsstring + tsstring
|
38
57
|
pad_count = 16 - encrypt_content.length % 16
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
58
|
+
padded_content =
|
59
|
+
if pad_count.positive?
|
60
|
+
encrypt_content + pad_count.chr * pad_count
|
61
|
+
else
|
62
|
+
encrypt_content
|
63
|
+
end
|
44
64
|
|
45
65
|
alg = 'AES-256-CBC'
|
46
66
|
aes = OpenSSL::Cipher.new(alg)
|
47
67
|
iv = OpenSSL::Cipher.new(alg).random_iv
|
48
68
|
aes.encrypt
|
49
|
-
aes.key =
|
69
|
+
aes.key = _generate_aes_key
|
50
70
|
aes.iv = iv
|
51
71
|
cipher = aes.update(padded_content)
|
52
72
|
msg = iv + cipher
|
53
|
-
|
73
|
+
Base64.strict_encode64 msg
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
def _generate_aes_key
|
78
|
+
if pin_token.size == 32
|
79
|
+
JOSE::JWA::X25519.x25519(
|
80
|
+
JOSE::JWA::Ed25519.secret_to_curve25519(private_key[0..31]),
|
81
|
+
pin_token
|
82
|
+
)
|
83
|
+
else
|
84
|
+
JOSE::JWA::PKCS1.rsaes_oaep_decrypt(
|
85
|
+
'SHA256',
|
86
|
+
pin_token,
|
87
|
+
OpenSSL::PKey::RSA.new(private_key),
|
88
|
+
session_id
|
89
|
+
)
|
54
90
|
end
|
55
91
|
end
|
56
92
|
end
|
@@ -1,26 +1,41 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module MixinBot
|
2
4
|
class API
|
3
5
|
module Snapshot
|
4
|
-
def
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
6
|
+
def read_network_snapshots(options = {})
|
7
|
+
path = format(
|
8
|
+
'/network/snapshots?limit=%<limit>s&offset=%<offset>s&asset=%<asset>s&order=%<order>s',
|
9
|
+
limit: options[:limit],
|
10
|
+
offset: options[:offset],
|
11
|
+
asset: options[:asset],
|
12
|
+
order: options[:order]
|
13
|
+
)
|
10
14
|
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
offset: offset,
|
15
|
-
asset: asset,
|
16
|
-
order: order
|
17
|
-
}
|
18
|
-
client.get(path, params: payload)
|
15
|
+
access_token = options[:access_token] || access_token('GET', path)
|
16
|
+
authorization = format('Bearer %<access_token>s', access_token: access_token)
|
17
|
+
client.get(path, headers: { 'Authorization': authorization })
|
19
18
|
end
|
20
19
|
|
21
|
-
def
|
22
|
-
path = format(
|
23
|
-
|
20
|
+
def read_snapshots(options = {})
|
21
|
+
path = format(
|
22
|
+
'/snapshots?limit=%<limit>s&offset=%<offset>s&asset=%<asset>s',
|
23
|
+
limit: options[:limit],
|
24
|
+
offset: options[:offset],
|
25
|
+
asset: options[:asset]
|
26
|
+
)
|
27
|
+
|
28
|
+
access_token = options[:access_token] || access_token('GET', path)
|
29
|
+
authorization = format('Bearer %<access_token>s', access_token: access_token)
|
30
|
+
client.get(path, headers: { 'Authorization': authorization })
|
31
|
+
end
|
32
|
+
|
33
|
+
def read_network_snapshot(snapshot_id, options = {})
|
34
|
+
path = format('/network/snapshots/%<snapshot_id>s', snapshot_id: snapshot_id)
|
35
|
+
|
36
|
+
access_token = options[:access_token] || access_token('GET', path)
|
37
|
+
authorization = format('Bearer %<access_token>s', access_token: access_token)
|
38
|
+
client.get(path, headers: { 'Authorization': authorization })
|
24
39
|
end
|
25
40
|
end
|
26
41
|
end
|
@@ -1,35 +1,35 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module MixinBot
|
2
4
|
class API
|
3
5
|
module Transfer
|
4
|
-
def create_transfer(pin, options)
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
trace_id = options.fetch('trace_id')
|
12
|
-
trace_id ||= SecureRandom.uuid
|
6
|
+
def create_transfer(pin, options, access_token: nil)
|
7
|
+
asset_id = options[:asset_id]
|
8
|
+
opponent_id = options[:opponent_id]
|
9
|
+
amount = options[:amount]
|
10
|
+
memo = options[:memo]
|
11
|
+
trace_id = options[:trace_id] || SecureRandom.uuid
|
12
|
+
encrypted_pin = options[:encrypted_pin] || encrypt_pin(pin)
|
13
13
|
|
14
14
|
path = '/transfers'
|
15
15
|
payload = {
|
16
16
|
asset_id: asset_id,
|
17
17
|
opponent_id: opponent_id,
|
18
|
-
pin:
|
19
|
-
amount: amount,
|
18
|
+
pin: encrypted_pin,
|
19
|
+
amount: amount.to_s,
|
20
20
|
trace_id: trace_id,
|
21
21
|
memo: memo
|
22
22
|
}
|
23
23
|
|
24
|
-
access_token ||=
|
25
|
-
authorization = format('Bearer
|
24
|
+
access_token ||= access_token('POST', path, payload.to_json)
|
25
|
+
authorization = format('Bearer %<access_token>s', access_token: access_token)
|
26
26
|
client.post(path, headers: { 'Authorization': authorization }, json: payload)
|
27
27
|
end
|
28
28
|
|
29
|
-
def read_transfer(trace_id)
|
30
|
-
path = format('/transfers/trace
|
31
|
-
access_token ||=
|
32
|
-
authorization = format('Bearer
|
29
|
+
def read_transfer(trace_id, access_token: nil)
|
30
|
+
path = format('/transfers/trace/%<trace_id>s', trace_id: trace_id)
|
31
|
+
access_token ||= access_token('GET', path, '')
|
32
|
+
authorization = format('Bearer %<access_token>s', access_token: access_token)
|
33
33
|
client.get(path, headers: { 'Authorization': authorization })
|
34
34
|
end
|
35
35
|
end
|
data/lib/mixin_bot/api/user.rb
CHANGED
@@ -1,29 +1,77 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module MixinBot
|
2
4
|
class API
|
3
5
|
module User
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
6
|
+
# https://developers.mixin.one/api/beta-mixin-message/read-user/
|
7
|
+
def read_user(user_id)
|
8
|
+
# user_id: Mixin User UUID
|
9
|
+
path = format('/users/%<user_id>s', user_id: user_id)
|
10
|
+
access_token = access_token('GET', path, '')
|
11
|
+
authorization = format('Bearer %<access_token>s', access_token: access_token)
|
9
12
|
client.get(path, headers: { 'Authorization': authorization })
|
10
13
|
end
|
11
14
|
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
15
|
+
# https://developers.mixin.one/api/alpha-mixin-network/app-user/
|
16
|
+
# Create a new Mixin Network user (like a normal Mixin Messenger user). You should keep PrivateKey which is used to sign an AuthenticationToken and encrypted PIN for the user.
|
17
|
+
def create_user(full_name, key_type: 'RSA', rsa_key: nil, ed25519_key: nil)
|
18
|
+
case key_type
|
19
|
+
when 'RSA'
|
20
|
+
rsa_key ||= generate_rsa_key
|
21
|
+
session_secret = rsa_key[:public_key].gsub(/^-----.*PUBLIC KEY-----$/, '').strip
|
22
|
+
when 'Ed25519'
|
23
|
+
ed25519_key ||= generate_ed25519_key
|
24
|
+
session_secret = ed25519_key[:public_key]
|
25
|
+
else
|
26
|
+
raise 'Only RSA and Ed25519 are supported'
|
27
|
+
end
|
28
|
+
|
29
|
+
payload = {
|
30
|
+
full_name: full_name,
|
31
|
+
session_secret: session_secret
|
32
|
+
}
|
33
|
+
access_token = access_token('POST', '/users', payload.to_json)
|
34
|
+
authorization = format('Bearer %<access_token>s', access_token: access_token)
|
35
|
+
res = client.post('/users', headers: { 'Authorization': authorization }, json: payload)
|
36
|
+
|
37
|
+
res.merge(rsa_key: rsa_key, ed25519_key: ed25519_key)
|
38
|
+
end
|
39
|
+
|
40
|
+
def generate_rsa_key
|
41
|
+
rsa_key = OpenSSL::PKey::RSA.new 1024
|
42
|
+
{
|
43
|
+
private_key: rsa_key.to_pem,
|
44
|
+
public_key: rsa_key.public_key.to_pem
|
45
|
+
}
|
46
|
+
end
|
47
|
+
|
48
|
+
def generate_ed25519_key
|
49
|
+
ed25519_key = JOSE::JWA::Ed25519.keypair
|
50
|
+
{
|
51
|
+
private_key: Base64.strict_encode64(ed25519_key[1]),
|
52
|
+
public_key: Base64.strict_encode64(ed25519_key[0])
|
53
|
+
}
|
54
|
+
end
|
55
|
+
|
56
|
+
# https://developers.mixin.one/api/beta-mixin-message/search-user/
|
57
|
+
# search by Mixin Id or Phone Number
|
58
|
+
def search_user(query)
|
59
|
+
path = format('/search/%<query>s', query: query)
|
60
|
+
|
61
|
+
access_token = access_token('GET', path, '')
|
62
|
+
authorization = format('Bearer %<access_token>s', access_token: access_token)
|
17
63
|
client.get(path, headers: { 'Authorization': authorization })
|
18
64
|
end
|
19
65
|
|
20
|
-
|
66
|
+
# https://developers.mixin.one/api/beta-mixin-message/read-users/
|
67
|
+
def fetch_users(user_ids)
|
21
68
|
# user_ids: a array of user_ids
|
22
69
|
path = '/users/fetch'
|
23
70
|
user_ids = [user_ids] if user_ids.is_a? String
|
24
71
|
payload = user_ids
|
25
|
-
|
26
|
-
|
72
|
+
|
73
|
+
access_token = access_token('POST', path, payload.to_json)
|
74
|
+
authorization = format('Bearer %<access_token>s', access_token: access_token)
|
27
75
|
client.post(path, headers: { 'Authorization': authorization }, json: payload)
|
28
76
|
end
|
29
77
|
end
|
@@ -0,0 +1,78 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module MixinBot
|
4
|
+
class API
|
5
|
+
module Withdraw
|
6
|
+
# https://developers.mixin.one/api/alpha-mixin-network/create-address/
|
7
|
+
def create_withdraw_address(options, access_token: nil)
|
8
|
+
path = '/addresses'
|
9
|
+
encrypted_pin = encrypt_pin(options[:pin])
|
10
|
+
payload =
|
11
|
+
# for EOS withdraw, account_name & account_tag must be valid
|
12
|
+
if options[:public_key].nil?
|
13
|
+
{
|
14
|
+
asset_id: options[:asset_id],
|
15
|
+
account_name: options[:account_name],
|
16
|
+
account_tag: options[:account_tag],
|
17
|
+
label: options[:label],
|
18
|
+
pin: encrypted_pin
|
19
|
+
}
|
20
|
+
# for other withdraw
|
21
|
+
else
|
22
|
+
{
|
23
|
+
asset_id: options[:asset_id],
|
24
|
+
public_key: options[:public_key],
|
25
|
+
label: options[:label],
|
26
|
+
pin: encrypted_pin
|
27
|
+
}
|
28
|
+
end
|
29
|
+
|
30
|
+
access_token ||= access_token('POST', path, payload.to_json)
|
31
|
+
authorization = format('Bearer %<access_token>s', access_token: access_token)
|
32
|
+
client.post(path, headers: { 'Authorization': authorization }, json: payload)
|
33
|
+
end
|
34
|
+
|
35
|
+
# https://developers.mixin.one/api/alpha-mixin-network/read-address/
|
36
|
+
def get_withdraw_address(address, access_token: nil)
|
37
|
+
path = format('/addresses/%<address>s', address: address)
|
38
|
+
access_token ||= access_token('GET', path, '')
|
39
|
+
authorization = format('Bearer %<access_token>s', access_token: access_token)
|
40
|
+
client.get(path, headers: { 'Authorization': authorization })
|
41
|
+
end
|
42
|
+
|
43
|
+
# https://developers.mixin.one/api/alpha-mixin-network/delete-address/
|
44
|
+
def delete_withdraw_address(address, pin, access_token: nil)
|
45
|
+
path = format('/addresses/%<address>s/delete', address: address)
|
46
|
+
payload = {
|
47
|
+
pin: encrypt_pin(pin)
|
48
|
+
}
|
49
|
+
|
50
|
+
access_token ||= access_token('POST', path, payload.to_json)
|
51
|
+
authorization = format('Bearer %<access_token>s', access_token: access_token)
|
52
|
+
client.post(path, headers: { 'Authorization': authorization }, json: payload)
|
53
|
+
end
|
54
|
+
|
55
|
+
# https://developers.mixin.one/api/alpha-mixin-network/withdrawal-addresses/
|
56
|
+
def withdrawals(options, access_token: nil)
|
57
|
+
address_id = options[:address_id]
|
58
|
+
pin = options[:pin]
|
59
|
+
amount = options[:amount]
|
60
|
+
trace_id = options[:trace_id]
|
61
|
+
memo = options[:memo]
|
62
|
+
|
63
|
+
path = '/withdrawals'
|
64
|
+
payload = {
|
65
|
+
address_id: address_id,
|
66
|
+
amount: amount,
|
67
|
+
trace_id: trace_id,
|
68
|
+
memo: memo,
|
69
|
+
pin: encrypt_pin(pin)
|
70
|
+
}
|
71
|
+
|
72
|
+
access_token ||= access_token('POST', path, payload.to_json)
|
73
|
+
authorization = format('Bearer %<access_token>s', access_token: access_token)
|
74
|
+
client.post(path, headers: { 'Authorization': authorization }, json: payload)
|
75
|
+
end
|
76
|
+
end
|
77
|
+
end
|
78
|
+
end
|
@@ -0,0 +1,128 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'awesome_print'
|
4
|
+
require 'cli/ui'
|
5
|
+
require 'thor'
|
6
|
+
require 'yaml'
|
7
|
+
require 'json'
|
8
|
+
require_relative './cli/node'
|
9
|
+
require_relative './cli/me'
|
10
|
+
require_relative './cli/multisig'
|
11
|
+
|
12
|
+
module MixinBot
|
13
|
+
class CLI < Thor
|
14
|
+
# https://github.com/Shopify/cli-ui
|
15
|
+
UI = ::CLI::UI
|
16
|
+
|
17
|
+
class_option :apihost, type: :string, aliases: '-a', desc: 'Specify mixin api host, default as api.mixin.one'
|
18
|
+
class_option :pretty, type: :boolean, aliases: '-p', desc: 'Print output in pretty'
|
19
|
+
|
20
|
+
attr_reader :config, :api
|
21
|
+
|
22
|
+
def initialize(*args)
|
23
|
+
super
|
24
|
+
if File.exist? options[:config].to_s
|
25
|
+
@config =
|
26
|
+
begin
|
27
|
+
YAML.load_file options[:config]
|
28
|
+
rescue StandardError => e
|
29
|
+
log UI.fmt(
|
30
|
+
format(
|
31
|
+
'{{x}} %<file>s is not a valid .yml file',
|
32
|
+
file: options[:config]
|
33
|
+
)
|
34
|
+
)
|
35
|
+
UI::Frame.open('{{x}}', color: :red) do
|
36
|
+
log e
|
37
|
+
end
|
38
|
+
end
|
39
|
+
elsif options[:config]
|
40
|
+
@confg =
|
41
|
+
begin
|
42
|
+
JSON.parse options[:config]
|
43
|
+
rescue StandardError => e
|
44
|
+
log UI.fmt(
|
45
|
+
format(
|
46
|
+
'{{x}} Failed to parse %<config>s',
|
47
|
+
config: options[:config]
|
48
|
+
)
|
49
|
+
)
|
50
|
+
UI::Frame.open('{{x}}', color: :red) do
|
51
|
+
log e
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
return unless @config
|
57
|
+
|
58
|
+
MixinBot.api_host = options[:apihost]
|
59
|
+
@api ||=
|
60
|
+
begin
|
61
|
+
MixinBot::API.new(
|
62
|
+
client_id: @config['client_id'],
|
63
|
+
client_secret: @config['client_secret'],
|
64
|
+
session_id: @config['session_id'],
|
65
|
+
pin_token: @config['pin_token'],
|
66
|
+
private_key: @config['private_key'],
|
67
|
+
pin_code: @config['pin_code']
|
68
|
+
)
|
69
|
+
rescue StandardError => e
|
70
|
+
log UI.fmt '{{x}}: Failed to initialize api, maybe your config is incorrect.'
|
71
|
+
UI.Frame.open('{{x}}', color: :red) do
|
72
|
+
log e
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
desc 'node', 'mixin node commands helper'
|
78
|
+
subcommand 'node', MixinBot::NodeCLI
|
79
|
+
|
80
|
+
desc 'version', 'Distay MixinBot version'
|
81
|
+
def version
|
82
|
+
log MixinBot::VERSION
|
83
|
+
end
|
84
|
+
|
85
|
+
def self.exit_on_failure?
|
86
|
+
true
|
87
|
+
end
|
88
|
+
|
89
|
+
private
|
90
|
+
|
91
|
+
def api_method(method, *args, **params)
|
92
|
+
if api.nil?
|
93
|
+
log UI.fmt '{{x}} MixinBot api not initialized!'
|
94
|
+
return
|
95
|
+
end
|
96
|
+
|
97
|
+
res = if args.empty? && params.empty?
|
98
|
+
api&.public_send method
|
99
|
+
elsif args.empty? && !params.empty?
|
100
|
+
api&.public_send method params
|
101
|
+
elsif !args.empty? && params.empty?
|
102
|
+
api&.public_send method, args
|
103
|
+
else
|
104
|
+
args.push params
|
105
|
+
api&.public_send method, args
|
106
|
+
end
|
107
|
+
log res
|
108
|
+
|
109
|
+
[res, res && res['error'].nil?]
|
110
|
+
rescue MixinBot::Errors => e
|
111
|
+
UI::Frame.open('{{x}}', color: :red) do
|
112
|
+
log e
|
113
|
+
end
|
114
|
+
end
|
115
|
+
|
116
|
+
def log(obj)
|
117
|
+
if options[:pretty]
|
118
|
+
if obj.is_a? String
|
119
|
+
puts obj
|
120
|
+
else
|
121
|
+
ap obj
|
122
|
+
end
|
123
|
+
else
|
124
|
+
puts obj.inspect
|
125
|
+
end
|
126
|
+
end
|
127
|
+
end
|
128
|
+
end
|