keybase-unofficial-local 0.2.1 → 0.3.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: '09ef090a265fc40d07a8564a2fc5514bb6a0cafc'
4
- data.tar.gz: f153a504b1beecd3570dcec400bfec883c587005
3
+ metadata.gz: f3a1adda41e99d65322a01fe1743e53372a89a9c
4
+ data.tar.gz: d03dab857b300bb9066ec45da73922a69f45d150
5
5
  SHA512:
6
- metadata.gz: 4fb253de4da7fc91d05002652c3f6a6b0569e21e287e01436ebbab5edf14b57da117514a53fa781edf6e84b6404c88796b88aacb17a86ceca8e6d9bfc07f4c75
7
- data.tar.gz: d410503e96997a14d905b51c117b198171c3bc980b2fc6332b87f2882d0b0044e2c0eb866395eeaf702b5fe8b2561e0f8eec02dab7a78e764f384da20e94a432
6
+ metadata.gz: '09e28fb48d0732a42e856cbf93a79cccdefc3f9e1040ff347c157631a8f8367709b819412a71242f0272ee2f4f40ebad232e25a2bbb139d757957e59b25093bf'
7
+ data.tar.gz: 85b46b56b645ca98bb6740c8a4b51ed42e203bee91539277bd92b404847874915654ec410919a9ba224f7f7d9511e0c8b46191793ca53b0e68fa9679de9cd7db
@@ -25,28 +25,41 @@ module Keybase
25
25
  }.to_json
26
26
  end
27
27
 
28
- # @param payload [String] the JSON payload to send to the chat API
28
+ # Cleans up the object returned by {chat_call}.
29
+ # @param struct [OpenStruct] a structified response from the Keybase chat API
30
+ # @return [OpenStruct] an unwrapped version of the response
31
+ # @raise [Exceptions::ChatError] when the struct contains an error message
32
+ # @api private
33
+ def unwrap(struct)
34
+ raise Exceptions::ChatError, struct.error.message if struct.error
35
+
36
+ struct.result
37
+ end
38
+
39
+ # Makes chat API calls.
40
+ # @param meth [String, Symbol] the team method
41
+ # @param options [Hash] the options hash
29
42
  # @return [OpenStruct] a struct mapping of the JSON response
43
+ # @raise [Exceptions::ChatError] if the chat call fails
30
44
  # @api private
31
- def chat_call(payload)
45
+ def chat_call(meth, options: {})
32
46
  response = Open3.popen3(*CHAT_EXEC_ARGS) do |stdin, stdout, _, _|
33
- stdin.write payload
34
- stdin.close # close after writing to let keybase know we're done
47
+ stdin.write envelope meth, options: options
48
+ stdin.close
35
49
  stdout.read
36
50
  end
37
51
 
38
- JSON.parse response, object_class: OpenStruct
52
+ unwrap JSON.parse response, object_class: OpenStruct
39
53
  end
40
54
 
41
- # List the user's inbox.
55
+ # List the current user's inbox.
42
56
  # @param topic_type [String] the topic type to list by
43
57
  # @return [OpenStruct] a struct mapping of the JSON response
58
+ # @raise [Exceptions::ChatError] if the chat call fails
44
59
  def list_inbox(topic_type: nil)
