unsavory 1.0.4 → 1.1
Sign up to get free protection for your applications and to get access to all the features.
- 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
|
-
|