unsavory 1.0.4 → 1.1
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/LICENSE +1 -1
- data/bin/unsavory +38 -58
- data/lib/pinboard_client.rb +22 -0
- data/lib/utilities.rb +23 -0
- metadata +5 -5
- data/lib/pinboard.rb +0 -31
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: bae6a0b70cb546a3f264489c758033807f3e4e78
|
4
|
+
data.tar.gz: c005ba81e51809b6b14f541fdea099a8c4e37cfa
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 4262f12d74d044d5a696f97cffda5fcc05e86139946da98bb4d24f7e8d93ee3ddd267b0415f8cae12cdacce7fefab7eb4a2ff14030a18fbbf626c90f5e65d4b1
|
7
|
+
data.tar.gz: 63599f53345ade64bf63b73fc76a0ad0fcbb58fd1434728783e38398e36403074840938cf43ef7055ac1862ff47b86597061c6f42deda15e950ca7ae9a4aa504
|
data/LICENSE
CHANGED
data/bin/unsavory
CHANGED
@@ -1,88 +1,68 @@
|
|
1
1
|
#! /usr/bin/env ruby
|
2
|
-
# Copyright (c) 2009 Michael Kohl
|
2
|
+
# Copyright (c) 2009-2013 Michael Kohl
|
3
3
|
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
highline = false
|
11
|
-
end
|
12
|
-
|
13
|
-
CFG_FILE = File.join(ENV['HOME'], ".#{File.basename($0)}")
|
14
|
-
|
15
|
-
if File.exists?(CFG_FILE)
|
16
|
-
puts "Using config file '#{CFG_FILE}'"
|
17
|
-
user, pass = File.new(CFG_FILE).gets.chomp.split(':', 2)
|
18
|
-
elsif highline
|
19
|
-
hl = HighLine.new
|
20
|
-
user = hl.ask('Enter Pinboard username: ')
|
21
|
-
pass = hl.ask('Enter Pinboard password: ') { |q| q.echo = "*" }
|
22
|
-
else
|
23
|
-
puts %{
|
24
|
-
Can't find config file '#{CFG_FILE}' and you
|
25
|
-
don't seem to have HighLine installed. Aborting!
|
26
|
-
}
|
27
|
-
exit 1
|
28
|
-
end
|
4
|
+
require "rubygems" # for the 1.8 users
|
5
|
+
require "logger"
|
6
|
+
require "net/http"
|
7
|
+
require "progressbar"
|
8
|
+
require_relative "../lib/pinboard_client.rb"
|
9
|
+
require_relative "../lib/utilities.rb"
|
29
10
|
|
11
|
+
user, pass = Utilities.get_credentials
|
12
|
+
pinboard_client = PinboardClient.new(user, pass)
|
30
13
|
logger = Logger.new('unsavory.log')
|
31
|
-
logger.info "Unsavory started: #{Time.now.strftime('%Y-%m-%d %H:%M')}"
|
32
|
-
pinboard = Pinboard.new(user, pass)
|
33
|
-
moved = 0
|
34
14
|
|
35
|
-
|
36
|
-
urls = pinboard.get_all_urls
|
37
|
-
rescue => e
|
38
|
-
puts %{
|
39
|
-
I couldn't get your posts from Pinboard!
|
15
|
+
logger.info "Unsavory started: #{Time.now.strftime('%Y-%m-%d %H:%M')}"
|
40
16
|
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
17
|
+
puts "Retrieving URLs"
|
18
|
+
urls = pinboard_client.get_urls
|
19
|
+
unless urls
|
20
|
+
puts "\nCould not retrieve URLs!\nPlease check your login credentials."
|
21
|
+
exit 1
|
45
22
|
end
|
46
|
-
|
47
23
|
puts "\n#{user} has #{urls.length} bookmarks."
|
48
24
|
|
49
25
|
pbar = ProgressBar.new("URLs", urls.size)
|
26
|
+
moved = 0
|
50
27
|
|
51
28
|
urls.each_with_index do |url, idx|
|
52
29
|
pbar.inc
|
53
|
-
|
30
|
+
delete = false
|
31
|
+
|
32
|
+
# Hackety fix for issue #1
|
54
33
|
uri = URI.parse(url) rescue next
|
55
|
-
response = nil
|
56
34
|
|
57
35
|
begin
|
58
36
|
Net::HTTP.start(uri.host, uri.port) do |http|
|
59
|
-
response = http.head(uri.path.
|
37
|
+
response = http.head(uri.path.empty? ? '/' : uri.path)
|
38
|
+
|
39
|
+
# handle redirects
|
40
|
+
if response.is_a?(Net::HTTPRedirection)
|
41
|
+
moved += 1
|
42
|
+
logger.info "#{url} redirects to #{response['location']}"
|
43
|
+
next
|
44
|
+
end
|
45
|
+
|
46
|
+
if response.code == '404'
|
47
|
+
delete = true
|
48
|
+
elsif response.code != '200'
|
49
|
+
logger.info "#{response.code}: #{url}"
|
50
|
+
end
|
60
51
|
end
|
61
52
|
rescue Errno::ENOENT
|
62
|
-
|
63
|
-
logger.info "Deleted #{url}"
|
64
|
-
next
|
53
|
+
delete = true
|
65
54
|
# In 1.8, TimeoutError does not inherit from StandardError
|
66
55
|
rescue StandardError, Timeout::Error => e
|
67
56
|
logger.error "#{e.message} - #{url}"
|
68
|
-
next
|
69
57
|
end
|
70
58
|
|
71
|
-
|
72
|
-
|
73
|
-
new_uri = URI.parse(response['location'])
|
74
|
-
moved += 1
|
75
|
-
logger.info "#{url} redirects to #{new_uri}"
|
76
|
-
next
|
77
|
-
end
|
78
|
-
|
79
|
-
if response.code == '404'
|
80
|
-
pinboard.delete(url)
|
59
|
+
if delete
|
60
|
+
pinboard_client.delete(url)
|
81
61
|
logger.info "Deleted #{url}"
|
82
|
-
elsif response.code != '200'
|
83
|
-
logger.info "#{response.code}: #{url}"
|
84
62
|
end
|
85
63
|
end
|
64
|
+
|
86
65
|
pbar.finish
|
87
66
|
logger.close
|
67
|
+
|
88
68
|
puts "\n#{moved} URIs are redirecting to new locations, you might want to fix them." if moved > 0
|
@@ -0,0 +1,22 @@
|
|
1
|
+
require 'httparty'
|
2
|
+
|
3
|
+
class PinboardClient
|
4
|
+
include HTTParty
|
5
|
+
base_uri 'https://api.pinboard.in/v1/'
|
6
|
+
headers "User-Agent" => "Unsavory"
|
7
|
+
|
8
|
+
def initialize(user, password)
|
9
|
+
@options = {:basic_auth => {:username => user, :password => password}}
|
10
|
+
end
|
11
|
+
|
12
|
+
def get_urls
|
13
|
+
response = self.class.get('/posts/all', @options)
|
14
|
+
if response.success?
|
15
|
+
response['posts']['post'].map { |post| post['href'] }
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
def delete(url)
|
20
|
+
self.class.get("/posts/delete?url=#{url}", @options)
|
21
|
+
end
|
22
|
+
end
|
data/lib/utilities.rb
ADDED
@@ -0,0 +1,23 @@
|
|
1
|
+
module Utilities
|
2
|
+
class << self
|
3
|
+
CFG_FILE = File.join(ENV['HOME'], ".#{File.basename($0)}")
|
4
|
+
|
5
|
+
def get_credentials
|
6
|
+
if File.exists?(CFG_FILE)
|
7
|
+
puts "Using config file '#{CFG_FILE}'"
|
8
|
+
user, pass = File.new(CFG_FILE).gets.chomp.split(':', 2)
|
9
|
+
else
|
10
|
+
begin
|
11
|
+
require 'highline'
|
12
|
+
hl = HighLine.new
|
13
|
+
user = hl.ask('Enter Pinboard username: ')
|
14
|
+
pass = hl.ask('Enter Pinboard password: ') { |q| q.echo = "*" }
|
15
|
+
rescue LoadError
|
16
|
+
puts "Can't find config file '#{CFG_FILE}' and you don't seem to have HighLine installed. Aborting!"
|
17
|
+
exit 1
|
18
|
+
end
|
19
|
+
end
|
20
|
+
[user, pass]
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: unsavory
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.
|
4
|
+
version: '1.1'
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Michael Kohl
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2013-10-
|
11
|
+
date: 2013-10-11 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: httparty
|
@@ -47,7 +47,8 @@ executables:
|
|
47
47
|
extensions: []
|
48
48
|
extra_rdoc_files: []
|
49
49
|
files:
|
50
|
-
- lib/
|
50
|
+
- lib/pinboard_client.rb
|
51
|
+
- lib/utilities.rb
|
51
52
|
- bin/unsavory
|
52
53
|
- ./LICENSE
|
53
54
|
- ./README.rdoc
|
@@ -71,9 +72,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
71
72
|
version: '0'
|
72
73
|
requirements: []
|
73
74
|
rubyforge_project:
|
74
|
-
rubygems_version: 2.0.
|
75
|
+
rubygems_version: 2.0.3
|
75
76
|
signing_key:
|
76
77
|
specification_version: 4
|
77
78
|
summary: Removes outdated links from your Pinboard bookmarks
|
78
79
|
test_files: []
|
79
|
-
has_rdoc: false
|
data/lib/pinboard.rb
DELETED
@@ -1,31 +0,0 @@
|
|
1
|
-
require 'httparty'
|
2
|
-
|
3
|
-
class Pinboard
|
4
|
-
include HTTParty
|
5
|
-
base_uri 'https://api.pinboard.in/v1/'
|
6
|
-
headers "User-Agent" => "Unsavory"
|
7
|
-
|
8
|
-
API_METHODS = {
|
9
|
-
:all => '/posts/all',
|
10
|
-
:delete => '/posts/delete?url='}
|
11
|
-
|
12
|
-
def initialize(user, password)
|
13
|
-
@options = {:basic_auth => {:username => user, :password => password}}
|
14
|
-
end
|
15
|
-
|
16
|
-
# get_all returns a nested hash, but we want an array of URLs
|
17
|
-
def get_all_urls
|
18
|
-
get_all['posts']['post'].inject([]) { |urls, post| urls << post['href'] }
|
19
|
-
end
|
20
|
-
|
21
|
-
def delete(url)
|
22
|
-
self.class.get(API_METHODS[:delete]+url, @options)
|
23
|
-
end
|
24
|
-
|
25
|
-
private
|
26
|
-
def get_all
|
27
|
-
self.class.get(API_METHODS[:all], @options)
|
28
|
-
end
|
29
|
-
end
|
30
|
-
|
31
|
-
|