adri 0.0.1 → 0.1.0
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/CHANGELOG.md +33 -0
- data/README.md +42 -26
- data/bin/adri +40 -5
- metadata +22 -22
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 90377a82643327c5d87bcb74efc72d75f5ada30761b194a518f4755dc6c0068c
|
4
|
+
data.tar.gz: f924d6679ed5e00f4ad8b8fab22f0210602e96c34dfb793bbbd87d9d4af013a7
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: d8b94ea5b8b0dcd583283f5b41aa2e670dfd8524bee5931a34ce302be69c7cce7a4e1684cdf781427a2b2f47547ff7e0be0704aa77ab8815e5a2f36580da16a7
|
7
|
+
data.tar.gz: cbfcaf8200e317b1c1d75d48a2d740063f099dc1e016184779538165dd1fe0ba7c72ac8688da7e8c08ebad6db0a8a4ef6dad8957bdf60a70dbf0dcafd1023b32
|
data/CHANGELOG.md
ADDED
@@ -0,0 +1,33 @@
|
|
1
|
+
# Changelog
|
2
|
+
|
3
|
+
All notable changes to this project will be documented in this file.
|
4
|
+
|
5
|
+
The format is based on [Keep a Changelog][] and this project adheres to
|
6
|
+
[Semantic Versioning][].
|
7
|
+
|
8
|
+
## [Unreleased][]
|
9
|
+
|
10
|
+
## [0.1.0][] - 2020-09-06
|
11
|
+
|
12
|
+
### Added
|
13
|
+
|
14
|
+
- Make language of geocoding results configurable through the
|
15
|
+
`GEOCODER_LANGUAGE` environment variable (default is `en` for English)
|
16
|
+
|
17
|
+
### Changed
|
18
|
+
|
19
|
+
- Update README file
|
20
|
+
- Update Gem dependencies
|
21
|
+
- Improve specificity of extracted location
|
22
|
+
- Increase geocoding timeout from 3 to 10 seconds
|
23
|
+
- Handle geocoding timeout errors
|
24
|
+
|
25
|
+
## [0.0.1][] - 2018-12-06
|
26
|
+
|
27
|
+
Initial release.
|
28
|
+
|
29
|
+
[Keep a Changelog]: http://keepachangelog.com/en/1.0.0/
|
30
|
+
[Semantic Versioning]: http://semver.org/spec/v2.0.0.html
|
31
|
+
[Unreleased]: https://github.com/agorf/adri/compare/0.1.0...HEAD
|
32
|
+
[0.1.0]: https://github.com/agorf/adri/compare/0.0.1...0.1.0
|
33
|
+
[0.0.1]: https://github.com/agorf/adri/releases/tag/0.0.1
|
data/README.md
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
# adri
|
1
|
+
# adri [](http://badge.fury.io/rb/adri)
|
2
2
|
|
3
3
|
adri organizes JPEG/TIFF photographs according to their EXIF date and location
|
4
4
|
data into a custom directory structure.
|
@@ -6,23 +6,25 @@ data into a custom directory structure.
|
|
6
6
|
In other words, it turns this:
|
7
7
|
|
8
8
|
```sh
|
9
|
-
$
|
10
|
-
|
11
|
-
|
12
|
-
|
9
|
+
$ tree photos/
|
10
|
+
photos/
|
11
|
+
├── IMG100001.jpg
|
12
|
+
├── IMG100002.jpg
|
13
|
+
└── IMG100003.jpg
|
13
14
|
```
|
14
15
|
|
15
16
|
To this:
|
16
17
|
|
17
18
|
```sh
|
18
|
-
$ tree photos/
|
19
|
-
photos/
|
20
|
-
└──
|
21
|
-
└──
|
22
|
-
└──
|
23
|
-
|
24
|
-
|
25
|
-
|
19
|
+
$ tree photos/
|
20
|
+
photos/
|
21
|
+
└── 2018/
|
22
|
+
└── 10/
|
23
|
+
└── 14/
|
24
|
+
└── London
|
25
|
+
├── IMG100001.jpg
|
26
|
+
├── IMG100002.jpg
|
27
|
+
└── IMG100003.jpg
|
26
28
|
```
|
27
29
|
|
28
30
|
## Installation
|
@@ -76,26 +78,33 @@ usage: adri [options] <path>...
|
|
76
78
|
-h, --help Print help text
|
77
79
|
```
|
78
80
|
|
79
|
-
|
80
|
-
|
81
|
+
### Dry run mode (default)
|
82
|
+
|
83
|
+
By default, adri runs in dry run mode, printing `(DRY RUN)` at the end of each
|
84
|
+
line. This means it simply prints out what it would do, without actually doing
|
85
|
+
it:
|
81
86
|
|
82
87
|
```sh
|
83
88
|
$ pwd
|
84
89
|
/home/agorf/work/adri/
|
85
|
-
$
|
86
|
-
|
87
|
-
|
88
|
-
|
90
|
+
$ tree photos/
|
91
|
+
photos/
|
92
|
+
├── IMG100001.jpg
|
93
|
+
├── IMG100002.jpg
|
94
|
+
└── IMG100003.jpg
|
89
95
|
$ adri photos/*.jpg
|
90
96
|
/home/agorf/work/adri/photos/IMG100001.jpg -> /home/agorf/work/adri/photos/2018/10/14/London/IMG100001.jpg (DRY RUN)
|
91
97
|
/home/agorf/work/adri/photos/IMG100002.jpg -> /home/agorf/work/adri/photos/2018/10/14/London/IMG100002.jpg (DRY RUN)
|
92
98
|
/home/agorf/work/adri/photos/IMG100003.jpg -> /home/agorf/work/adri/photos/2018/10/14/London/IMG100003.jpg (DRY RUN)
|
93
|
-
$
|
94
|
-
|
95
|
-
|
96
|
-
|
99
|
+
$ tree photos/
|
100
|
+
photos/
|
101
|
+
├── IMG100001.jpg
|
102
|
+
├── IMG100002.jpg
|
103
|
+
└── IMG100003.jpg
|
97
104
|
```
|
98
105
|
|
106
|
+
### Run mode
|
107
|
+
|
99
108
|
To apply the changes, use the `--run` option:
|
100
109
|
|
101
110
|
```sh
|
@@ -114,6 +123,8 @@ photos/
|
|
114
123
|
└── IMG100003.jpg
|
115
124
|
```
|
116
125
|
|
126
|
+
### Path prefix
|
127
|
+
|
117
128
|
To place everything under a path other than the parent directory of each
|
118
129
|
photograph, use the `--prefix` option:
|
119
130
|
|
@@ -124,8 +135,13 @@ $ adri --prefix . photos/*.jpg
|
|
124
135
|
/home/agorf/work/adri/photos/IMG100003.jpg -> /home/agorf/work/adri/2018/10/14/London/IMG100003.jpg (DRY RUN)
|
125
136
|
```
|
126
137
|
|
127
|
-
|
128
|
-
|
138
|
+
### Path format
|
139
|
+
|
140
|
+
The default path format is `%Y/%m/%d/%{location}` which stands for
|
141
|
+
_year/month/day/location_. Everything other than `%{location}` is formatted
|
142
|
+
according to [strftime(3)][strftime].
|
143
|
+
|
144
|
+
It is possible to specify a custom path with the `--path-format` option:
|
129
145
|
|
130
146
|
```sh
|
131
147
|
$ adri --path-format '%{location}/%b %Y/%d' photos/*.jpg
|
@@ -134,7 +150,7 @@ $ adri --path-format '%{location}/%b %Y/%d' photos/*.jpg
|
|
134
150
|
/home/agorf/work/adri/photos/IMG100003.jpg -> /home/agorf/work/adri/photos/London/Oct 2018/14/IMG100003.jpg (DRY RUN)
|
135
151
|
```
|
136
152
|
|
137
|
-
|
153
|
+
### Processing many photos
|
138
154
|
|
139
155
|
It's also possible to process many photos at once by passing space-separated
|
140
156
|
file names and directories (in which case adri will [recurse][]):
|
data/bin/adri
CHANGED
@@ -16,8 +16,18 @@ module Adri
|
|
16
16
|
DEFAULT_PATH_FORMAT = '%Y/%m/%d/%{location}'.freeze
|
17
17
|
EXTENSIONS = %w[jpg jpeg JPG JPEG tif tiff TIF TIFF].freeze
|
18
18
|
GEOCODE_MAX_DELAY = 60 # Seconds
|
19
|
+
GEOCODER_TIMEOUT = 10 # Seconds
|
20
|
+
GEOCODER_LANGUAGE = ENV.fetch('GEOCODER_LANGUAGE', 'en').freeze
|
19
21
|
LOCATION_CACHE_SCALE = 2
|
20
|
-
|
22
|
+
LOCATION_ADDRESS_TYPES = %i[
|
23
|
+
locality
|
24
|
+
sublocality
|
25
|
+
administrative_area_level_5
|
26
|
+
administrative_area_level_4
|
27
|
+
administrative_area_level_3
|
28
|
+
administrative_area_level_2
|
29
|
+
].freeze
|
30
|
+
VERSION = '0.1.0'.freeze
|
21
31
|
|
22
32
|
class Photo
|
23
33
|
class << self
|
@@ -172,8 +182,9 @@ module Adri
|
|
172
182
|
|
173
183
|
begin
|
174
184
|
geocode_results = Geocoder.search(latlng)
|
175
|
-
rescue Geocoder::OverQueryLimitError
|
176
|
-
|
185
|
+
rescue Geocoder::OverQueryLimitError,
|
186
|
+
Geocoder::LookupTimeout => e
|
187
|
+
puts "Got #{e.class.name}" if verbose
|
177
188
|
|
178
189
|
if current_delay > GEOCODE_MAX_DELAY
|
179
190
|
puts "Exceeded max delay of #{GEOCODE_MAX_DELAY} seconds" if verbose
|
@@ -187,7 +198,27 @@ module Adri
|
|
187
198
|
retry
|
188
199
|
end
|
189
200
|
|
190
|
-
geocode_results.
|
201
|
+
geocode_results.each do |result|
|
202
|
+
location = location_from_geocode_result(result)
|
203
|
+
|
204
|
+
if location
|
205
|
+
return location
|
206
|
+
end
|
207
|
+
end
|
208
|
+
|
209
|
+
nil
|
210
|
+
end
|
211
|
+
|
212
|
+
private def location_from_geocode_result(result)
|
213
|
+
LOCATION_ADDRESS_TYPES.each do |type|
|
214
|
+
entity = result.address_components_of_type(type).first
|
215
|
+
|
216
|
+
if entity
|
217
|
+
return entity['long_name']
|
218
|
+
end
|
219
|
+
end
|
220
|
+
|
221
|
+
nil
|
191
222
|
end
|
192
223
|
|
193
224
|
private def location_cache_key
|
@@ -251,6 +282,8 @@ module Adri
|
|
251
282
|
end
|
252
283
|
end
|
253
284
|
|
285
|
+
# This is necessary to support both files and directories as paths. It also
|
286
|
+
# performs some basic sanity checks.
|
254
287
|
def self.expand_paths(paths, verbose)
|
255
288
|
glob_pattern = File.join('**', "*.{#{EXTENSIONS.join(',')}}")
|
256
289
|
|
@@ -298,7 +331,9 @@ end
|
|
298
331
|
Geocoder.configure(
|
299
332
|
always_raise: :all,
|
300
333
|
lookup: :google,
|
301
|
-
api_key: options[:api_key]
|
334
|
+
api_key: options[:api_key],
|
335
|
+
timeout: Adri::GEOCODER_TIMEOUT,
|
336
|
+
language: Adri::GEOCODER_LANGUAGE
|
302
337
|
)
|
303
338
|
|
304
339
|
Adri.expand_paths(args, !options[:quiet]).each do |path|
|
metadata
CHANGED
@@ -1,55 +1,55 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: adri
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0
|
4
|
+
version: 0.1.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Angelos Orfanakos
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2020-09-05 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: exif
|
15
15
|
requirement: !ruby/object:Gem::Requirement
|
16
16
|
requirements:
|
17
|
-
- - "~>"
|
18
|
-
- !ruby/object:Gem::Version
|
19
|
-
version: '2.2'
|
20
17
|
- - ">="
|
21
18
|
- !ruby/object:Gem::Version
|
22
19
|
version: 2.2.0
|
20
|
+
- - "~>"
|
21
|
+
- !ruby/object:Gem::Version
|
22
|
+
version: '2.2'
|
23
23
|
type: :runtime
|
24
24
|
prerelease: false
|
25
25
|
version_requirements: !ruby/object:Gem::Requirement
|
26
26
|
requirements:
|
27
|
-
- - "~>"
|
28
|
-
- !ruby/object:Gem::Version
|
29
|
-
version: '2.2'
|
30
27
|
- - ">="
|
31
28
|
- !ruby/object:Gem::Version
|
32
29
|
version: 2.2.0
|
30
|
+
- - "~>"
|
31
|
+
- !ruby/object:Gem::Version
|
32
|
+
version: '2.2'
|
33
33
|
- !ruby/object:Gem::Dependency
|
34
34
|
name: geocoder
|
35
35
|
requirement: !ruby/object:Gem::Requirement
|
36
36
|
requirements:
|
37
|
-
- - "~>"
|
38
|
-
- !ruby/object:Gem::Version
|
39
|
-
version: '1.5'
|
40
37
|
- - ">="
|
41
38
|
- !ruby/object:Gem::Version
|
42
39
|
version: 1.5.0
|
40
|
+
- - "~>"
|
41
|
+
- !ruby/object:Gem::Version
|
42
|
+
version: '1.5'
|
43
43
|
type: :runtime
|
44
44
|
prerelease: false
|
45
45
|
version_requirements: !ruby/object:Gem::Requirement
|
46
46
|
requirements:
|
47
|
-
- - "~>"
|
48
|
-
- !ruby/object:Gem::Version
|
49
|
-
version: '1.5'
|
50
47
|
- - ">="
|
51
48
|
- !ruby/object:Gem::Version
|
52
49
|
version: 1.5.0
|
50
|
+
- - "~>"
|
51
|
+
- !ruby/object:Gem::Version
|
52
|
+
version: '1.5'
|
53
53
|
- !ruby/object:Gem::Dependency
|
54
54
|
name: slop
|
55
55
|
requirement: !ruby/object:Gem::Requirement
|
@@ -74,22 +74,22 @@ dependencies:
|
|
74
74
|
name: dotenv
|
75
75
|
requirement: !ruby/object:Gem::Requirement
|
76
76
|
requirements:
|
77
|
-
- - "~>"
|
78
|
-
- !ruby/object:Gem::Version
|
79
|
-
version: '2.5'
|
80
77
|
- - ">="
|
81
78
|
- !ruby/object:Gem::Version
|
82
79
|
version: 2.5.0
|
80
|
+
- - "~>"
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: '2.5'
|
83
83
|
type: :development
|
84
84
|
prerelease: false
|
85
85
|
version_requirements: !ruby/object:Gem::Requirement
|
86
86
|
requirements:
|
87
|
-
- - "~>"
|
88
|
-
- !ruby/object:Gem::Version
|
89
|
-
version: '2.5'
|
90
87
|
- - ">="
|
91
88
|
- !ruby/object:Gem::Version
|
92
89
|
version: 2.5.0
|
90
|
+
- - "~>"
|
91
|
+
- !ruby/object:Gem::Version
|
92
|
+
version: '2.5'
|
93
93
|
description:
|
94
94
|
email: me@agorf.gr
|
95
95
|
executables:
|
@@ -97,6 +97,7 @@ executables:
|
|
97
97
|
extensions: []
|
98
98
|
extra_rdoc_files: []
|
99
99
|
files:
|
100
|
+
- CHANGELOG.md
|
100
101
|
- LICENSE.txt
|
101
102
|
- README.md
|
102
103
|
- bin/adri
|
@@ -119,8 +120,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
119
120
|
- !ruby/object:Gem::Version
|
120
121
|
version: '0'
|
121
122
|
requirements: []
|
122
|
-
|
123
|
-
rubygems_version: 2.7.6
|
123
|
+
rubygems_version: 3.0.3
|
124
124
|
signing_key:
|
125
125
|
specification_version: 4
|
126
126
|
summary: Organize photos by date and location in a directory structure
|