flickarr 0.1.4 → 0.1.5

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 047771d3b777387881e11c1bbe210a0ab9b6ff75a26a30fbff7e856a337fe3f7
4
- data.tar.gz: 4b13d68b86693ec63c75fca5ca4116cf166b2a6c711368245d9a75afd5051eb3
3
+ metadata.gz: 6dd50d5580622268a50b6050a2d74bb4cca723d0d0e66c6238e5d86b017b952d
4
+ data.tar.gz: a50e621f678f3f8a3479ecef24dca5d448269adb7a714a803225e5ced9d9e1aa
5
5
  SHA512:
6
- metadata.gz: bd2b1b6a9c71c7fef881a49c58866ffa35948a1e76a96614c7f662c3a9b04c183294ab605edf3bfaf218a9d4eed2d8ab703caa813e1612ae9da20ae1f6e9a311
7
- data.tar.gz: e0653f10a829f86efd3c4c7635d3054090c45339164a03d1e4dfce74a7edd47fc70bd6aab040f0f9f134e27f5a231d7fd26f81e5c8abf4812fb747e85ff1dfd9
6
+ metadata.gz: a1673833cb8cdd13da7166d9bb26576793cf19acfda964e0d94f068d565c73e66b59971921c13dcca0262999c1426860b2cc1e59ee9daa9b1bd15a0af3c34210
7
+ data.tar.gz: 0b0efcf5314432863584a1fb640b5353510df81fea003a0794c779c1e53e11dd3e5e1a79f938151319c4091a54017e156f7564b3018942fba4b5a78817bc4420
data/CHANGELOG.md CHANGED
@@ -1,5 +1,11 @@
1
1
  ## [Unreleased]
2
2
 
3
+ ## [0.1.5] - 2026-03-23
4
+
5
+ - Add `flickarr version` / `-v` / `--version` command
6
+ - Show version header in help output
7
+ - Check for gem updates: always on `version` and `status`, periodically (daily) after other commands
8
+
3
9
  ## [0.1.4] - 2026-03-22
4
10
 
5
11
  - Retry transient network errors (connection reset, timeouts, HTML-instead-of-JSON) up to 3 times with backoff
data/lib/flickarr/cli.rb CHANGED
@@ -4,7 +4,8 @@ module Flickarr
4
4
  class CLI
5
5
  DEFAULT_CONFIG_PATH = File.join(Dir.home, '.flickarr', 'config.yml').freeze
6
6
  VALID_CONFIG_KEYS = %i[access_secret access_token api_key last_page_photos last_page_posts last_page_videos
7
- library_path shared_secret total_collections total_photos total_sets total_videos
7
+ latest_version latest_version_checked_at library_path shared_secret
8
+ total_collections total_photos total_sets total_videos
8
9
  user_nsid username].freeze
9
10
 
10
11
  def initialize args, config_path: DEFAULT_CONFIG_PATH
@@ -12,7 +13,7 @@ module Flickarr
12
13
  @limit = nil
13
14
  @overwrite = false
14
15
 
15
- if args.empty? || %w[-h --help help].include?(args.first)
16
+ if args.empty? || %w[-h --help help -v --version version].include?(args.first)
16
17
  @args = args
17
18
  else
18
19
  @parser = build_parser
@@ -35,12 +36,15 @@ module Flickarr
35
36
  when 'export:photos' then run_export_posts(media: 'photos')
36
37
  when 'export:profile' then run_export_profile
37
38
  when 'export:videos' then run_export_posts(media: 'videos')
39
+ when '-v', '--version', 'version' then run_version
38
40
  when 'init' then run_init
39
41
  when 'open' then run_open
40
42
  when 'path' then run_path
41
43
  when 'status' then run_status
42
44
  else print_help
43
45
  end
46
+
47
+ check_for_update unless %w[-v --version version status -h --help help config config:set init].include?(command)
44
48
  end
45
49
 
46
50
  private
@@ -301,7 +305,13 @@ module Flickarr
301
305
  collection_count = count_subdirs(File.join(archive, 'Collections'))
302
306
  disk_usage = human_size(dir_size(archive))
303
307
 
