keybase-unofficial-local 0.2.1 → 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 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