xxx_rename 0.0.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 +7 -0
- data/.github/workflows/codeql-analysis.yml +42 -0
- data/.github/workflows/ruby.yml +44 -0
- data/.gitignore +12 -0
- data/.rspec +3 -0
- data/.rubocop.yml +41 -0
- data/.ruby-version +1 -0
- data/Gemfile +6 -0
- data/Gemfile.lock +174 -0
- data/README.md +319 -0
- data/Rakefile +12 -0
- data/bin/console +23 -0
- data/bin/install +22 -0
- data/bin/setup +8 -0
- data/codecov.yml +2 -0
- data/docs/DEVELOPMENT.md +42 -0
- data/exe/xxx_rename +12 -0
- data/lib/xxx_rename/actions/base_action.rb +20 -0
- data/lib/xxx_rename/actions/log_new_filename.rb +40 -0
- data/lib/xxx_rename/actions/resolver.rb +32 -0
- data/lib/xxx_rename/actions/stash_app_post_movie.rb +62 -0
- data/lib/xxx_rename/actors_helper.rb +117 -0
- data/lib/xxx_rename/cli.rb +211 -0
- data/lib/xxx_rename/client.rb +110 -0
- data/lib/xxx_rename/constants.rb +96 -0
- data/lib/xxx_rename/contract/config_contract.rb +241 -0
- data/lib/xxx_rename/contract/config_generator.rb +207 -0
- data/lib/xxx_rename/contract/file_rename_op_contract.rb +54 -0
- data/lib/xxx_rename/contract/types.rb +10 -0
- data/lib/xxx_rename/core_extensions/string.rb +39 -0
- data/lib/xxx_rename/data/base.rb +34 -0
- data/lib/xxx_rename/data/config.rb +97 -0
- data/lib/xxx_rename/data/file_rename_op.rb +42 -0
- data/lib/xxx_rename/data/file_rename_op_datastore.rb +111 -0
- data/lib/xxx_rename/data/naughty_america_database.rb +22 -0
- data/lib/xxx_rename/data/query_interface.rb +78 -0
- data/lib/xxx_rename/data/scene_data.rb +71 -0
- data/lib/xxx_rename/data/scene_datastore.rb +401 -0
- data/lib/xxx_rename/data/site_config.rb +84 -0
- data/lib/xxx_rename/data/types.rb +13 -0
- data/lib/xxx_rename/errors.rb +28 -0
- data/lib/xxx_rename/file_scanner.rb +49 -0
- data/lib/xxx_rename/file_utilities.rb +38 -0
- data/lib/xxx_rename/filename_generator.rb +173 -0
- data/lib/xxx_rename/integrations/base.rb +20 -0
- data/lib/xxx_rename/integrations/stash_app.rb +316 -0
- data/lib/xxx_rename/log.rb +26 -0
- data/lib/xxx_rename/migration_client.rb +139 -0
- data/lib/xxx_rename/processed_file.rb +203 -0
- data/lib/xxx_rename/search.rb +166 -0
- data/lib/xxx_rename/site_client_matcher.rb +299 -0
- data/lib/xxx_rename/site_clients/adult_time.rb +31 -0
- data/lib/xxx_rename/site_clients/algolia_common.rb +48 -0
- data/lib/xxx_rename/site_clients/algolia_v2.rb +181 -0
- data/lib/xxx_rename/site_clients/babes.rb +15 -0
- data/lib/xxx_rename/site_clients/base.rb +61 -0
- data/lib/xxx_rename/site_clients/blacked.rb +12 -0
- data/lib/xxx_rename/site_clients/blacked_raw.rb +12 -0
- data/lib/xxx_rename/site_clients/brazzers.rb +15 -0
- data/lib/xxx_rename/site_clients/configuration.rb +55 -0
- data/lib/xxx_rename/site_clients/digital_playground.rb +15 -0
- data/lib/xxx_rename/site_clients/elegant_angel.rb +168 -0
- data/lib/xxx_rename/site_clients/errors.rb +103 -0
- data/lib/xxx_rename/site_clients/evil_angel.rb +59 -0
- data/lib/xxx_rename/site_clients/goodporn.rb +109 -0
- data/lib/xxx_rename/site_clients/jules_jordan.rb +22 -0
- data/lib/xxx_rename/site_clients/jules_jordan_media.rb +175 -0
- data/lib/xxx_rename/site_clients/manuel_ferrara.rb +24 -0
- data/lib/xxx_rename/site_clients/mg_premium.rb +247 -0
- data/lib/xxx_rename/site_clients/mofos.rb +15 -0
- data/lib/xxx_rename/site_clients/naughty_america.rb +272 -0
- data/lib/xxx_rename/site_clients/nfbusty.rb +84 -0
- data/lib/xxx_rename/site_clients/query_generator/base.rb +89 -0
- data/lib/xxx_rename/site_clients/query_generator/evil_angel.rb +36 -0
- data/lib/xxx_rename/site_clients/query_generator/goodporn.rb +27 -0
- data/lib/xxx_rename/site_clients/query_generator/mg_premium.rb +26 -0
- data/lib/xxx_rename/site_clients/query_generator/naughty_america.rb +24 -0
- data/lib/xxx_rename/site_clients/query_generator/stash_db.rb +21 -0
- data/lib/xxx_rename/site_clients/query_generator/vixen.rb +27 -0
- data/lib/xxx_rename/site_clients/query_generator/whale.rb +39 -0
- data/lib/xxx_rename/site_clients/reality_kings.rb +14 -0
- data/lib/xxx_rename/site_clients/stash_db.rb +257 -0
- data/lib/xxx_rename/site_clients/tushy.rb +12 -0
- data/lib/xxx_rename/site_clients/tushy_raw.rb +12 -0
- data/lib/xxx_rename/site_clients/twistys.rb +15 -0
- data/lib/xxx_rename/site_clients/vixen.rb +12 -0
- data/lib/xxx_rename/site_clients/vixen_media.rb +130 -0
- data/lib/xxx_rename/site_clients/whale.rb +106 -0
- data/lib/xxx_rename/site_clients/wicked.rb +52 -0
- data/lib/xxx_rename/site_clients/x_empire.rb +51 -0
- data/lib/xxx_rename/site_clients/zero_tolerance.rb +36 -0
- data/lib/xxx_rename/utils.rb +81 -0
- data/lib/xxx_rename/version.rb +5 -0
- data/lib/xxx_rename.rb +60 -0
- data/output.png +0 -0
- data/xxx_rename.gemspec +42 -0
- metadata +411 -0
data/bin/console
ADDED
@@ -0,0 +1,23 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
require "bundler/setup"
|
5
|
+
require_relative "../lib/xxx_rename"
|
6
|
+
|
7
|
+
def reload!(print: true)
|
8
|
+
puts "Reloading ..." if print
|
9
|
+
# Main project directory.
|
10
|
+
root_dir = File.expand_path("..", __dir__)
|
11
|
+
# Directories within the project that should be reloaded.
|
12
|
+
reload_dirs = %w[lib]
|
13
|
+
# Loop through and reload every file in all relevant project directories.
|
14
|
+
reload_dirs.each do |dir|
|
15
|
+
Dir.glob("#{root_dir}/#{dir}/**/*.rb").each { |f| load(f) }
|
16
|
+
end
|
17
|
+
# Return true when complete.
|
18
|
+
true
|
19
|
+
end
|
20
|
+
|
21
|
+
require "irb"
|
22
|
+
|
23
|
+
IRB.start(__FILE__)
|
data/bin/install
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
#!/bin/bash
|
2
|
+
|
3
|
+
# check if ruby is installed and version is above 2.7
|
4
|
+
if [ -x "$(command -v ruby)" ]; then
|
5
|
+
ruby_version=$(ruby -v | awk '{print $2}')
|
6
|
+
if [ "$(echo $ruby_version | cut -d '.' -f 1)" -ge 2 ] && [ "$(echo $ruby_version | cut -d '.' -f 2)" -ge 7 ]; then
|
7
|
+
echo "Uninstalling any previously installed versions"
|
8
|
+
gem uninstall -a -x xxx_rename
|
9
|
+
echo "Building gem"
|
10
|
+
rake build
|
11
|
+
gem_path=$(ls -t ./pkg/*.gem | head -1)
|
12
|
+
echo "Installing xxx_rename"
|
13
|
+
gem install --local $gem_path
|
14
|
+
echo "Done"
|
15
|
+
else
|
16
|
+
echo "Ruby version is $ruby_version, please upgrade to 2.7 or higher"
|
17
|
+
exit 1
|
18
|
+
fi
|
19
|
+
else
|
20
|
+
echo "Ruby is not installed, please install ruby 2.7 or higher"
|
21
|
+
exit 1
|
22
|
+
fi
|
data/bin/setup
ADDED
data/codecov.yml
ADDED
data/docs/DEVELOPMENT.md
ADDED
@@ -0,0 +1,42 @@
|
|
1
|
+
# Building from Source
|
2
|
+
|
3
|
+
## Pre-requisites
|
4
|
+
|
5
|
+
The CLI is written entirely in [Ruby](https://www.ruby-lang.org/en/). The
|
6
|
+
supported version is 2.7.
|
7
|
+
|
8
|
+
You can also choose to use any env managers like
|
9
|
+
[rbenv](https://github.com/rbenv/rbenv), [rvm](https://rvm.io/),
|
10
|
+
[asdf](https://asdf-vm.com/), [chruby](https://github.com/postmodern/chruby),
|
11
|
+
etc.
|
12
|
+
|
13
|
+
To clone the repository, follow the steps below:
|
14
|
+
|
15
|
+
```bash
|
16
|
+
brew install ruby@2.7 # Install ruby (This only works for MacOS/Linux)
|
17
|
+
git clone https://github.com/c477y/xxx_rename.git
|
18
|
+
cd xxx_rename
|
19
|
+
```
|
20
|
+
|
21
|
+
## Environment
|
22
|
+
|
23
|
+
I cannot vouch for Windows, as this CLI is tested to work on Linux and MacOS,
|
24
|
+
but the test coverage should allow you to test for any errors.
|
25
|
+
|
26
|
+
## Build
|
27
|
+
|
28
|
+
Run the setup script to build the gem and its dependencies.
|
29
|
+
|
30
|
+
```bash
|
31
|
+
./bin/setup
|
32
|
+
```
|
33
|
+
|
34
|
+
To install the gem to your local machine.
|
35
|
+
|
36
|
+
```bash
|
37
|
+
./bin/install
|
38
|
+
```
|
39
|
+
|
40
|
+
## Run tests
|
41
|
+
|
42
|
+
Run the `rake` command to run the tests and lint the project using Rubocop.
|
data/exe/xxx_rename
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module XxxRename
|
4
|
+
module Actions
|
5
|
+
class BaseAction
|
6
|
+
attr_reader :config
|
7
|
+
|
8
|
+
def initialize(config)
|
9
|
+
@config = config
|
10
|
+
end
|
11
|
+
|
12
|
+
# @param [String] _dir
|
13
|
+
# @param [String] _file
|
14
|
+
# @param [XxxRename::Search::SearchResult] _search_result
|
15
|
+
def perform(_dir, _file, _search_result)
|
16
|
+
raise "Not Implemented"
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
@@ -0,0 +1,40 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "xxx_rename/actions/base_action"
|
4
|
+
|
5
|
+
module XxxRename
|
6
|
+
module Actions
|
7
|
+
class LogNewFilename < BaseAction
|
8
|
+
def perform(_dir, file, search_result)
|
9
|
+
new_filename = FilenameGenerator.generate_with_multi_formats!(
|
10
|
+
search_result.scene_data,
|
11
|
+
File.extname(file),
|
12
|
+
config.prefix_hash,
|
13
|
+
*output_patterns(search_result.site_client)
|
14
|
+
)
|
15
|
+
|
16
|
+
XxxRename.logger.info "[RENAME OPERATION]".colorize(:blue)
|
17
|
+
XxxRename.logger.info "\t#{"ORIGINAL:".colorize(:light_magenta)} #{file}"
|
18
|
+
XxxRename.logger.info "\t#{"NEW: ".colorize(:green)} #{new_filename}"
|
19
|
+
|
20
|
+
config.output_recorder.create!(search_result.scene_data, file, new_filename, Dir.pwd)
|
21
|
+
rescue FilenameGenerationError => e
|
22
|
+
XxxRename.logger.error "#{"[RENAME OPERATION ERROR]".colorize(:red)} #{e.message}"
|
23
|
+
nil
|
24
|
+
rescue Contract::FileRenameOpValidationFailure => e
|
25
|
+
XxxRename.logger.error "[RENAME OPERATION VALIDATION ERROR] #{e.message}"
|
26
|
+
nil
|
27
|
+
end
|
28
|
+
|
29
|
+
#
|
30
|
+
# Return a list of patterns that will be used to generate the new filename
|
31
|
+
# Individual site client formats take precedence over global formats
|
32
|
+
#
|
33
|
+
# @param [XxxRename::SiteClients::Base] site_client
|
34
|
+
# @return [Array[String]]
|
35
|
+
def output_patterns(site_client)
|
36
|
+
site_client.site_config.output_format.push(*config.global.output_format)
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "xxx_rename/actions/log_new_filename"
|
4
|
+
require "xxx_rename/actions/stash_app_post_movie"
|
5
|
+
|
6
|
+
module XxxRename
|
7
|
+
module Actions
|
8
|
+
class Resolver
|
9
|
+
def initialize(config)
|
10
|
+
@config = config
|
11
|
+
end
|
12
|
+
|
13
|
+
def resolve!(action)
|
14
|
+
action = action.to_sym
|
15
|
+
case action
|
16
|
+
when :sync_to_stash
|
17
|
+
actions_klass_hash.fetch(action, StashAppPostMovie.new(@config))
|
18
|
+
when :log_rename_op
|
19
|
+
actions_klass_hash.fetch(action, LogNewFilename.new(@config))
|
20
|
+
else
|
21
|
+
raise Errors::FatalError, "Unknown action #{action}"
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
private
|
26
|
+
|
27
|
+
def actions_klass_hash
|
28
|
+
@actions_klass_hash ||= {}
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
@@ -0,0 +1,62 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "xxx_rename/actions/base_action"
|
4
|
+
require "xxx_rename/integrations/stash_app"
|
5
|
+
|
6
|
+
module XxxRename
|
7
|
+
module Actions
|
8
|
+
class StashAppPostMovie < BaseAction
|
9
|
+
attr_reader :stash, :config
|
10
|
+
|
11
|
+
def initialize(config)
|
12
|
+
super(config)
|
13
|
+
@stash = Integrations::StashApp.new(config)
|
14
|
+
@stash.setup_credentials!
|
15
|
+
end
|
16
|
+
|
17
|
+
def perform(dir, file, search_result)
|
18
|
+
scene_data = search_result.scene_data
|
19
|
+
return if scene_data.movie.nil?
|
20
|
+
|
21
|
+
post_movie!(dir, file, scene_data)
|
22
|
+
rescue XxxRename::Integrations::StashAPIError => e
|
23
|
+
XxxRename.logger.error e.message
|
24
|
+
end
|
25
|
+
|
26
|
+
private
|
27
|
+
|
28
|
+
def post_movie!(_dir, file, scene_data)
|
29
|
+
scene = stash.fetch_scene(file)
|
30
|
+
if scene.nil?
|
31
|
+
XxxRename.logger.warn "[FILE MISSING ON STASH] #{file}"
|
32
|
+
return
|
33
|
+
end
|
34
|
+
|
35
|
+
if scene["movies"].find { |x| x.dig("movie", "name") == scene_data.movie.name }
|
36
|
+
XxxRename.logger.info "#{"[STASH APP MOVIE NOT UPDATED]".colorize(:yellow)} #{file}"
|
37
|
+
return
|
38
|
+
end
|
39
|
+
|
40
|
+
studio_id = studio_id(scene_data.movie.studio)
|
41
|
+
XxxRename.logger.warn "#{"[NO STUDIO ON STASH]".colorize(:light_red)} #{scene_data.movie.studio}" if studio_id.nil?
|
42
|
+
|
43
|
+
existing_movie = stash.fetch_movie(scene_data.movie.name)
|
44
|
+
if existing_movie.nil?
|
45
|
+
XxxRename.logger.info "#{"[STASH MOVIE CREATE]".colorize(:green)} #{scene_data.movie.name}"
|
46
|
+
movie = stash.create_movie(scene_data, studio_id)
|
47
|
+
stash.update_scene(scene["id"], movie["id"])
|
48
|
+
else
|
49
|
+
XxxRename.logger.info "#{"[STASH MOVIE ASSIGN]".colorize(:green)} #{scene_data.movie.name}"
|
50
|
+
stash.update_scene(scene["id"], existing_movie["id"])
|
51
|
+
end
|
52
|
+
rescue SocketError => e
|
53
|
+
XxxRename.logger.error "#{"[SOCKET ERROR #post_movie!]".colorize(:red)} #{e.message}"
|
54
|
+
nil
|
55
|
+
end
|
56
|
+
|
57
|
+
def studio_id(name)
|
58
|
+
stash.fetch_studio(name)&.[]("id")
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
@@ -0,0 +1,117 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "singleton"
|
4
|
+
|
5
|
+
module XxxRename
|
6
|
+
class ActorsHelper
|
7
|
+
include Singleton
|
8
|
+
|
9
|
+
def matcher(matcher = nil)
|
10
|
+
raise Errors::FatalError, "#{self.class.name} initialised without matcher" if @matcher.nil? && matcher.nil?
|
11
|
+
|
12
|
+
@matcher ||= matcher
|
13
|
+
end
|
14
|
+
|
15
|
+
def female_actors
|
16
|
+
@female_actors ||= {}
|
17
|
+
end
|
18
|
+
|
19
|
+
def male_actors
|
20
|
+
@male_actors ||= {}
|
21
|
+
end
|
22
|
+
|
23
|
+
def append_female(actor_hash)
|
24
|
+
female_actors[actor_hash["compressed_name"]] = actor_hash["name"] if female_actors[actor_hash["compressed_name"]].nil?
|
25
|
+
end
|
26
|
+
|
27
|
+
def append_male(actor_hash)
|
28
|
+
male_actors[actor_hash["compressed_name"]] = actor_hash["name"] if male_actors[actor_hash["compressed_name"]].nil?
|
29
|
+
end
|
30
|
+
|
31
|
+
def male?(actor)
|
32
|
+
processed!(actor)
|
33
|
+
male_actors.key? actor.normalize
|
34
|
+
rescue Errors::UnprocessedEntity
|
35
|
+
false
|
36
|
+
end
|
37
|
+
|
38
|
+
def female?(actor)
|
39
|
+
processed!(actor)
|
40
|
+
female_actors.key? actor.normalize
|
41
|
+
rescue Errors::UnprocessedEntity
|
42
|
+
false
|
43
|
+
end
|
44
|
+
|
45
|
+
def processed?(actor)
|
46
|
+
processed!(actor)
|
47
|
+
rescue Errors::UnprocessedEntity
|
48
|
+
false
|
49
|
+
end
|
50
|
+
|
51
|
+
def processed!(actor)
|
52
|
+
return true if female_actors.key?(actor.normalize) || male_actors.key?(actor.normalize)
|
53
|
+
|
54
|
+
raise Errors::UnprocessedEntity, actor
|
55
|
+
end
|
56
|
+
|
57
|
+
def auto_fetch!(actor)
|
58
|
+
details = fetch_actor_details.details(actor)
|
59
|
+
|
60
|
+
raise Errors::UnprocessedEntity, actor if details.nil?
|
61
|
+
|
62
|
+
details["gender"].downcase == "female" ? append_female(details) : append_male(details)
|
63
|
+
nil
|
64
|
+
end
|
65
|
+
|
66
|
+
def auto_fetch(actor)
|
67
|
+
auto_fetch!(actor)
|
68
|
+
rescue Errors::UnprocessedEntity => e
|
69
|
+
XxxRename.logger.warn "Unable to fetch details for #{e.message}"
|
70
|
+
nil
|
71
|
+
end
|
72
|
+
|
73
|
+
private
|
74
|
+
|
75
|
+
def fetch_actor_details
|
76
|
+
@fetch_actor_details ||= FetchActorDetails.new(matcher)
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
class FetchActorDetails
|
81
|
+
# @param [XxxRename::SiteClientMatcher] matcher
|
82
|
+
def initialize(matcher)
|
83
|
+
@matcher = matcher
|
84
|
+
end
|
85
|
+
|
86
|
+
# @param [String] actor Search string for actor
|
87
|
+
# @return [nil, Hash] Hash of details or nil if not found
|
88
|
+
def details(actor)
|
89
|
+
clients.each do |client|
|
90
|
+
details = client.actor_details(actor)
|
91
|
+
next if details.nil?
|
92
|
+
|
93
|
+
XxxRename.logger.debug "#{client.class.name.split("::").last} matched actor #{actor} as #{details["gender"]}"
|
94
|
+
details.tap do |h|
|
95
|
+
h["compressed_name"] = details["name"].normalize
|
96
|
+
h["gender"] = details["gender"].normalize
|
97
|
+
end
|
98
|
+
return details
|
99
|
+
end
|
100
|
+
nil
|
101
|
+
end
|
102
|
+
|
103
|
+
private
|
104
|
+
|
105
|
+
attr_reader :matcher
|
106
|
+
|
107
|
+
def clients
|
108
|
+
[
|
109
|
+
matcher.initialise_site_client(:stash),
|
110
|
+
matcher.initialise_site_client(:brazzers),
|
111
|
+
matcher.initialise_site_client(:wicked),
|
112
|
+
matcher.initialise_site_client(:reality_kings),
|
113
|
+
matcher.initialise_site_client(:evil_angel)
|
114
|
+
].compact
|
115
|
+
end
|
116
|
+
end
|
117
|
+
end
|
@@ -0,0 +1,211 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "thor"
|
4
|
+
|
5
|
+
module XxxRename
|
6
|
+
class Cli < Thor
|
7
|
+
SUPPORTED_SITES = %w[
|
8
|
+
adult_time
|
9
|
+
babes
|
10
|
+
blacked
|
11
|
+
blacked_raw
|
12
|
+
brazzers
|
13
|
+
digital_playground
|
14
|
+
elegant_angel
|
15
|
+
evil_angel
|
16
|
+
goodporn
|
17
|
+
jules_jordan
|
18
|
+
manuel_ferrara
|
19
|
+
mofos
|
20
|
+
naughty_america
|
21
|
+
nf_busty
|
22
|
+
reality_kings
|
23
|
+
stash
|
24
|
+
tushy
|
25
|
+
tushy_raw
|
26
|
+
twistys
|
27
|
+
vixen
|
28
|
+
whale_media
|
29
|
+
wicked
|
30
|
+
x_empire
|
31
|
+
zero_tolerance
|
32
|
+
].freeze
|
33
|
+
|
34
|
+
def self.exit_on_failure?
|
35
|
+
true
|
36
|
+
end
|
37
|
+
|
38
|
+
desc "version", "Print the CLI version"
|
39
|
+
def version
|
40
|
+
require_relative "version"
|
41
|
+
puts "v#{XxxRename::VERSION}"
|
42
|
+
end
|
43
|
+
map %w[--version -v] => :version
|
44
|
+
|
45
|
+
long_desc <<-LONGDESC
|
46
|
+
Scan files and generate metadata
|
47
|
+
|
48
|
+
For first time users, run the command without any flags to generate a config
|
49
|
+
file in $HOME/.config/xxx_rename
|
50
|
+
|
51
|
+
$ xxx_rename generate
|
52
|
+
|
53
|
+
The cli will look for a config file in these three places in order:
|
54
|
+
|
55
|
+
* --config (This takes precedence over everything)
|
56
|
+
|
57
|
+
* $HOME/.config/xxx_rename
|
58
|
+
|
59
|
+
* HOME/xxx_rename
|
60
|
+
|
61
|
+
Examples
|
62
|
+
|
63
|
+
# Scan all files in a given directory and its sub-directories
|
64
|
+
|
65
|
+
$ xxx_rename generate . --nested
|
66
|
+
|
67
|
+
# Force the cli to use `brazzers` to match a file
|
68
|
+
|
69
|
+
$ xxx_rename generate . --verbose --override_site=brazzers
|
70
|
+
|
71
|
+
# Generate a migrations file to rename the matched files
|
72
|
+
|
73
|
+
$ xxx_rename generate . --actions=log_rename_op
|
74
|
+
LONGDESC
|
75
|
+
desc "generate FILE|FOLDER", "Rename a file or all file(s) inside a given directory"
|
76
|
+
option :config, alias: :c, type: :string, required: false, desc: "path to config file"
|
77
|
+
option :verbose, alias: :v, type: :boolean, default: false, desc: "enable verbose logging"
|
78
|
+
option :override_site, alias: :s, type: :string, required: false, desc: "force use an override site",
|
79
|
+
enum: SUPPORTED_SITES
|
80
|
+
option :nested, type: :boolean, default: false, desc: "recursively search for all files in the given directory"
|
81
|
+
option :force_refresh_datastore, type: :boolean, default: false, desc: "force site client to fetch all scenes, if implemented"
|
82
|
+
option :actions, alias: :a, type: :string, default: [], desc: "action to perform on a successful match",
|
83
|
+
enum: %w[sync_to_stash log_rename_op], repeatable: true
|
84
|
+
option :force_refresh, type: :boolean, default: false, desc: "force match scenes from original sites"
|
85
|
+
option :checkpoint, type: :string, required: false, desc: "skip all iterations until check-pointed file is matched"
|
86
|
+
def generate(object)
|
87
|
+
XxxRename.logger(verbose: options["verbose"])
|
88
|
+
config = Contract::ConfigGenerator.new(options).generate!
|
89
|
+
client = Client.new(config,
|
90
|
+
verbose: options["verbose"],
|
91
|
+
override_site: options["override_site"]&.to_sym,
|
92
|
+
nested: options["nested"],
|
93
|
+
checkpoint: options["checkpoint"])
|
94
|
+
client.generate(object)
|
95
|
+
rescue Interrupt
|
96
|
+
print "Exiting...\n".colorize(:green)
|
97
|
+
rescue Errors::FatalError => e
|
98
|
+
XxxRename.logger.fatal "#{e.class} #{e.message}".colorize(:red)
|
99
|
+
e.backtrace&.each { |x| XxxRename.logger.debug x }
|
100
|
+
exit 1
|
101
|
+
rescue StandardError => e
|
102
|
+
XxxRename.logger.fatal "CLI ran into an unexpected error. Report this on https://github.com/c477y/xxx_rename/issues/new"
|
103
|
+
XxxRename.logger.fatal "#{e.class} #{e.message}".colorize(:red)
|
104
|
+
e.backtrace&.each { |x| XxxRename.logger.fatal x }
|
105
|
+
exit 1
|
106
|
+
end
|
107
|
+
|
108
|
+
long_desc <<~LONGDESC
|
109
|
+
WARNING: This is a destructive operation as it will rename files
|
110
|
+
Run this on a small subset to be sure and run it at your own risk
|
111
|
+
|
112
|
+
Rename files based on operations listed in a migration file.
|
113
|
+
|
114
|
+
All rename files are located in your `generated_files_dir` directory.
|
115
|
+
Migration files are plain YAML files of format 'output_YYYYMMDDHHMM.yml'
|
116
|
+
|
117
|
+
Pass a migration file using option --version YYYYMMDDHHMM
|
118
|
+
If you want to apply a migration file that you have just created,
|
119
|
+
pass the --version as "latest". Or don't pass the --version
|
120
|
+
flag and the CLI will use the latest version by default.
|
121
|
+
|
122
|
+
Migration files have the following format:
|
123
|
+
|
124
|
+
---
|
125
|
+
# 0 means the migration is not applied
|
126
|
+
|
127
|
+
# 1 means the migration is applied
|
128
|
+
|
129
|
+
# This flag prevents applying a migration that has already been applied
|
130
|
+
|
131
|
+
___MIGRATION_STATUS___: 0
|
132
|
+
|
133
|
+
# All operations are stored as an array
|
134
|
+
|
135
|
+
___RENAME_ACTIONS___:
|
136
|
+
|
137
|
+
# DO NOT MANIPULATE AN ARRAY ITEM! Doing so can result in unexpected
|
138
|
+
|
139
|
+
# behaviour. You can remove an operation from the list entirely, but
|
140
|
+
|
141
|
+
# the recommended way is to discard this migration completely,
|
142
|
+
|
143
|
+
# modify the `output_format` for your file in the config and run the
|
144
|
+
|
145
|
+
# generate command again
|
146
|
+
|
147
|
+
- !ruby/object:XxxRename::Data::FileRenameOp
|
148
|
+
|
149
|
+
attributes:
|
150
|
+
|
151
|
+
:key: eab204175567d39202c1df5895e443be # DO NOT MODIFY THIS#{" "}
|
152
|
+
|
153
|
+
:directory: "/ABSOLUTE/DIRECTORY/TOFILE"
|
154
|
+
|
155
|
+
:source_filename: ORIGINAL_FILENAME.MP4
|
156
|
+
|
157
|
+
:output_filename: NEW_FILENAME.MP4
|
158
|
+
|
159
|
+
:mtime: 2000-01-01 00:00:00.000000000 +00:00
|
160
|
+
|
161
|
+
Example Usage:
|
162
|
+
|
163
|
+
$ xxx_rename migrate --version=202301131252
|
164
|
+
|
165
|
+
$ xxx_rename migrate
|
166
|
+
LONGDESC
|
167
|
+
desc "migrate --version=VERSION", "Apply a rename migration file"
|
168
|
+
option :config, alias: :c, type: :string, required: false, desc: "path to config file"
|
169
|
+
option :version, type: :string, default: "latest", desc: "Name of migration file to apply"
|
170
|
+
def migrate
|
171
|
+
config = Contract::ConfigGenerator.new(options.slice("config")).generate!
|
172
|
+
MigrationClient.new(config, options["version"]).apply
|
173
|
+
rescue Interrupt
|
174
|
+
print "Exiting...\n".colorize(:green)
|
175
|
+
rescue Errors::FatalError => e
|
176
|
+
XxxRename.logger.fatal "#{e.class} #{e.message}".colorize(:red)
|
177
|
+
e.backtrace&.each { |x| XxxRename.logger.debug x }
|
178
|
+
exit 1
|
179
|
+
rescue StandardError => e
|
180
|
+
XxxRename.logger.fatal "CLI ran into an unexpected error. Report this on https://github.com/c477y/xxx_rename/issues/new"
|
181
|
+
XxxRename.logger.fatal "#{e.class} #{e.message}".colorize(:red)
|
182
|
+
e.backtrace&.each { |x| XxxRename.logger.fatal x }
|
183
|
+
exit 1
|
184
|
+
end
|
185
|
+
|
186
|
+
long_desc <<-LONGDESC
|
187
|
+
Reverse the actions taken by the `migrate` command
|
188
|
+
|
189
|
+
Read the help command for more information
|
190
|
+
$ xxx_rename help migrate
|
191
|
+
LONGDESC
|
192
|
+
desc "rollback --version=VERSION", "Rollback a migration"
|
193
|
+
option :config, alias: :c, type: :string, required: false, desc: "path to config file"
|
194
|
+
option :version, type: :string, default: "latest", desc: "Name of migration file to apply"
|
195
|
+
def rollback
|
196
|
+
config = Contract::ConfigGenerator.new(options.slice("config")).generate!
|
197
|
+
MigrationClient.new(config, options["version"]).rollback
|
198
|
+
rescue Interrupt
|
199
|
+
print "Exiting...\n".colorize(:green)
|
200
|
+
rescue Errors::FatalError => e
|
201
|
+
XxxRename.logger.fatal "#{e.class} #{e.message}".colorize(:red)
|
202
|
+
e.backtrace&.each { |x| XxxRename.logger.debug x }
|
203
|
+
exit 1
|
204
|
+
rescue StandardError => e
|
205
|
+
XxxRename.logger.fatal "CLI ran into an unexpected error. Report this on https://github.com/c477y/xxx_rename/issues/new"
|
206
|
+
XxxRename.logger.fatal "#{e.class} #{e.message}".colorize(:red)
|
207
|
+
e.backtrace&.each { |x| XxxRename.logger.fatal x }
|
208
|
+
exit 1
|
209
|
+
end
|
210
|
+
end
|
211
|
+
end
|