45
- payload = envelope :list, options: {
60
+ chat_call :list, options: {
46
61
  topic_type: topic_type,
47
62
  }
48
-
49
- chat_call payload
50
63
  end
51
64
 
52
65
  # Read a conversation.
@@ -54,16 +67,15 @@ module Keybase
54
67
  # @param peek [Boolean] whether to mark the conversation read
55
68
  # @param unread_only [Boolean] whether to fetch unread messages only
56
69
  # @return [OpenStruct] a struct mapping of the JSON response
70
+ # @raise [Exceptions::ChatError] if the chat call fails
57
71
  def conversation(users, peek: false, unread_only: false)
58
- payload = envelope :read, options: {
72
+ chat_call :read, options: {
59
73
  channel: {
60
74
  name: Core::U[*users],
61
75
  },
62
76
  peek: peek,
63
77
  unread_only: unread_only,
64
78
  }
65
-
66
- chat_call payload
67
79
  end
68
80
 
69
81
  # Send a message to a conversation.
@@ -71,8 +83,9 @@ module Keybase
71
83
  # @param message [String] the message to send
72
84
  # @param public [Boolean] whether to send the message to a public channel
73
85
  # @return [OpenStruct] a struct mapping of the JSON response
86
+ # @raise [Exceptions::ChatError] if the chat call fails
74
87
  def send_message(users, message, public: false)
75
- payload = envelope :send, options: {
88
+ chat_call :send, options: {
76
89
  channel: {
77
90
  name: Core::U[*users],
78
91
  public: public,
@@ -81,23 +94,20 @@ module Keybase
81
94
  body: message,
82
95
  },
83
96
  }
84
-
85
- chat_call payload
86
97
  end
87
98
 
88
99
  # Delete a message from a conversation.
89
100
  # @param users [Array<String>] a list of the users in the conversation
90
101
  # @param id [Integer] the id of the message to delete
91
102
  # @return [OpenStruct] a struct mapping of the JSON response
103
+ # @raise [Exceptions::ChatError] if the chat call fails
92
104
  def delete_message(users, id)
93
- payload = envelope :delete, options: {
105
+ chat_call :delete, options: {
94
106
  channel: {
95
107
  name: Core::U[*users],
96
108
  },
97
109
  message_id: id,
98
110
  }
99
-
100
- chat_call payload
101
111
  end
102
112
 
103
113
  # Edit a message in a conversation.
@@ -105,8 +115,9 @@ module Keybase
105
115
  # @param id [Integer] the id of the message to delete
106
116
  # @param message [String] the message to send
107
117
  # @return [OpenStruct] a struct mapping of the JSON response
118
+ # @raise [Exceptions::ChatError] if the chat call fails
108
119
  def edit_message(users, id, message)
109
- payload = envelope :edit, options: {
120
+ chat_call :edit, options: {
110
121
  channel: {
111
122
  name: Core::U[*users],
112
123
  },
@@ -115,8 +126,6 @@ module Keybase
115
126
  body: message,
116
127
  },
117
128
  }
118
-
119
- chat_call payload
120
129
  end
121
130
 
122
131
  # Upload a file to a conversation.
@@ -124,16 +133,15 @@ module Keybase
124
133
  # @param path [String] the pathname of the file to upload
125
134
  # @param title [String] the uploaded file's title
126
135
  # @return [OpenStruct] a struct mapping of the JSON response
136
+ # @raise [Exceptions::ChatError] if the chat call fails
127
137
  def upload_attachment(users, path, title)
128
- payload = envelope :attach, options: {
138
+ chat_call :attach, options: {
129
139
  channel: {
130
140
  name: Core::U[*users],
131
141
  },
132
142
  filename: path,
133
143
  title: title,
134
144
  }
135
-
136
- chat_call payload
137
145
  end
138
146
 
139
147
  # Download a file from a conversation.
@@ -141,45 +149,42 @@ module Keybase
141
149
  # @param id [Integer] the id of the message to download from
142
150
  # @param path [String] the pathname to download to
143
151
  # @return [OpenStruct] a struct mapping of the JSON response
152
+ # @raise [Exceptions::ChatError] if the chat call fails
144
153
  def download_attachment(users, id, path)
145
- payload = envelope :download, options: {
154
+ chat_call :download, options: {
146
155
  channel: {
147
156
  name: Core::U[*users],
148
157
  },
149
158
  message_id: id,
150
159
  output: path,
151
160
  }
152
-
153
- chat_call payload
154
161
  end
155
162
 
156
163
  # Make a conversation as read up to a specific ID.
157
164
  # @param users [Array<String>] a list of the users in the conversation
158
165
  # @param id [Integer] the id of the message to mark up to
159
166
  # @return [OpenStruct] a struct mapping of the JSON response
167
+ # @raise [Exceptions::ChatError] if the chat call fails
160
168
  def mark_conversation(users, id)
161
- payload = envelope :mark, options: {
169
+ chat_call :mark, options: {
162
170
  channel: {
163
171
  name: Core::U[*users],
164
172
  },
165
173
  message_id: id,
166
174
  }
167
-
168
- chat_call payload
169
175
  end
170
176
 
171
177
  # Mute a conversation.
172
178
  # @param users [Array<String>] a list of the users in the conversation
173
179
  # @return [OpenStruct] a struct mapping of the JSON response
180
+ # @raise [Exceptions::ChatError] if the chat call fails
174
181
  def mute_conversation(users)
175
- payload = envelope :setstatus, options: {
182
+ chat_call :setstatus, options: {
176
183
  channel: {
177
184
  name: Core::U[*users],
178
185
  },
179
186
  status: "muted",
180
187
  }
181
-
182
- chat_call payload
183
188
  end
184
189
  end
185
190
  end
@@ -24,6 +24,22 @@ module Keybase
24
24
  super "KBFS needs to be enabled and running"
25
25
  end
26
26
  end
27
+
28
+ # Raised whenever a {Keybase::Local::Chat} call fails.
29
+ class ChatError < Core::Exceptions::KeybaseError
30
+ # @param message [String] the error message returned by the API
31
+ def initialize(message)
32
+ super message
33
+ end
34
+ end
35
+
36
+ # Raised whenever a {Keybase::Local::Team} call fails.
37
+ class TeamError < Core::Exceptions::KeybaseError
38
+ # @param message [String] the error message returned by the API
39
+ def initialize(message)
40
+ super message
41
+ end
42
+ end
27
43
  end
28
44
  end
29
45
  end
@@ -2,138 +2,167 @@
2
2
 
3
3
  require "open3"
4
4
  require "json"
5
+ require "ostruct"
5
6
 
6
7
  module Keybase
7
8
  module Local
8
- # Represents an interface to Keybase's teams.
9
+ # Represents Keybase's JSON team API.
9
10
  module Team
10
11
  # The initial arguments to pass when executing Keybase for team management.
11
- TEAM_EXEC_ARGS = %w[keybase team].freeze
12
-
13
- # The pattern used to (partially) validate team names.
14
- # @see https://github.com/keybase/client/blob/5aa02d1b351f0dfab050eb5ae22bffdf59f61d91/go/protocol/keybase1/extras.go#L1560
15
- TEAM_PATTERN = /([a-zA-Z0-9][a-zA-Z0-9_]?)+/
12
+ TEAM_EXEC_ARGS = %w[keybase team api].freeze
16
13
 
17
14
  class << self
18
- # @param args [Array<String>] additional arguments to pass to `keybase team`
19
- # @param payload [String, nil] input data to feed to the invocation
20
- # @param json [Boolean] whether or not to parse `stdout` as JSON
21
- # @return [Hash, Boolean, nil] the parsed JSON, or a true/false/nil result indicating
22
- # command success
15
+ # @param meth [Symbol] the team method
16
+ # @param options [Hash] the options hash
17
+ # @return [String] the JSON serialized envelope
23
18
  # @api private
24
- def team_call(*args, payload: nil, json: false)
25
- if json
26
- response = Open3.popen3(*TEAM_EXEC_ARGS, *args) do |stdin, stdout, _, _|
27
- stdin.write payload if payload
28
- stdin.close # close after writing to let keybase know we're done
29
- stdout.read
30
- end
31
-
32
- if response.empty?
33
- {}
34
- else
35
- JSON.parse response
36
- end
37
- else
38
- system(*TEAM_EXEC_ARGS, *args)
39
- end
19
+ def envelope(meth, options: {})
20
+ {
21
+ method: meth,
22
+ params: {
23
+ options: options,
24
+ },
25
+ }.to_json
40
26
  end
41
27
 
42
- # Create a new Keybase team.
43
- # @note This is a stub.
28
+ # Cleans up the object returned by {team_call}.
29
+ # @param struct [OpenStruct] a structified response from the Keybase team API
30
+ # @return [OpenStruct] an unwrapped version of the response
31
+ # @raise [Exceptions::TeamError] when the struct contains an error message
44
32
  # @api private
45
- def create(_team)
46
- # stub
47
- end
33
+ def unwrap(struct)
34
+ raise Exceptions::TeamError, struct.error.message if struct.error
48
35
 
49
- # Add a user to a Keybase team.
50
- # @note This is a stub.
51
- # @api private
52
- def add_member(_team, _user, _role: :reader, _email: false)
53
- # stub
36
+ struct.result
54
37
  end
55
38
 
56
- # Remove a user from a Keybase team.
57
- # @note This is a stub.
39
+ # Makes team API calls.
40
+ # @param meth [String, Symbol] the team method
41
+ # @param options [Hash] the options hash
42
+ # @return [OpenStruct] a struct mapping on the JSON response
58
43
  # @api private
59
- def remove_member(_team, _user)
60
- # stub
44
+ def team_call(meth, options: {})
45
+ response = Open3.popen3(*TEAM_EXEC_ARGS) do |stdin, stdout, _, _|
46
+ stdin.write envelope meth, options: options
47
+ stdin.close
48
+ stdout.read
49
+ end
50
+
51
+ unwrap JSON.parse response, object_class: OpenStruct
61
52
  end
62
53
 
63
- # Modify a user in a Keybase team.
64
- # @note This is a stub.
65
- # @api private
66
- def edit_member(_team, _user, _role: :reader)
67
- # stub
54
+ # List all team memberships for the current user.
55
+ # @return [OpenStruct] a struct mapping of the JSON response
56
+ # @raise [Exceptions::TeamError] if the team call fails
57
+ def list_self_memberships
58
+ team_call "list-self-memberships"
68
59
  end
69
60
 
70
- # List all teams currently belonged to.
71
- # @param force_poll [Boolean] whether or not to force a poll of the server for all idents
72
- # @return [Hash] a hash representation of all teams currently belonged to
73
- def list_memberships(force_poll: false)
74
- args = %w[list-memberships --json]
75
- args << "--force-poll" if force_poll
61
+ alias self_memberships list_self_memberships
76
62
 
77
- team_call(*args, json: true)
63
+ # List all users in the given team.
64
+ # @param team [String] the team to list
65
+ # @return [OpenStruct] a struct mapping of the JSON response
66
+ # @raise [Exceptions::TeamError] if the team call fails
67
+ def list_team_memberships(team)
68
+ team_call "list-team-memberships", options: {
69
+ team: team,
70
+ }
78
71
  end
79
72
 
80
- # List all members of the given team.
81
- # @param force_poll [Boolean] whether or not to force a poll of the server for all idents
82
- # @return [Hash] a hash representation of all members of the given team
83
- def list_members(team, force_poll: false)
84
- args = %W[list-members #{team} --json]
85
- args << "--force-poll" if force_poll
73
+ alias team_memberships list_team_memberships
86
74
 
87
- team_call(*args, json: true)
75
+ # List teams for a user.
76
+ # @param user [String] a Keybase username
77
+ # @return [OpenStruct] a struct mapping of the JSON response
78
+ # @raise [Exceptions::TeamError] if the team call fails
79
+ def list_user_memberships(user)
80
+ team_call "list-user-memberships", options: {
81
+ username: user,
82
+ }
88
83
  end
89
84
 
90
- # Change the name of a Keybase team.
91
- # @note This is a stub.
92
- # @api private
93
- def rename(_old_team, _new_team)
94
- # stub
95
- end
85
+ alias user_memberships list_user_memberships
96
86
 
97
- # Request access to a Keybase team.
98
- # @note This is a stub.
99
- # @api private
100
- def request_access(_team)
101
- # stub
87
+ # Create a new team.
88
+ # @param team [String] the team name
89
+ # @return [OpenStruct] a struct mapping of the JSON response
90
+ # @raise [Exceptions::TeamError] if the team call fails
91
+ def create_team(team)
92
+ team_call "create-team", options: {
93
+ team: team,
94
+ }
102
95
  end
103
96
 
104
- # List requests to join Keybase teams.
105
- # @note This is a stub.
106
- # @api private
107
- def list_requests
108
- # stub
97
+ # Add members to a team.
98
+ # @param team [String] the team name
99
+ # @param emails [Array<Hash>] a list of email-role hashes to add to the team
100
+ # @param users [Array<Hash>] a list of Keybase user-role hashes to add to the team
101
+ # @return [OpenStruct] a struct mapping of the JSON response
102
+ # @raise [Exceptions::TeamError] if the team call fails
103
+ # @example
104
+ # Keybase::Local::Team.add_members "foo", users: [{ username: "bob", role: "reader" }]
105
+ # Keybase::Local::Team.add_members "bar", emails: [{ email: "foo@bar.com", role: "admin" }]
106
+ def add_members(team, emails: [], users: [])
107
+ team_call "add-members", options: {
108
+ team: team,
109
+ emails: emails,
110
+ usernames: users,
111
+ }
109
112
  end
110
113
 
111
- # Ignore a request to join a Keybase team.
112
- # @note This is a stub.
113
- # @api private
114
- def ignore_request(_team, _user)
115
- # stub
114
+ # Edit the role of a user on a team.
115
+ # @param team [String] the team name
116
+ # @param user [String] the Keybase user to edit
117
+ # @param role [String] the user's new role
118
+ # @return [OpenStruct] a struct mapping of the JSON response
119
+ # @raise [Exceptions::TeamError] if the team call fails
120
+ # @example
121
+ # Keybase::Local::Team.edit_member "foo", "bob", "reader"
122
+ def edit_member(team, user, role)
123
+ team_call "edit-member", options: {
124
+ team: team,
125
+ username: user,
126
+ role: role,
127
+ }
116
128
  end
117
129
 
118
- # Accept an email invitation to join a Keybase team.
119
- # @note This is a stub.
120
- # @api private
121
- def accept_invite(_token)
122
- # stub
130
+ # Remove a user from a team.
131
+ # @param team [String] the team name
132
+ # @param user [String] the Keybase user to remove
133
+ # @return [OpenStruct] a struct mapping of the JSON response
134
+ # @raise [Exceptions::TeamError] if the team call fails
135
+ def remove_member(team, user)
136
+ team_call "remove-member", options: {
137
+ team: team,
138
+ username: user,
139
+ }
123
140
  end
124
141
 
125
- # Leave a Keybase team.
126
- # @note This is a stub.
127
- # @api private
128
- def leave(_team, _permanent: false)
129
- # stub
142
+ # Rename a subteam.
143
+ # @param old_name [String] the subteam's current name
144
+ # @param new_name [String] the subteam's new name
145
+ # @return [OpenStruct] a struct mapping of the JSON response
146
+ # @raise [Exceptions::TeamError] if the team call fails
147
+ # @example
148
+ # Keybase::Local::Team.rename_subteam "foo.bar", "foo.baz"
149
+ def rename_subteam(old_name, new_name)
150
+ team_call "rename-subteam", options: {
151
+ team: old_name,
152
+ "new-team-name": new_name,
153
+ }
130
154
  end
131
155
 
132
- # Delete a Keybase team.
133
- # @note This is a stub.
134
- # @api private
135
- def delete(_team)
136
- # stub
156
+ # Leave a team.
157
+ # @param team [String] the team name
158
+ # @param permanent [Boolean] whether or not to leave the team permanently
159
+ # @return [OpenStruct] a struct mapping of the JSON response
160
+ # @raise [Exceptions::TeamError] if the team call fails
161
+ def leave_team(team, permanent: false)
162
+ team_call "leave-team", options: {
163
+ team: team,
164
+ permanent: permanent,
165
+ }
137
166
  end
138
167
  end
139
168
  end
data/lib/keybase/local.rb CHANGED
@@ -14,7 +14,7 @@ module Keybase
14
14
  # The namespace for `keybase-unofficial-local`.
15
15
  module Local
16
16
  # The current version of `keybase-unofficial-local`.
17
- VERSION = "0.2.1"
17
+ VERSION = "0.3.0"
18
18
 
19
19
  extend Config
20
20
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: keybase-unofficial-local
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.1
4
+ version: 0.3.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - William Woodruff
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2017-10-26 00:00:00.000000000 Z
11
+ date: 2017-11-06 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: keybase-unofficial-core