pocketbeuter 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +23 -0
- data/.rspec +2 -0
- data/Gemfile +4 -0
- data/LICENSE +20 -0
- data/LICENSE.txt +22 -0
- data/README.md +29 -0
- data/Rakefile +1 -0
- data/auth.md +6 -0
- data/bin/pockerbeuter +5 -0
- data/lib/pocketbeuter.rb +29 -0
- data/lib/pocketbeuter/cli.rb +83 -0
- data/lib/pocketbeuter/conf.rb +44 -0
- data/lib/pocketbeuter/configfile.rb +123 -0
- data/lib/pocketbeuter/get_access_token_and_username.rb +29 -0
- data/lib/pocketbeuter/pocket.rb +72 -0
- data/lib/pocketbeuter/version.rb +3 -0
- data/pocketbeuter.gemspec +29 -0
- data/spec/cli_spec.rb +67 -0
- data/spec/configfile_spec.rb +384 -0
- data/spec/fixtures/.pocketbeuterrc +9 -0
- data/spec/fixtures/bar_default_account +9 -0
- data/spec/fixtures/createapp +9 -0
- data/spec/fixtures/emptyrc +6 -0
- data/spec/fixtures/multiple_accounts +7 -0
- data/spec/fixtures/no_default_account +9 -0
- data/spec/fixtures/options +6 -0
- data/spec/fixtures/vcr_cassettes/Pocketbeuter_CLI/VCR_example_group_metadata/records_an_http_request.yml +48 -0
- data/spec/fixtures/vcr_cassettes/authorize.yml +103 -0
- data/spec/fixtures/vcr_cassettes/get_access_token_and_username.yml +53 -0
- data/spec/fixtures/vcr_cassettes/get_request_token.yml +53 -0
- data/spec/fixtures/vcr_cassettes/google_body.yml +48 -0
- data/spec/helpers.rb +3 -0
- data/spec/spec_helper.rb +26 -0
- metadata +206 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 2bf10da39b725cd65c787315d948e4d468de3378
|
4
|
+
data.tar.gz: 6f458edf09352a7e637c72fa41752b1049caf09d
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 39e65cd4dded9ef813a1cbcbac5e6c565d92b2196586905659f25a85ac86b9e01a53dc0b46ce747e1b16ad94467865f03f70cd538966bd60c0a661e32230d64b
|
7
|
+
data.tar.gz: b96e0240e62a81a1918747d1b0d1fd8ec822a6d3524dea7c0da285544f5df8d43c760fc3ed1e9019f15ddfbfb250910de59aff9a1b46ea260c7b36730fbd24cd
|
data/.gitignore
ADDED
@@ -0,0 +1,23 @@
|
|
1
|
+
*.gem
|
2
|
+
*.rbc
|
3
|
+
.bundle
|
4
|
+
.config
|
5
|
+
.yardoc
|
6
|
+
Gemfile.lock
|
7
|
+
InstalledFiles
|
8
|
+
_yardoc
|
9
|
+
coverage
|
10
|
+
doc/
|
11
|
+
lib/bundler/man
|
12
|
+
pkg
|
13
|
+
rdoc
|
14
|
+
spec/reports
|
15
|
+
test/tmp
|
16
|
+
test/version_tmp
|
17
|
+
tmp
|
18
|
+
|
19
|
+
# YARD artifacts
|
20
|
+
.yardoc
|
21
|
+
_yardoc
|
22
|
+
doc/
|
23
|
+
tags
|
data/.rspec
ADDED
data/Gemfile
ADDED
data/LICENSE
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
The MIT License (MIT)
|
2
|
+
|
3
|
+
Copyright (c) 2013 Piotr Król
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy of
|
6
|
+
this software and associated documentation files (the "Software"), to deal in
|
7
|
+
the Software without restriction, including without limitation the rights to
|
8
|
+
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
9
|
+
the Software, and to permit persons to whom the Software is furnished to do so,
|
10
|
+
subject to the following conditions:
|
11
|
+
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
13
|
+
copies or substantial portions of the Software.
|
14
|
+
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
17
|
+
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
18
|
+
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
19
|
+
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
20
|
+
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/LICENSE.txt
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
Copyright (c) 2013 Piotr Król
|
2
|
+
|
3
|
+
MIT License
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
6
|
+
a copy of this software and associated documentation files (the
|
7
|
+
"Software"), to deal in the Software without restriction, including
|
8
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
9
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
10
|
+
permit persons to whom the Software is furnished to do so, subject to
|
11
|
+
the following conditions:
|
12
|
+
|
13
|
+
The above copyright notice and this permission notice shall be
|
14
|
+
included in all copies or substantial portions of the Software.
|
15
|
+
|
16
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
17
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
18
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
19
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
20
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
21
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
22
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,29 @@
|
|
1
|
+
# Pocketbeuter
|
2
|
+
|
3
|
+
TODO: Write a gem description
|
4
|
+
|
5
|
+
## Installation
|
6
|
+
|
7
|
+
Add this line to your application's Gemfile:
|
8
|
+
|
9
|
+
gem 'pocketbeuter'
|
10
|
+
|
11
|
+
And then execute:
|
12
|
+
|
13
|
+
$ bundle
|
14
|
+
|
15
|
+
Or install it yourself as:
|
16
|
+
|
17
|
+
$ gem install pocketbeuter
|
18
|
+
|
19
|
+
## Usage
|
20
|
+
|
21
|
+
TODO: Write usage instructions here
|
22
|
+
|
23
|
+
## Contributing
|
24
|
+
|
25
|
+
1. Fork it
|
26
|
+
2. Create your feature branch (`git checkout -b my-new-feature`)
|
27
|
+
3. Commit your changes (`git commit -am 'Add some feature'`)
|
28
|
+
4. Push to the branch (`git push origin my-new-feature`)
|
29
|
+
5. Create new Pull Request
|
data/Rakefile
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
require "bundler/gem_tasks"
|
data/auth.md
ADDED
data/bin/pockerbeuter
ADDED
data/lib/pocketbeuter.rb
ADDED
@@ -0,0 +1,29 @@
|
|
1
|
+
require 'pocketbeuter/cli'
|
2
|
+
require 'thor'
|
3
|
+
|
4
|
+
module Pocketbeuter
|
5
|
+
#class Runner < Thor
|
6
|
+
# package_name "Pocketbeuter"
|
7
|
+
|
8
|
+
# desc "init", "initialize configuration and authorize Pocket app"
|
9
|
+
# def init
|
10
|
+
# Conf.init
|
11
|
+
# end
|
12
|
+
# desc "all", "get all Pocket articles"
|
13
|
+
# def all
|
14
|
+
# Conf.load_config
|
15
|
+
# unless Conf.config[:access_token]
|
16
|
+
# Conf.init
|
17
|
+
# end
|
18
|
+
# Pocket.all
|
19
|
+
# end
|
20
|
+
# desc "open ARTICLE_ID", "open Pocket article in browser"
|
21
|
+
# def open(id)
|
22
|
+
# Conf.load_config
|
23
|
+
# unless Conf.config[:access_token]
|
24
|
+
# Conf.init
|
25
|
+
# end
|
26
|
+
# Pocket.open(id)
|
27
|
+
# end
|
28
|
+
#end
|
29
|
+
end
|
@@ -0,0 +1,83 @@
|
|
1
|
+
require 'launchy'
|
2
|
+
require 'thor'
|
3
|
+
require 'pocketbeuter/get_access_token_and_username'
|
4
|
+
require 'pocketbeuter/configfile'
|
5
|
+
require 'pocketbeuter/pocket'
|
6
|
+
|
7
|
+
module Pocketbeuter
|
8
|
+
class CLI < Thor
|
9
|
+
ADD_URL = 'https://getpocket.com/v3/add'
|
10
|
+
SEND_URL = 'https://getpocket.com/v3/send'
|
11
|
+
GET_URL = 'https://getpocket.com/v3/get'
|
12
|
+
OAUTH_URL = 'https://getpocket.com/v3/oauth/request'
|
13
|
+
AUTH_URL = 'https://getpocket.com/auth/authorize'
|
14
|
+
OAUTH_AUTH_URL = 'https://getpocket.com/v3/oauth/authorize'
|
15
|
+
POCKET_DEV = 'http://getpocket.com/developer/apps/new'
|
16
|
+
check_unknown_options!
|
17
|
+
class_option 'config', :aliases => '-c', :type => :string, :default => File.join(File.expand_path('~'), Pocketbeuter::ConfigFile::CONFIG_NAME), :desc => 'Path to config file', :banner => 'CONFIG'
|
18
|
+
|
19
|
+
attr_reader :config
|
20
|
+
def initialize(*)
|
21
|
+
@config = Pocketbeuter::ConfigFile.instance
|
22
|
+
super
|
23
|
+
end
|
24
|
+
|
25
|
+
desc 'createapp', 'create Pocket API application'
|
26
|
+
def createapp
|
27
|
+
say "Good day Sir/Madam before you can use pocketbeuter, you'll first"
|
28
|
+
say "need to register your application. Please follow below steps:"
|
29
|
+
say " 1. Log in into Pocket site."
|
30
|
+
say " 2. Create an Application - complete required fields and click"
|
31
|
+
say " \"CREATE APPLICATION\" button."
|
32
|
+
say " NOTE: application must have unique name (I recommend: <login>/pocketbeuter),"
|
33
|
+
say " add application description and give Add, Modify and Retrieve permissions,"
|
34
|
+
say " select platform for your application (i.e. Desktop (other)), and accept"
|
35
|
+
say " license terms"
|
36
|
+
ask " Press any key to open Pocket Create an Application form"
|
37
|
+
say
|
38
|
+
Launchy.open(Pocketbeuter::CLI::POCKET_DEV)
|
39
|
+
account_name = ask "Enter account name [#{ENV['USER']}]:"
|
40
|
+
if account_name.empty?
|
41
|
+
@config.account_name = ENV['USER']
|
42
|
+
else
|
43
|
+
@config.account_name = account_name
|
44
|
+
end
|
45
|
+
|
46
|
+
#TODO: handle empty consumer_key
|
47
|
+
@config.consumer_key = ask 'Enter consumer key:'
|
48
|
+
#TODO: handle empty redirect_uri
|
49
|
+
redirect_uri = ask 'Enter redirect uri:'
|
50
|
+
@config.redirect_uri = redirect_uri
|
51
|
+
@config.save_config
|
52
|
+
end
|
53
|
+
|
54
|
+
desc 'authorize', 'request Pocket user authorization'
|
55
|
+
def authorize
|
56
|
+
@config.path ||= options['config'] if options['config']
|
57
|
+
if @config.empty?
|
58
|
+
createapp
|
59
|
+
end
|
60
|
+
say 'Getting request token ...'
|
61
|
+
uri = URI.parse(OAUTH_URL)
|
62
|
+
http = Net::HTTP.new(uri.host, uri.port)
|
63
|
+
request = Net::HTTP::Post.new(uri.request_uri)
|
64
|
+
request.set_form_data("consumer_key" => @config.consumer_key, "redirect_uri" => @config.redirect_uri)
|
65
|
+
http.use_ssl = true
|
66
|
+
res = http.request(request)
|
67
|
+
@config.code = URI.decode_www_form(res.body).first[1]
|
68
|
+
auth_url = AUTH_URL + "?request_token=#{@config.code}&redirect_uri=#{@config.redirect_uri}"
|
69
|
+
say "Go to: #{auth_url}"
|
70
|
+
Launchy.open(auth_url)
|
71
|
+
ask 'Press any key after authorization ...'
|
72
|
+
uri = URI.parse(OAUTH_AUTH_URL)
|
73
|
+
http = Net::HTTP.new(uri.host, uri.port)
|
74
|
+
request = Net::HTTP::Post.new(uri.request_uri)
|
75
|
+
request.set_form_data("consumer_key" => @config.consumer_key, "code" => @config.code)
|
76
|
+
http.use_ssl = true
|
77
|
+
res = http.request(request)
|
78
|
+
@config.access_token = URI.decode_www_form(res.body)[0][1]
|
79
|
+
@config.username = URI.decode_www_form(res.body)[1][1]
|
80
|
+
@config.save_config
|
81
|
+
end
|
82
|
+
end
|
83
|
+
end
|
@@ -0,0 +1,44 @@
|
|
1
|
+
require 'pocketbeuter/get_access_token_and_username'
|
2
|
+
|
3
|
+
module Conf
|
4
|
+
ADD_URL = 'https://getpocket.com/v3/add'
|
5
|
+
SEND_URL = 'https://getpocket.com/v3/send'
|
6
|
+
GET_URL = 'https://getpocket.com/v3/get'
|
7
|
+
OAUTH_URL = 'https://getpocket.com/v3/oauth/request'
|
8
|
+
AUTH_URL = 'https://getpocket.com/auth/authorize'
|
9
|
+
OAUTH_AUTH_URL = 'https://getpocket.com/v3/oauth/authorize'
|
10
|
+
|
11
|
+
def config
|
12
|
+
@config ||= {}
|
13
|
+
end
|
14
|
+
def init
|
15
|
+
load_config
|
16
|
+
GetAccessToken.get_access_token_and_username
|
17
|
+
save_config
|
18
|
+
end
|
19
|
+
def default_config
|
20
|
+
config[:dir] = File.expand_path('~/.pocketbeuter')
|
21
|
+
config[:file] = config[:dir] + '/config'
|
22
|
+
config[:cache] = config[:dir] + '/cache'
|
23
|
+
end
|
24
|
+
def load_config
|
25
|
+
default_config
|
26
|
+
if File.exists?(config[:file])
|
27
|
+
@config = YAML.load_file(config[:file])
|
28
|
+
else
|
29
|
+
File.open(config[:file], mode: 'w', perm: 0600).close
|
30
|
+
end
|
31
|
+
end
|
32
|
+
def save_config
|
33
|
+
unless File.exists?(config[:dir])
|
34
|
+
FileUtils.mkdir_p(config[:dir])
|
35
|
+
end
|
36
|
+
|
37
|
+
if File.exists?(config[:file])
|
38
|
+
File.open(config[:file], 'w') { |f| f.write(config.to_yaml) }
|
39
|
+
else
|
40
|
+
File.open(config[:file], mode: 'w', perm: 0600).close
|
41
|
+
end
|
42
|
+
end
|
43
|
+
extend Conf
|
44
|
+
end
|
@@ -0,0 +1,123 @@
|
|
1
|
+
require 'singleton'
|
2
|
+
require 'yaml'
|
3
|
+
|
4
|
+
module Pocketbeuter
|
5
|
+
class ConfigFile
|
6
|
+
CONFIG_NAME = '.pocketbeuterrc'
|
7
|
+
include Singleton
|
8
|
+
attr_reader :path
|
9
|
+
|
10
|
+
def initialize
|
11
|
+
@path = File.join(File.expand_path('~'), CONFIG_NAME)
|
12
|
+
@config = load_config
|
13
|
+
end
|
14
|
+
|
15
|
+
def [](node)
|
16
|
+
@config[node]
|
17
|
+
end
|
18
|
+
|
19
|
+
def []=(subsec, sec)
|
20
|
+
@config[subsec] ||= {}
|
21
|
+
@config[subsec].merge!(sec)
|
22
|
+
save_config
|
23
|
+
end
|
24
|
+
|
25
|
+
def account
|
26
|
+
@config['account']
|
27
|
+
end
|
28
|
+
|
29
|
+
def account=(value)
|
30
|
+
@config['account'] ||= value.keys[0]
|
31
|
+
@config['account'][value.keys[0]] = value[value.keys[0]]
|
32
|
+
end
|
33
|
+
|
34
|
+
def account_name
|
35
|
+
@config['account'].keys[0]
|
36
|
+
end
|
37
|
+
|
38
|
+
def account_name=(name)
|
39
|
+
@config['account'][name] = {}
|
40
|
+
end
|
41
|
+
|
42
|
+
def consumer_key
|
43
|
+
@config['account'][account_name]['consumer_key']
|
44
|
+
end
|
45
|
+
|
46
|
+
def consumer_key=(key)
|
47
|
+
@config['account'][account_name] ||= 'consumer_key'
|
48
|
+
@config['account'][account_name]['consumer_key'] = key
|
49
|
+
end
|
50
|
+
|
51
|
+
def redirect_uri
|
52
|
+
@config['account'][account_name]['redirect_uri']
|
53
|
+
end
|
54
|
+
|
55
|
+
def redirect_uri=(uri)
|
56
|
+
@config['account'][account_name] ||= 'redirect_uri'
|
57
|
+
@config['account'][account_name]['redirect_uri'] = uri
|
58
|
+
end
|
59
|
+
|
60
|
+
def access_token
|
61
|
+
@config['account'][account_name]['access_token']
|
62
|
+
end
|
63
|
+
|
64
|
+
def access_token=(token)
|
65
|
+
@config['account'][account_name] ||= 'access_token'
|
66
|
+
@config['account'][account_name]['access_token'] = token
|
67
|
+
end
|
68
|
+
|
69
|
+
def username
|
70
|
+
@config['account'][account_name]['username']
|
71
|
+
end
|
72
|
+
|
73
|
+
def username=(name)
|
74
|
+
@config['account'][account_name] ||= 'username'
|
75
|
+
@config['account'][account_name]['username'] = name
|
76
|
+
end
|
77
|
+
|
78
|
+
def code
|
79
|
+
@config['account'][account_name]['code']
|
80
|
+
end
|
81
|
+
|
82
|
+
def code=(token)
|
83
|
+
@config['account'][account_name] ||= 'code'
|
84
|
+
@config['account'][account_name]['code'] = token
|
85
|
+
end
|
86
|
+
|
87
|
+
def path=(path)
|
88
|
+
@path = path
|
89
|
+
@config = load_config
|
90
|
+
@path
|
91
|
+
end
|
92
|
+
|
93
|
+
def load_config
|
94
|
+
require 'yaml'
|
95
|
+
if YAML.load_file(@path)
|
96
|
+
YAML.load_file(@path)
|
97
|
+
else
|
98
|
+
default_config
|
99
|
+
end
|
100
|
+
rescue Errno::ENOENT
|
101
|
+
default_config
|
102
|
+
end
|
103
|
+
|
104
|
+
def save_config
|
105
|
+
require 'yaml'
|
106
|
+
File.open(@path, File::RDWR | File::TRUNC | File::CREAT, 0600) do |f|
|
107
|
+
f.write @config.to_yaml
|
108
|
+
end
|
109
|
+
end
|
110
|
+
|
111
|
+
def default_config
|
112
|
+
{ 'options' => {}, 'account' => {}}
|
113
|
+
end
|
114
|
+
|
115
|
+
def reset
|
116
|
+
send(:initialize)
|
117
|
+
end
|
118
|
+
|
119
|
+
def empty?
|
120
|
+
@config == default_config
|
121
|
+
end
|
122
|
+
end
|
123
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
module Conf
|
2
|
+
module GetAccessToken
|
3
|
+
def get_request_token
|
4
|
+
uri = URI.parse(OAUTH_URL)
|
5
|
+
http = Net::HTTP.new(uri.host, uri.port)
|
6
|
+
request = Net::HTTP::Post.new(uri.request_uri)
|
7
|
+
request.set_form_data("consumer_key" => Conf.config[:consumer_key], "redirect_uri" => Conf.config[:redirect_uri])
|
8
|
+
http.use_ssl = true
|
9
|
+
res = http.request(request)
|
10
|
+
Conf.config[:request_token] = URI.decode_www_form(res.body).first[1]
|
11
|
+
end
|
12
|
+
def get_access_token_and_username
|
13
|
+
get_request_token
|
14
|
+
auth_url = AUTH_URL + "?request_token=#{Conf.config[:request_token]}&redirect_uri=#{Conf.config[:redirect_uri]}"
|
15
|
+
Launchy.open(auth_url)
|
16
|
+
puts "Go to: #{auth_url}\nPress any key after authorization ..."
|
17
|
+
STDIN.getc
|
18
|
+
uri = URI.parse(OAUTH_AUTH_URL)
|
19
|
+
http = Net::HTTP.new(uri.host, uri.port)
|
20
|
+
request = Net::HTTP::Post.new(uri.request_uri)
|
21
|
+
request.set_form_data("consumer_key" => Conf.config[:consumer_key], "code" => Conf.config[:request_token])
|
22
|
+
http.use_ssl = true
|
23
|
+
res = http.request(request)
|
24
|
+
Conf.config[:access_token] = URI.decode_www_form(res.body)[0][1]
|
25
|
+
Conf.config[:username] = URI.decode_www_form(res.body)[1][1]
|
26
|
+
end
|
27
|
+
extend GetAccessToken
|
28
|
+
end
|
29
|
+
end
|