dribbble-bucket-sync 0.0.1 → 0.0.2
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.
- data/README.md +6 -2
- data/dribbble_bucket_sync.gemspec +1 -1
- data/lib/dribbble_bucket_sync/folder.rb +58 -14
- data/lib/dribbble_bucket_sync/version.rb +1 -1
- data/lib/dribbble_bucket_sync.rb +8 -2
- metadata +5 -5
data/README.md
CHANGED
@@ -33,8 +33,12 @@ Output should be like this:
|
|
33
33
|
$ dribbble_bucket_sync ryantownsend ~/dribbble
|
34
34
|
Starting synchronisation...
|
35
35
|
ryantownsend has 29 buckets.
|
36
|
-
Timelines has
|
37
|
-
|
36
|
+
Timelines has 20 shots.
|
37
|
+
Connecting to dribbble.s3.amazonaws.com:80
|
38
|
+
Downloading 20 files:
|
39
|
+
....................
|
40
|
+
Infographics has 12 shots.
|
41
|
+
[...]
|
38
42
|
Synchronisation complete.
|
39
43
|
|
40
44
|
The syntax to run within your own app is fairly straight-forward:
|
@@ -15,7 +15,7 @@ Gem::Specification.new do |s|
|
|
15
15
|
s.require_paths = ["lib"]
|
16
16
|
s.version = DribbbleBucketSync::VERSION
|
17
17
|
|
18
|
-
s.add_dependency "dribbble-bucket-api"
|
18
|
+
s.add_dependency "dribbble-bucket-api", "~> 0.0.6"
|
19
19
|
s.add_development_dependency "rspec"
|
20
20
|
s.add_development_dependency "simplecov"
|
21
21
|
end
|
@@ -1,6 +1,7 @@
|
|
1
1
|
require "fileutils"
|
2
2
|
require "uri"
|
3
3
|
require "net/http"
|
4
|
+
require "timeout"
|
4
5
|
|
5
6
|
class DribbbleBucketSync
|
6
7
|
class Folder
|
@@ -17,23 +18,35 @@ class DribbbleBucketSync
|
|
17
18
|
end
|
18
19
|
|
19
20
|
def add_shot(shot)
|
20
|
-
|
21
|
-
|
22
|
-
filename = "#{shot.id}#{File.extname(url)}"
|
23
|
-
@shots << filename
|
21
|
+
# calculate the filename
|
22
|
+
filename = "#{shot.id}.#{shot.ext}"
|
24
23
|
# calculate the path
|
25
24
|
path = File.join(@path, filename)
|
26
|
-
#
|
27
|
-
|
28
|
-
|
25
|
+
# add the shot to the storage
|
26
|
+
@shots << { filename: filename, destination: path, url: shot.image_url }
|
27
|
+
end
|
28
|
+
|
29
|
+
def sync
|
30
|
+
download_new_shots
|
31
|
+
remove_old_shots
|
32
|
+
end
|
33
|
+
|
34
|
+
# downloads any shots missing from the folder
|
35
|
+
def download_new_shots
|
36
|
+
# select all the shots that don't exist
|
37
|
+
new_shots = @shots.select do |s|
|
38
|
+
!File.exist?(s[:destination])
|
29
39
|
end
|
40
|
+
# download them all
|
41
|
+
download_files(new_shots)
|
30
42
|
end
|
31
43
|
|
44
|
+
# deletes any shots in the folder that no longer exist in the bucket
|
32
45
|
def remove_old_shots
|
33
46
|
# loop through all shots in the folder
|
34
47
|
current_shot_files.each do |file|
|
35
48
|
# delete file if the shot isn't in the array
|
36
|
-
unless @shots.include?(File.basename(file))
|
49
|
+
unless @shots.map { |s| s[:filename] }.include?(File.basename(file))
|
37
50
|
FileUtils.rm(file)
|
38
51
|
end
|
39
52
|
end
|
@@ -45,12 +58,39 @@ class DribbbleBucketSync
|
|
45
58
|
end
|
46
59
|
|
47
60
|
private
|
48
|
-
#
|
49
|
-
def
|
50
|
-
#
|
51
|
-
|
52
|
-
|
53
|
-
|
61
|
+
# download URLs to a local path
|
62
|
+
def download_files(files)
|
63
|
+
# map the urls into groups by hostname
|
64
|
+
groups = files.inject({}) do |result,file|
|
65
|
+
uri = URI.parse(file[:url])
|
66
|
+
result["#{uri.host}:#{uri.port}"] ||= []
|
67
|
+
result["#{uri.host}:#{uri.port}"] << {
|
68
|
+
destination: file[:destination],
|
69
|
+
uri: uri
|
70
|
+
}
|
71
|
+
result
|
72
|
+
end
|
73
|
+
# loop through each group
|
74
|
+
groups.each do |key, files|
|
75
|
+
host = files.first[:uri].host
|
76
|
+
port = files.first[:uri].port
|
77
|
+
puts "Connecting to #{host}:#{port}"
|
78
|
+
# connect to the site
|
79
|
+
Net::HTTP.start(host, files.first[:uri].port) do |http|
|
80
|
+
puts "Downloading #{files.size} files:"
|
81
|
+
# loop through each uri
|
82
|
+
files.each do |file|
|
83
|
+
# download the file
|
84
|
+
download_file(http, file[:uri], file[:destination])
|
85
|
+
print "."
|
86
|
+
end
|
87
|
+
puts ""
|
88
|
+
end
|
89
|
+
end
|
90
|
+
end
|
91
|
+
|
92
|
+
def download_file(http, uri, destination)
|
93
|
+
Timeout::timeout(30) do
|
54
94
|
# download the file
|
55
95
|
resp = http.get(uri.request_uri)
|
56
96
|
# open the local file
|
@@ -59,6 +99,10 @@ class DribbbleBucketSync
|
|
59
99
|
file.write(resp.body)
|
60
100
|
end
|
61
101
|
end
|
102
|
+
rescue Timeout::Error => e
|
103
|
+
puts "Request timed out: #{uri.request_uri}, moving on to next... (#{e.class.name})"
|
104
|
+
rescue EOFError => e
|
105
|
+
puts "Request failed: #{uri.request_uri}, moving on to next... (#{e.class.name})"
|
62
106
|
end
|
63
107
|
|
64
108
|
# ensure the folder exists
|
data/lib/dribbble_bucket_sync.rb
CHANGED
@@ -31,6 +31,9 @@ class DribbbleBucketSync
|
|
31
31
|
buckets.each do |bucket|
|
32
32
|
sync_bucket(bucket, directory)
|
33
33
|
end
|
34
|
+
# being nice to Dribbble site
|
35
|
+
# sleep for 1 - 3 seconds every 5 buckets
|
36
|
+
sleep(3) + 1
|
34
37
|
end
|
35
38
|
end
|
36
39
|
|
@@ -54,9 +57,12 @@ class DribbbleBucketSync
|
|
54
57
|
shots.each do |shot|
|
55
58
|
folder.add_shot(shot)
|
56
59
|
end
|
60
|
+
# being nice to Dribbble site
|
61
|
+
# sleep for 0 - 2 seconds every 15 shots
|
62
|
+
sleep(3)
|
57
63
|
end
|
58
|
-
#
|
59
|
-
folder.
|
64
|
+
# process downloads / deletions
|
65
|
+
folder.sync
|
60
66
|
end
|
61
67
|
|
62
68
|
def connection
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: dribbble-bucket-sync
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.2
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -16,17 +16,17 @@ dependencies:
|
|
16
16
|
requirement: !ruby/object:Gem::Requirement
|
17
17
|
none: false
|
18
18
|
requirements:
|
19
|
-
- -
|
19
|
+
- - ~>
|
20
20
|
- !ruby/object:Gem::Version
|
21
|
-
version:
|
21
|
+
version: 0.0.6
|
22
22
|
type: :runtime
|
23
23
|
prerelease: false
|
24
24
|
version_requirements: !ruby/object:Gem::Requirement
|
25
25
|
none: false
|
26
26
|
requirements:
|
27
|
-
- -
|
27
|
+
- - ~>
|
28
28
|
- !ruby/object:Gem::Version
|
29
|
-
version:
|
29
|
+
version: 0.0.6
|
30
30
|
- !ruby/object:Gem::Dependency
|
31
31
|
name: rspec
|
32
32
|
requirement: !ruby/object:Gem::Requirement
|