lard 0.0.6 → 0.0.8.alpha1
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/lard +80 -153
- data/lib/lard.rb +119 -0
- metadata +8 -20
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 9baa80628bf009726fbb8d62d56c85d86390609311fe42789c087862408631c1
|
4
|
+
data.tar.gz: f65898d7ba1842f8a3ba64ee4ebf96d018832470d7ce462a3042282d26032f90
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: ddfbb8bb02065e7380acb453598b3e7bbdfd911ad0625495565d0708e1e87b0144f7612ba01f8bb13fbe806642ae1dd882c6a76c3a6d76d4e99be88a85ecf7fd
|
7
|
+
data.tar.gz: 52ce87ac6cee76ed629681331a50a0c1a4ab854884dcab12a89638ace3f7fbe2a0d304291868592d5b86571cb82ac0691a44c0323bb238bc7b9311a66500002a
|
data/bin/lard
CHANGED
@@ -1,186 +1,70 @@
|
|
1
1
|
#!/usr/bin/env ruby
|
2
|
-
|
2
|
+
|
3
|
+
require 'date'
|
3
4
|
require 'paint'
|
4
5
|
require 'thor'
|
5
6
|
require 'yaml'
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
}
|
22
|
-
}
|
23
|
-
$folders = []
|
24
|
-
|
25
|
-
# A set of utility functions for working with the Larder HTTP API
|
26
|
-
module LardHTTP
|
27
|
-
def authorized
|
28
|
-
# Assume Auth header longer than "Token " is authorized
|
29
|
-
$options[:headers]['Authorization'].length > 6
|
30
|
-
end
|
31
|
-
|
32
|
-
def get(endpoint, params = nil)
|
33
|
-
raise "You're not logged in! Run 'lard login' first." unless authorized
|
34
|
-
|
35
|
-
query = { query: params }
|
36
|
-
opts = $options.merge query
|
37
|
-
res = self.class.get "#{prefix}#{endpoint}", opts
|
38
|
-
parse_response res
|
39
|
-
end
|
40
|
-
|
41
|
-
def post(endpoint, args = {})
|
42
|
-
raise "You're not logged in! Run 'lard login' first." unless authorized
|
43
|
-
|
44
|
-
opts = {
|
45
|
-
body: args.to_json,
|
46
|
-
headers: {
|
47
|
-
'Content-Type' => 'application/json'
|
48
|
-
}
|
49
|
-
}
|
50
|
-
opts[:headers].merge! $options[:headers]
|
51
|
-
res = self.class.post "#{prefix}#{endpoint}", opts
|
52
|
-
parse_response res
|
53
|
-
end
|
54
|
-
|
55
|
-
def parse_response(res)
|
56
|
-
JSON.parse res.body, symbolize_names: true
|
57
|
-
end
|
58
|
-
|
59
|
-
def raw_get(url)
|
60
|
-
raise "You're not logged in! Run 'lard login' first." unless authorized
|
61
|
-
|
62
|
-
JSON.parse self.class.get(url, $options).body, symbolize_names: true
|
63
|
-
end
|
64
|
-
|
65
|
-
def prefix
|
66
|
-
'https://larder.io/api/1/@me/'
|
67
|
-
end
|
68
|
-
|
69
|
-
def get_folder_by_name(name)
|
70
|
-
fetch_folders if $folders.empty?
|
71
|
-
$folders.find do |folder|
|
72
|
-
folder[:name] == name
|
7
|
+
require 'lard'
|
8
|
+
|
9
|
+
# rubocop: disable ClassLength
|
10
|
+
class LardCLI < Thor
|
11
|
+
def initialize(*args)
|
12
|
+
super
|
13
|
+
|
14
|
+
# Try to authenticate with ~/.lard.yml
|
15
|
+
begin
|
16
|
+
config = YAML.load_file File.expand_path('~/.lard.yml')
|
17
|
+
token = config['token']
|
18
|
+
rescue StandardError
|
19
|
+
# Catch any file error here because the user can run `lard login`
|
20
|
+
# to generate this config file, so we may be OK!
|
21
|
+
token = nil
|
73
22
|
end
|
74
|
-
end
|
75
23
|
|
76
|
-
|
77
|
-
print Paint[folder[:name], folder[:color]]
|
78
|
-
puts ":\t#{folder[:links]} links"
|
24
|
+
@lard = Lard.new token
|
79
25
|
end
|
80
26
|
|
81
|
-
def fetch_tags
|
82
|
-
res = get 'tags', limit: 200
|
83
|
-
tags = res[:results] || []
|
84
|
-
|
85
|
-
until res[:next].nil?
|
86
|
-
res = raw_get res[:next]
|
87
|
-
tags.push(*res[:results])
|
88
|
-
end
|
89
|
-
|
90
|
-
tags
|
91
|
-
end
|
92
|
-
|
93
|
-
def fetch_bookmarks(folder_id)
|
94
|
-
res = get "folders/#{folder_id}", limit: 200
|
95
|
-
bookmarks = res[:results] || []
|
96
|
-
|
97
|
-
until res[:next].nil?
|
98
|
-
res = raw_get res[:next]
|
99
|
-
bookmarks.push(*res[:results])
|
100
|
-
end
|
101
|
-
|
102
|
-
bookmarks
|
103
|
-
end
|
104
|
-
|
105
|
-
def fetch_folders
|
106
|
-
res = get 'folders', limit: 200
|
107
|
-
$folders = res[:results]
|
108
|
-
|
109
|
-
until res[:next].nil?
|
110
|
-
res = raw_get res[:next]
|
111
|
-
$folders.push(*res[:results])
|
112
|
-
end
|
113
|
-
|
114
|
-
# TODO: Cache these folders
|
115
|
-
end
|
116
|
-
|
117
|
-
# TODO: How can we reduce the AbcSize here further?
|
118
|
-
# rubocop:disable AbcSize
|
119
|
-
def print_bookmark(bookmark)
|
120
|
-
puts Paint[(bookmark[:title]).to_s, :bright]
|
121
|
-
puts " #{bookmark[:description]}" if bookmark[:description]
|
122
|
-
puts " #{bookmark[:url]}"
|
123
|
-
|
124
|
-
return if bookmark[:tags].nil? || bookmark[:tags].empty?
|
125
|
-
|
126
|
-
print ' '
|
127
|
-
bookmark[:tags].each do |tag|
|
128
|
-
print Paint["##{tag[:name]}", tag[:color]]
|
129
|
-
print ' '
|
130
|
-
end
|
131
|
-
puts ''
|
132
|
-
end
|
133
|
-
# rubocop:enable AbcSize
|
134
|
-
|
135
|
-
def print_tag(tag)
|
136
|
-
puts Paint["##{tag[:name]}", tag[:color]]
|
137
|
-
end
|
138
|
-
end
|
139
|
-
|
140
|
-
class Lard < Thor
|
141
|
-
include LardHTTP
|
142
|
-
include HTTParty
|
143
|
-
maintain_method_across_redirects
|
144
|
-
|
145
27
|
desc 'user', 'Prints information about the logged-in user'
|
28
|
+
|
146
29
|
def user
|
147
|
-
|
30
|
+
print_user @lard.get 'user'
|
148
31
|
end
|
149
32
|
|
150
33
|
desc 'folders', 'Lists all bookmark folders'
|
151
|
-
def folders
|
152
|
-
fetch_folders if $folders == []
|
153
34
|
|
154
|
-
|
35
|
+
def folders
|
36
|
+
@lard.folders.each do |folder|
|
155
37
|
print_folder_name folder
|
156
38
|
end
|
157
39
|
end
|
158
40
|
|
159
41
|
desc 'folder <NAME>', 'Lists all bookmarks in a given folder'
|
42
|
+
|
160
43
|
def folder(name)
|
161
|
-
folder = get_folder_by_name name
|
44
|
+
folder = @lard.get_folder_by_name name
|
162
45
|
raise "Could not find a folder named #{name}!" unless folder
|
163
46
|
|
164
47
|
print_folder_name folder
|
165
48
|
|
166
|
-
bookmarks =
|
49
|
+
bookmarks = @lard.bookmarks folder[:id]
|
167
50
|
bookmarks.each do |bookmark|
|
168
51
|
print_bookmark bookmark
|
169
52
|
end
|
170
53
|
end
|
171
54
|
|
172
55
|
desc 'tags', 'Lists all tags'
|
56
|
+
|
173
57
|
def tags
|
174
|
-
tags
|
175
|
-
tags.each do |tag|
|
58
|
+
@lard.tags.each do |tag|
|
176
59
|
print_tag tag
|
177
60
|
end
|
178
61
|
end
|
179
62
|
|
180
63
|
desc 'search <QUERY>', 'Search for bookmarks'
|
64
|
+
|
181
65
|
def search(*args)
|
182
66
|
query = args.join ' '
|
183
|
-
res = get 'search', q: query
|
67
|
+
res = @lard.get 'search', q: query
|
184
68
|
raise "No booknarks found match #{query}!" if res[:results].empty?
|
185
69
|
|
186
70
|
bookmarks = res[:results]
|
@@ -189,8 +73,9 @@ class Lard < Thor
|
|
189
73
|
end
|
190
74
|
end
|
191
75
|
|
192
|
-
# rubocop: disable MethodLength
|
193
76
|
desc 'login [TOKEN]', 'Log in to larder with your API token'
|
77
|
+
|
78
|
+
# rubocop: disable MethodLength
|
194
79
|
def login(token = nil)
|
195
80
|
unless token
|
196
81
|
puts 'Enter your Larder API token to save to ~/.lard.yml.'
|
@@ -205,29 +90,70 @@ class Lard < Thor
|
|
205
90
|
end
|
206
91
|
|
207
92
|
puts 'Saved token to ~/.lard.yml'
|
93
|
+
# rubocop: enable MethodLength
|
208
94
|
end
|
209
|
-
# rubocop: enable MethodLength
|
210
95
|
|
211
96
|
desc 'bookmark <FOLDER> <TITLE> <LINK> [tags...]',
|
212
97
|
'Creates or edits a bookmark'
|
213
98
|
option :description, aliases: :d
|
99
|
+
|
214
100
|
def bookmark(folder, title, link, *tags)
|
215
|
-
f = get_folder_by_name folder
|
101
|
+
f = @lard.get_folder_by_name folder
|
216
102
|
raise "Could not find a folder named #{folder}!" unless f
|
217
103
|
|
218
|
-
res = post 'links/add',
|
219
|
-
|
220
|
-
|
221
|
-
|
104
|
+
res = @lard.post 'links/add',
|
105
|
+
'title' => title, 'url' => link, 'tags' => tags,
|
106
|
+
'parent' => f[:id],
|
107
|
+
'description' => options[:description]
|
222
108
|
|
223
109
|
raise 'Unable to add bookmark!' if res[:error]
|
224
110
|
|
225
111
|
print_bookmark res
|
226
112
|
end
|
113
|
+
|
114
|
+
private
|
115
|
+
|
116
|
+
def print_folder_name(folder)
|
117
|
+
print Paint[folder[:name], folder[:color]]
|
118
|
+
puts ":\t#{folder[:links]} links"
|
119
|
+
end
|
120
|
+
|
121
|
+
# TODO: How can we reduce the AbcSize here further?
|
122
|
+
# rubocop: disable AbcSize
|
123
|
+
def print_bookmark(bookmark)
|
124
|
+
puts Paint[(bookmark[:title]).to_s, :bright]
|
125
|
+
puts " #{bookmark[:description]}" if bookmark[:description]
|
126
|
+
puts " #{bookmark[:url]}"
|
127
|
+
|
128
|
+
return if bookmark[:tags].nil? || bookmark[:tags].empty?
|
129
|
+
|
130
|
+
print ' '
|
131
|
+
bookmark[:tags].each do |tag|
|
132
|
+
print Paint["##{tag[:name]}", tag[:color]]
|
133
|
+
print ' '
|
134
|
+
end
|
135
|
+
puts ''
|
136
|
+
end
|
137
|
+
|
138
|
+
# rubocop: enable AbcSize
|
139
|
+
|
140
|
+
def print_tag(tag)
|
141
|
+
puts Paint["##{tag[:name]}", tag[:color]]
|
142
|
+
end
|
143
|
+
|
144
|
+
def print_user(user)
|
145
|
+
date = Date.strptime user[:date_joined]
|
146
|
+
|
147
|
+
print Paint[user[:username], :bright]
|
148
|
+
puts " (#{user[:first_name]} #{user[:last_name]})"
|
149
|
+
puts " Links: #{user[:links]}"
|
150
|
+
puts " Joined on: #{date.strftime('%F')}"
|
151
|
+
puts ' Trial membership active' if user[:is_trial]
|
152
|
+
end
|
227
153
|
end
|
228
154
|
|
229
155
|
begin
|
230
|
-
|
156
|
+
LardCLI.start(ARGV)
|
231
157
|
rescue StandardError => e
|
232
158
|
STDERR.puts "Error: #{e.message}"
|
233
159
|
|
@@ -235,3 +161,4 @@ rescue StandardError => e
|
|
235
161
|
|
236
162
|
exit 1
|
237
163
|
end
|
164
|
+
# rubocop: enable ClassLength
|
data/lib/lard.rb
ADDED
@@ -0,0 +1,119 @@
|
|
1
|
+
require 'net/http'
|
2
|
+
require 'json'
|
3
|
+
|
4
|
+
# A set of utility functions for working with the Larder HTTP API
|
5
|
+
class Lard
|
6
|
+
VERSION = '0.0.8.alpha1'.freeze
|
7
|
+
|
8
|
+
def initialize(token = nil)
|
9
|
+
@token = token
|
10
|
+
@folders = []
|
11
|
+
end
|
12
|
+
|
13
|
+
def authorized
|
14
|
+
!@token.nil?
|
15
|
+
end
|
16
|
+
|
17
|
+
def api_url_prefix
|
18
|
+
'https://larder.io/api/1/@me/'
|
19
|
+
end
|
20
|
+
|
21
|
+
def get_folder_by_name(name)
|
22
|
+
folders if @folders.empty?
|
23
|
+
@folders.find do |folder|
|
24
|
+
folder[:name] == name
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
def tags
|
29
|
+
res = get 'tags', limit: 200
|
30
|
+
tags = res[:results] || []
|
31
|
+
|
32
|
+
until res[:next].nil?
|
33
|
+
res = get res[:next]
|
34
|
+
tags.push(*res[:results])
|
35
|
+
end
|
36
|
+
|
37
|
+
tags
|
38
|
+
end
|
39
|
+
|
40
|
+
def bookmarks(folder_id)
|
41
|
+
res = get "folders/#{folder_id}", limit: 200
|
42
|
+
bookmarks = res[:results] || []
|
43
|
+
|
44
|
+
until res[:next].nil?
|
45
|
+
res = get res[:next]
|
46
|
+
bookmarks.push(*res[:results])
|
47
|
+
end
|
48
|
+
|
49
|
+
bookmarks
|
50
|
+
end
|
51
|
+
|
52
|
+
def folders
|
53
|
+
res = get 'folders', limit: 200
|
54
|
+
@folders = res[:results] || @folders
|
55
|
+
|
56
|
+
until res[:next].nil?
|
57
|
+
res = get res[:next]
|
58
|
+
@folders.push(*res[:results])
|
59
|
+
end
|
60
|
+
|
61
|
+
@folders
|
62
|
+
end
|
63
|
+
|
64
|
+
# Perform a GET request to an endpoint in the Larder API
|
65
|
+
def get(url, params = nil)
|
66
|
+
raise "You're not logged in! Run 'lard login' first." unless authorized
|
67
|
+
|
68
|
+
# Make a URI based on whether we received a full URL or just endpoint
|
69
|
+
uri = prepare_uri url
|
70
|
+
uri.query = URI.encode_www_form params unless params.nil?
|
71
|
+
|
72
|
+
res = Net::HTTP.start uri.host, uri.port, use_ssl: true do |http|
|
73
|
+
http.request prepare_request 'get', uri
|
74
|
+
end
|
75
|
+
parse_response res
|
76
|
+
end
|
77
|
+
|
78
|
+
# Perform a POST request to an endpoint in the Larder API
|
79
|
+
# Posts args as JSON in the post body, where args is a hash
|
80
|
+
def post(endpoint, args = {})
|
81
|
+
raise "You're not logged in! Run 'lard login' first." unless authorized
|
82
|
+
|
83
|
+
uri = prepare_uri endpoint
|
84
|
+
request = prepare_request 'post', uri
|
85
|
+
request.set_form_data args
|
86
|
+
res = Net::HTTP.start uri.host, uri.port, use_ssl: true do |http|
|
87
|
+
http.request request
|
88
|
+
end
|
89
|
+
parse_response res
|
90
|
+
end
|
91
|
+
|
92
|
+
private
|
93
|
+
|
94
|
+
def prepare_uri(url)
|
95
|
+
if url.start_with?('http://', 'https://')
|
96
|
+
URI url
|
97
|
+
else
|
98
|
+
URI "#{api_url_prefix}#{url}/"
|
99
|
+
end
|
100
|
+
end
|
101
|
+
|
102
|
+
def prepare_request(method, uri)
|
103
|
+
case method
|
104
|
+
when 'get'
|
105
|
+
request = Net::HTTP::Get.new uri
|
106
|
+
when 'post'
|
107
|
+
request = Net::HTTP::Post.new uri
|
108
|
+
request.add_field 'Content-Type', 'application/json'
|
109
|
+
end
|
110
|
+
request.add_field 'Authorization', "Token #{@token}"
|
111
|
+
# TODO: How can we ensure this gets updated with every new version?
|
112
|
+
request.add_field 'User-Agent', "Lard/#{VERSION}"
|
113
|
+
request
|
114
|
+
end
|
115
|
+
|
116
|
+
def parse_response(res)
|
117
|
+
JSON.parse res.body, symbolize_names: true
|
118
|
+
end
|
119
|
+
end
|
metadata
CHANGED
@@ -1,29 +1,15 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: lard
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.8.alpha1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- hawkins
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2018-10-
|
11
|
+
date: 2018-10-28 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
|
-
- !ruby/object:Gem::Dependency
|
14
|
-
name: httparty
|
15
|
-
requirement: !ruby/object:Gem::Requirement
|
16
|
-
requirements:
|
17
|
-
- - "~>"
|
18
|
-
- !ruby/object:Gem::Version
|
19
|
-
version: 0.16.2
|
20
|
-
type: :runtime
|
21
|
-
prerelease: false
|
22
|
-
version_requirements: !ruby/object:Gem::Requirement
|
23
|
-
requirements:
|
24
|
-
- - "~>"
|
25
|
-
- !ruby/object:Gem::Version
|
26
|
-
version: 0.16.2
|
27
13
|
- !ruby/object:Gem::Dependency
|
28
14
|
name: paint
|
29
15
|
requirement: !ruby/object:Gem::Requirement
|
@@ -60,8 +46,10 @@ extensions: []
|
|
60
46
|
extra_rdoc_files: []
|
61
47
|
files:
|
62
48
|
- bin/lard
|
63
|
-
|
64
|
-
|
49
|
+
- lib/lard.rb
|
50
|
+
homepage: https://github.com/hawkins/lard
|
51
|
+
licenses:
|
52
|
+
- MIT
|
65
53
|
metadata: {}
|
66
54
|
post_install_message:
|
67
55
|
rdoc_options: []
|
@@ -74,9 +62,9 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
74
62
|
version: '0'
|
75
63
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
76
64
|
requirements:
|
77
|
-
- - "
|
65
|
+
- - ">"
|
78
66
|
- !ruby/object:Gem::Version
|
79
|
-
version:
|
67
|
+
version: 1.3.1
|
80
68
|
requirements: []
|
81
69
|
rubyforge_project:
|
82
70
|
rubygems_version: 2.7.7
|