308
+ checker = Version.new(config)
309
+ checker.check
310
+ config.save(@config_path)
311
+ version_str = checker.update_message || "#{Flickarr::VERSION} (up to date)"
312
+
304
313
  rows = [
314
+ ['Version', version_str],
305
315
  ['Archive', archive],
306
316
  ['Profile', profile_exists ? 'Downloaded' : 'Not downloaded'],
307
317
  ['Photos', format_count(photo_count, config.total_photos)],
@@ -353,6 +363,35 @@ module Flickarr
353
363
  end
354
364
  end
355
365
 
366
+ def check_for_update
367
+ return unless File.exist?(@config_path)
368
+
369
+ config = Config.load(@config_path)
370
+ checker = Version.new(config)
371
+ return unless checker.stale?
372
+
373
+ message = checker.update_message
374
+ config.save(@config_path)
375
+ return unless message
376
+
377
+ warn "\n#{message}"
378
+ rescue StandardError
379
+ nil
380
+ end
381
+
382
+ def run_version
383
+ config = Config.load(@config_path)
384
+ checker = Version.new(config)
385
+ latest = checker.check
386
+ config.save(@config_path)
387
+
388
+ if latest && Gem::Version.new(latest) > Gem::Version.new(Flickarr::VERSION)
389
+ puts "#{Flickarr::VERSION} (latest: #{latest} — run `gem update flickarr`)"
390
+ else
391
+ puts "#{Flickarr::VERSION} (up to date)"
392
+ end
393
+ end
394
+
356
395
  def count_subdirs path
357
396
  return 0 unless Dir.exist?(path)
358
397
 
@@ -707,6 +746,8 @@ module Flickarr
707
746
  end
708
747
 
709
748
  def print_help
749
+ puts "flickarr version #{Flickarr::VERSION}"
750
+ puts
710
751
  help_path = File.expand_path('../../HELP.txt', __dir__)
711
752
  puts File.read(help_path)
712
753
  puts
@@ -6,7 +6,8 @@ module Flickarr
6
6
  DEFAULT_LIBRARY_PATH = File.join(Dir.home, 'Pictures', 'Flickarr').freeze
7
7
 
8
8
  attr_accessor :access_secret, :access_token, :api_key, :last_page_photos, :last_page_posts, :last_page_videos,
9
- :library_path, :shared_secret, :total_collections, :total_photos, :total_sets, :total_videos,
9
+ :latest_version, :latest_version_checked_at, :library_path, :shared_secret,
10
+ :total_collections, :total_photos, :total_sets, :total_videos,
10
11
  :user_nsid, :username
11
12
 
12
13
  def initialize
@@ -16,6 +17,8 @@ module Flickarr
16
17
  @last_page_photos = nil
17
18
  @last_page_posts = nil
18
19
  @last_page_videos = nil
20
+ @latest_version = nil
21
+ @latest_version_checked_at = nil
19
22
  @library_path = DEFAULT_LIBRARY_PATH
20
23
  @shared_secret = ENV.fetch('FLICKARR_SHARED_SECRET', nil)
21
24
  @total_collections = nil
@@ -43,20 +46,22 @@ module Flickarr
43
46
 
44
47
  def to_h
45
48
  {
46
- access_secret: access_secret,
47
- access_token: access_token,
48
- api_key: api_key,
49
- last_page_photos: last_page_photos,
50
- last_page_posts: last_page_posts,
51
- last_page_videos: last_page_videos,
52
- library_path: library_path,
53
- shared_secret: shared_secret,
54
- total_collections: total_collections,
55
- total_photos: total_photos,
56
- total_sets: total_sets,
57
- total_videos: total_videos,
58
- user_nsid: user_nsid,
59
- username: username
49
+ access_secret: access_secret,
50
+ access_token: access_token,
51
+ api_key: api_key,
52
+ last_page_photos: last_page_photos,
53
+ last_page_posts: last_page_posts,
54
+ last_page_videos: last_page_videos,
55
+ latest_version: latest_version,
56
+ latest_version_checked_at: latest_version_checked_at,
57
+ library_path: library_path,
58
+ shared_secret: shared_secret,
59
+ total_collections: total_collections,
60
+ total_photos: total_photos,
61
+ total_sets: total_sets,
62
+ total_videos: total_videos,
63
+ user_nsid: user_nsid,
64
+ username: username
60
65
  }
61
66
  end
62
67
 
@@ -67,20 +72,22 @@ module Flickarr
67
72
  yaml = YAML.load_file(path, symbolize_names: true)
68
73
  return config unless yaml.is_a?(Hash)
69
74
 
70
- config.access_secret = yaml[:access_secret] if yaml[:access_secret]
71
- config.access_token = yaml[:access_token] if yaml[:access_token]
72
- config.api_key = yaml[:api_key] if yaml[:api_key]
73
- config.last_page_photos = yaml[:last_page_photos] if yaml[:last_page_photos]
74
- config.last_page_posts = yaml[:last_page_posts] if yaml[:last_page_posts]
75
- config.last_page_videos = yaml[:last_page_videos] if yaml[:last_page_videos]
76
- config.library_path = yaml[:library_path] if yaml[:library_path]
77
- config.shared_secret = yaml[:shared_secret] if yaml[:shared_secret]
78
- config.total_collections = yaml[:total_collections] if yaml[:total_collections]
79
- config.total_photos = yaml[:total_photos] if yaml[:total_photos]
80
- config.total_sets = yaml[:total_sets] if yaml[:total_sets]
81
- config.total_videos = yaml[:total_videos] if yaml[:total_videos]
82
- config.user_nsid = yaml[:user_nsid] if yaml[:user_nsid]
83
- config.username = yaml[:username] if yaml[:username]
75
+ config.access_secret = yaml[:access_secret] if yaml[:access_secret]
76
+ config.access_token = yaml[:access_token] if yaml[:access_token]
77
+ config.api_key = yaml[:api_key] if yaml[:api_key]
78
+ config.last_page_photos = yaml[:last_page_photos] if yaml[:last_page_photos]
79
+ config.last_page_posts = yaml[:last_page_posts] if yaml[:last_page_posts]
80
+ config.last_page_videos = yaml[:last_page_videos] if yaml[:last_page_videos]
81
+ config.latest_version = yaml[:latest_version] if yaml[:latest_version]
82
+ config.latest_version_checked_at = yaml[:latest_version_checked_at] if yaml[:latest_version_checked_at]
83
+ config.library_path = yaml[:library_path] if yaml[:library_path]
84
+ config.shared_secret = yaml[:shared_secret] if yaml[:shared_secret]
85
+ config.total_collections = yaml[:total_collections] if yaml[:total_collections]
86
+ config.total_photos = yaml[:total_photos] if yaml[:total_photos]
87
+ config.total_sets = yaml[:total_sets] if yaml[:total_sets]
88
+ config.total_videos = yaml[:total_videos] if yaml[:total_videos]
89
+ config.user_nsid = yaml[:user_nsid] if yaml[:user_nsid]
90
+ config.username = yaml[:username] if yaml[:username]
84
91
 
85
92
  config
86
93
  end
@@ -1,3 +1,67 @@
1
+ require 'json'
2
+ require 'net/http'
3
+ require 'uri'
4
+
1
5
  module Flickarr
2
- VERSION = '0.1.4'.freeze
6
+ VERSION = '0.1.5'.freeze
7
+
8
+ class Version
9
+ RUBYGEMS_URL = 'https://rubygems.org/api/v1/gems/flickarr.json'.freeze
10
+ CACHE_TTL_SECONDS = 86_400 # 1 day
11
+
12
+ def initialize config
13
+ @config = config
14
+ end
15
+
16
+ def check
17
+ fetch_latest if stale?
18
+ @config.latest_version
19
+ end
20
+
21
+ def stale?
22
+ return true if @config.latest_version_checked_at.nil?
23
+
24
+ last_check = Time.parse(@config.latest_version_checked_at.to_s)
25
+ Time.now - last_check > CACHE_TTL_SECONDS
26
+ rescue ArgumentError
27
+ true
28
+ end
29
+
30
+ def update_available?
31
+ latest = check
32
+ return false unless latest
33
+
34
+ Gem::Version.new(latest) > Gem::Version.new(Flickarr::VERSION)
35
+ rescue ArgumentError
36
+ false
37
+ end
38
+
39
+ def update_message
40
+ latest = check
41
+ return nil unless latest
42
+
43
+ if Gem::Version.new(latest) > Gem::Version.new(Flickarr::VERSION)
44
+ "Update available: #{latest} (current: #{Flickarr::VERSION}) — run `gem update flickarr`"
45
+ end
46
+ rescue ArgumentError
47
+ nil
48
+ end
49
+
50
+ private
51
+
52
+ def fetch_latest
53
+ uri = URI(RUBYGEMS_URL)
54
+ response = Net::HTTP.get_response(uri)
55
+ return unless response.is_a?(Net::HTTPSuccess)
56
+
57
+ data = JSON.parse(response.body)
58
+ version = data['version']
59
+
60
+ @config.latest_version = version
61
+ @config.latest_version_checked_at = Time.now.iso8601
62
+ version
63
+ rescue StandardError
64
+ nil
65
+ end
66
+ end
3
67
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: flickarr
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.4
4
+ version: 0.1.5
5
5
  platform: ruby
6
6
  authors:
7
7
  - Shane Becker
@@ -95,7 +95,6 @@ files:
95
95
  - LICENSE.txt
96
96
  - README.md
97
97
  - Rakefile
98
- - TODO.md
99
98
  - exe/flickarr
100
99
  - lib/flickarr.rb
101
100
  - lib/flickarr/auth.rb
data/TODO.md DELETED
@@ -1,6 +0,0 @@
1
- # Flickarr TODO
2
-
3
- ## Features
4
-
5
- - [ ] Retry on transient network failures (5xx, timeouts)
6
- - [ ] Verify downloaded file integrity (checksum or size check)