commit 2d4073aca19fc6cd6ceb8b7aa56b694053ec4c43
parent 0eca255124c8aff7e35e881612399fd228fab546
Author: Alex Balgavy <a.balgavy@gmail.com>
Date: Thu, 22 Oct 2020 00:23:03 +0200
pocket: lots of refactoring, new commands
Also added the ability to list items, and show only videos.
Former-commit-id: 83bb1b21b80ac23aaaa0e7ceefc284141ed15534
Diffstat:
M | scripts/pocket | | | 140 | ++++++++++++++++++++++++++++++++++++++++++++++++++++++++----------------------- |
1 file changed, 99 insertions(+), 41 deletions(-)
diff --git a/scripts/pocket b/scripts/pocket
@@ -11,64 +11,96 @@ def die(message)
exit 1
end
-# The Pocket API interface class
-class Pocket
- ACCESS_TOKEN_FILE = "#{ENV['HOME']}/.cache/pocket-access-token"
-
+# The Pocket API authentication system
+class PocketAuth
def initialize
- # byebug
die 'Please set the POCKET_CONSUMER_KEY environment variable.' unless ENV['POCKET_CONSUMER_KEY']
- @base = 'https://getpocket.com/v3'
@consumer_key = ENV['POCKET_CONSUMER_KEY']
+ @base = 'https://getpocket.com/v3'
@headers = { 'Content-Type' => 'application/json; charset=UTF8', 'X-Accept' => 'application/json' }
+ @access_token = read_access_token
+ end
+
+ def credentials
+ { consumer_key: @consumer_key, access_token: @access_token }
+ end
+
+ private
+
+ ACCESS_TOKEN_FILE = "#{ENV['HOME']}/.cache/pocket-access-token"
+
+ def read_access_token
if File.exist? ACCESS_TOKEN_FILE
@access_token = File.read ACCESS_TOKEN_FILE
else
- query = { consumer_key: @consumer_key, redirect_uri: 'https://google.com' }
- response = Net::HTTP.post URI("#{@base}/oauth/request"), query.to_json, @headers
- if response.code == '200'
- @pocket_code = JSON.parse(response.body)['code']
- else
- die 'Could not retrieve code.'
- end
- puts "Please open: https://getpocket.com/auth/authorize?request_token=#{@pocket_code}&redirect_uri=#{query['redirect_uri']}"
- # TODO: receive this with a temp server
- print 'Press enter when done.'
- STDIN.getc
- query = { consumer_key: @consumer_key, code: @pocket_code }
- response = Net::HTTP.post URI("#{@base}/oauth/authorize"), query.to_json, @headers
- if response.code == '200'
- body = JSON.parse(response.body)
- puts "Authenticated for username #{body['username']}"
- @access_token = body['access_token']
- else
- die "Could not authenticate, code: #{response.code}"
- end
+ @access_token = request_access_token
puts "Writing access token to #{ACCESS_TOKEN_FILE}, remove this file to revoke authorization."
File.write ACCESS_TOKEN_FILE, @access_token
end
- @security_params = { consumer_key: @consumer_key, access_token: @access_token }
end
- def save(url)
- response = Net::HTTP.post URI("#{@base}/add"), { url: url }.merge(@security_params).to_json, @headers
+ def generate_auth_uri
+ query = { consumer_key: @consumer_key, redirect_uri: 'https://google.com' }
+ response = Net::HTTP.post URI("#{@base}/oauth/request"), query.to_json, @headers
if response.code == '200'
- puts 'URL added'
+ @pocket_code = JSON.parse(response.body)['code']
else
- die "Could not add, code #{response.code}"
+ die 'Could not retrieve code.'
end
+ "https://getpocket.com/auth/authorize?request_token=#{@pocket_code}&redirect_uri=#{query['redirect_uri']}"
+ end
+
+ def authenticate
+ query = { consumer_key: @consumer_key, code: @pocket_code }
+ response = Net::HTTP.post URI("#{@base}/oauth/authorize"), query.to_json, @headers
+ return nil unless response.code == '200'
+
+ JSON.parse(response.body)
end
- def audio
- query = { domain: '*.bandcamp.com', count: 5 }
- response = Net::HTTP.post URI("#{@base}/get"), query.merge(@security_params).to_json, @headers
+ def request_access_token
+ puts "Please open: #{generate_auth_uri}"
+ # TODO: start a temp server, react when receive request (URL passed in redirect_uri above)
+ print 'Press enter when done.'
+ STDIN.getc
+ auth_response = authenticate
+ die 'Could not authenticate' unless auth_response
+ puts "Authenticated for username #{body['username']}"
+ @access_token = body['access_token']
+ end
+end
+
+# The Pocket API interface class
+class Pocket
+ def initialize
+ @base = 'https://getpocket.com/v3'
+ @headers = { 'Content-Type' => 'application/json; charset=UTF8', 'X-Accept' => 'application/json' }
+ @security_params = PocketAuth.new.credentials
+ end
+
+ def api_call(url_string, params)
+ response = Net::HTTP.post URI(url_string), params.merge(@security_params).to_json, @headers
if response.code == '200'
- items = JSON.parse(response.body)['list']
- items.each do |_id, data|
- puts "#{data['resolved_title']}\t#{data['resolved_url']}"
- end
+ yield response if block_given?
else
- die "Could not get, code #{response.code}"
+ die "Could not add, code #{response.code}"
+ end
+ end
+
+ def save(url)
+ api_call("#{@base}/add", url: url)
+ end
+
+ def retrieve_list(query)
+ # merge overwrites sort key if needed
+ api_call("#{@base}/get", { sort: 'newest' }.merge(query)) { |resp| parse_article_list(resp.body).join("\n") }
+ end
+
+ private
+
+ def parse_article_list(response_body)
+ JSON.parse(response_body)['list'].inject([]) do |lines, (_id, data)|
+ lines << "#{data['resolved_title']}\t#{data['resolved_url']}"
end
end
end
@@ -79,19 +111,45 @@ def usage
Commands:
save [URL]\tsave URL to Pocket
- audio\tget saved audio to Pocket
+ audio [n]\tget n recently saved audio URLs (if n is negative, get oldest)
+ video [n]\tget n recently saved video URLs (if n is negative, get oldest)
+ list [n]\tlist n recently saved URLs (if n is negative, get oldest)
HEREDOC
end
+
if ARGV.empty?
usage
exit 1
end
+
+def count_sort_from_second_arg
+ begin
+ count = Integer(ARGV[1])
+ rescue ArgumentError
+ die 'Second argument must be an integer.'
+ end
+ return { count: count.abs, sort: 'oldest' } if count.negative?
+
+ { count: count.abs }
+end
+
pocket = Pocket.new
if ARGV[0] == 'save'
die 'save: URL required' unless ARGV[1]
pocket.save ARGV[1]
elsif ARGV[0] == 'audio'
- pocket.audio
+ params = { domain: '*.bandcamp.com', contentType: 'article' }.merge(count_sort_from_second_arg)
+ puts pocket.retrieve_list(params)
+elsif ARGV[0] == 'video'
+ params = { has_video: 2, contentType: 'article' }.merge(count_sort_from_second_arg)
+ puts pocket.retrieve_list(params)
+elsif ARGV[0] == 'list'
+ if ARGV[1]
+ params = { contentType: 'article' }.merge(count_sort_from_second_arg)
+ puts pocket.retrieve_list(params)
+ else
+ puts pocket.retrieve_list(contentType: 'article')
+ end
else
die "Command '#{ARGV[0]}' not recognised."
end