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.
Files changed (97) hide show
  1. checksums.yaml +7 -0
  2. data/.github/workflows/codeql-analysis.yml +42 -0
  3. data/.github/workflows/ruby.yml +44 -0
  4. data/.gitignore +12 -0
  5. data/.rspec +3 -0
  6. data/.rubocop.yml +41 -0
  7. data/.ruby-version +1 -0
  8. data/Gemfile +6 -0
  9. data/Gemfile.lock +174 -0
  10. data/README.md +319 -0
  11. data/Rakefile +12 -0
  12. data/bin/console +23 -0
  13. data/bin/install +22 -0
  14. data/bin/setup +8 -0
  15. data/codecov.yml +2 -0
  16. data/docs/DEVELOPMENT.md +42 -0
  17. data/exe/xxx_rename +12 -0
  18. data/lib/xxx_rename/actions/base_action.rb +20 -0
  19. data/lib/xxx_rename/actions/log_new_filename.rb +40 -0
  20. data/lib/xxx_rename/actions/resolver.rb +32 -0
  21. data/lib/xxx_rename/actions/stash_app_post_movie.rb +62 -0
  22. data/lib/xxx_rename/actors_helper.rb +117 -0
  23. data/lib/xxx_rename/cli.rb +211 -0
  24. data/lib/xxx_rename/client.rb +110 -0
  25. data/lib/xxx_rename/constants.rb +96 -0
  26. data/lib/xxx_rename/contract/config_contract.rb +241 -0
  27. data/lib/xxx_rename/contract/config_generator.rb +207 -0
  28. data/lib/xxx_rename/contract/file_rename_op_contract.rb +54 -0
  29. data/lib/xxx_rename/contract/types.rb +10 -0
  30. data/lib/xxx_rename/core_extensions/string.rb +39 -0
  31. data/lib/xxx_rename/data/base.rb +34 -0
  32. data/lib/xxx_rename/data/config.rb +97 -0
  33. data/lib/xxx_rename/data/file_rename_op.rb +42 -0
  34. data/lib/xxx_rename/data/file_rename_op_datastore.rb +111 -0
  35. data/lib/xxx_rename/data/naughty_america_database.rb +22 -0
  36. data/lib/xxx_rename/data/query_interface.rb +78 -0
  37. data/lib/xxx_rename/data/scene_data.rb +71 -0
  38. data/lib/xxx_rename/data/scene_datastore.rb +401 -0
  39. data/lib/xxx_rename/data/site_config.rb +84 -0
  40. data/lib/xxx_rename/data/types.rb +13 -0
  41. data/lib/xxx_rename/errors.rb +28 -0
  42. data/lib/xxx_rename/file_scanner.rb +49 -0
  43. data/lib/xxx_rename/file_utilities.rb +38 -0
  44. data/lib/xxx_rename/filename_generator.rb +173 -0
  45. data/lib/xxx_rename/integrations/base.rb +20 -0
  46. data/lib/xxx_rename/integrations/stash_app.rb +316 -0
  47. data/lib/xxx_rename/log.rb +26 -0
  48. data/lib/xxx_rename/migration_client.rb +139 -0
  49. data/lib/xxx_rename/processed_file.rb +203 -0
  50. data/lib/xxx_rename/search.rb +166 -0
  51. data/lib/xxx_rename/site_client_matcher.rb +299 -0
  52. data/lib/xxx_rename/site_clients/adult_time.rb +31 -0
  53. data/lib/xxx_rename/site_clients/algolia_common.rb +48 -0
  54. data/lib/xxx_rename/site_clients/algolia_v2.rb +181 -0
  55. data/lib/xxx_rename/site_clients/babes.rb +15 -0
  56. data/lib/xxx_rename/site_clients/base.rb +61 -0
  57. data/lib/xxx_rename/site_clients/blacked.rb +12 -0
  58. data/lib/xxx_rename/site_clients/blacked_raw.rb +12 -0
  59. data/lib/xxx_rename/site_clients/brazzers.rb +15 -0
  60. data/lib/xxx_rename/site_clients/configuration.rb +55 -0
  61. data/lib/xxx_rename/site_clients/digital_playground.rb +15 -0
  62. data/lib/xxx_rename/site_clients/elegant_angel.rb +168 -0
  63. data/lib/xxx_rename/site_clients/errors.rb +103 -0
  64. data/lib/xxx_rename/site_clients/evil_angel.rb +59 -0
  65. data/lib/xxx_rename/site_clients/goodporn.rb +109 -0
  66. data/lib/xxx_rename/site_clients/jules_jordan.rb +22 -0
  67. data/lib/xxx_rename/site_clients/jules_jordan_media.rb +175 -0
  68. data/lib/xxx_rename/site_clients/manuel_ferrara.rb +24 -0
  69. data/lib/xxx_rename/site_clients/mg_premium.rb +247 -0
  70. data/lib/xxx_rename/site_clients/mofos.rb +15 -0
  71. data/lib/xxx_rename/site_clients/naughty_america.rb +272 -0
  72. data/lib/xxx_rename/site_clients/nfbusty.rb +84 -0
  73. data/lib/xxx_rename/site_clients/query_generator/base.rb +89 -0
  74. data/lib/xxx_rename/site_clients/query_generator/evil_angel.rb +36 -0
  75. data/lib/xxx_rename/site_clients/query_generator/goodporn.rb +27 -0
  76. data/lib/xxx_rename/site_clients/query_generator/mg_premium.rb +26 -0
  77. data/lib/xxx_rename/site_clients/query_generator/naughty_america.rb +24 -0
  78. data/lib/xxx_rename/site_clients/query_generator/stash_db.rb +21 -0
  79. data/lib/xxx_rename/site_clients/query_generator/vixen.rb +27 -0
  80. data/lib/xxx_rename/site_clients/query_generator/whale.rb +39 -0
  81. data/lib/xxx_rename/site_clients/reality_kings.rb +14 -0
  82. data/lib/xxx_rename/site_clients/stash_db.rb +257 -0
  83. data/lib/xxx_rename/site_clients/tushy.rb +12 -0
  84. data/lib/xxx_rename/site_clients/tushy_raw.rb +12 -0
  85. data/lib/xxx_rename/site_clients/twistys.rb +15 -0
  86. data/lib/xxx_rename/site_clients/vixen.rb +12 -0
  87. data/lib/xxx_rename/site_clients/vixen_media.rb +130 -0
  88. data/lib/xxx_rename/site_clients/whale.rb +106 -0
  89. data/lib/xxx_rename/site_clients/wicked.rb +52 -0
  90. data/lib/xxx_rename/site_clients/x_empire.rb +51 -0
  91. data/lib/xxx_rename/site_clients/zero_tolerance.rb +36 -0
  92. data/lib/xxx_rename/utils.rb +81 -0
  93. data/lib/xxx_rename/version.rb +5 -0
  94. data/lib/xxx_rename.rb +60 -0
  95. data/output.png +0 -0
  96. data/xxx_rename.gemspec +42 -0
  97. metadata +411 -0
@@ -0,0 +1,272 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "nokogiri"
4
+ require "pathname"
5
+ require "xxx_rename/site_clients/query_generator/naughty_america"
6
+
7
+ module XxxRename
8
+ module SiteClients
9
+ class NaughtyAmerica < Base
10
+ include HTTParty
11
+ base_uri "https://www.naughtyamerica.com"
12
+
13
+ site_client_name :naughty_america
14
+ ACTOR_ENDPOINT = "/pornstar"
15
+
16
+ def search(filename)
17
+ resp = SiteClients::QueryGenerator::NaughtyAmerica.generate(filename, source_format)
18
+ case resp
19
+ when String
20
+ search_unprocessed(filename, resp)
21
+ when SiteClients::QueryGenerator::Base::SearchParameters
22
+ search_processed(resp)
23
+ else
24
+ raise Errors::NoMatchError.new(Errors::NoMatchError::ERR_NO_METADATA, filename)
25
+ end
26
+ end
27
+
28
+ def search_processed(scene_data)
29
+ female_actor = scene_data.female_actors.first || scene_data.actors.first
30
+ scenes = fetch_scenes(female_actor)
31
+ scenes.select do |x|
32
+ x.match_processed?(scene_data)
33
+ end.first&.to_struct || raise(Errors::NoMatchError.new(Errors::NoMatchError::ERR_NO_METADATA, scene_data.to_s))
34
+ end
35
+
36
+ def search_unprocessed(filename, compressed_scene_title)
37
+ actor = parent_dir(filename)
38
+ scenes = fetch_scenes(actor)
39
+ match = scenes.select { |x| x.match_unprocessed?(compressed_scene_title) }.first&.to_struct
40
+
41
+ return match if match
42
+
43
+ XxxRename.logger.error "#{actor} - #{compressed_scene_title}"
44
+ raise Errors::NoMatchError.new(Errors::NoMatchError::ERR_NO_RESULT, compressed_scene_title)
45
+ end
46
+
47
+ # @param [String] actor
48
+ # @return [Array[NaughtyAmericaScene]]
49
+ def fetch_scenes(actor, force = false)
50
+ if force
51
+ XxxRename.logger.debug "Force fetch scene #{actor}"
52
+ fetch_scenes_from_api(actor)
53
+ else
54
+ fetch_scenes_from_cache(actor) || fetch_scenes_from_api(actor)
55
+ end
56
+ end
57
+
58
+ def fetch_scenes_from_cache(actor)
59
+ scene_store.transaction(true) do
60
+ scene_store[normalized_actor(actor)]
61
+ end
62
+ end
63
+
64
+ def fetch_scenes_from_api(actor)
65
+ scenes = process_actor(actor)
66
+ return if scenes.nil?
67
+
68
+ cache_scenes(normalized_actor(actor), scenes)
69
+ end
70
+
71
+ def cache_scenes(actor, scenes)
72
+ scene_store.transaction do
73
+ scene_store[actor] = [] unless scene_store[actor]
74
+ existing_actors = scene_store[actor]
75
+ diff_scenes = scenes - existing_actors
76
+ diff_scenes.each do |scene|
77
+ XxxRename.logger.debug "Adding #{scene.title} to cache"
78
+ scene_store[actor] << scene
79
+ end
80
+ end
81
+ end
82
+
83
+ def normalized_actor(actor)
84
+ actor.normalize
85
+ end
86
+
87
+ def process_actor(actor)
88
+ actor_all_scenes = []
89
+ (1..5).to_a.each { |page| actor_all_scenes.concat(fetch_actors_page(actor, page: page)) }
90
+ rescue Errors::NoMatchError => e
91
+ case e.code
92
+ when NoMatchError::ERR_NO_RESULT
93
+ XxxRename.logger.info "Naughty America does not have an actor named #{actor}"
94
+ when NoMatchError::ERR_NW_REDIRECT
95
+ XxxRename.logger.debug "Page #{e.data} exceeded maximum available pages"
96
+ end
97
+ actor_all_scenes
98
+ end
99
+
100
+ def fetch_actors_page(actor, page:)
101
+ doc = fetch_actor_page!(actor, page: page)
102
+ scenes = doc.css(".contain-block").css(".alt-bg").css(".scene-item")
103
+ scenes.map do |scene|
104
+ next if vr?(scene)
105
+
106
+ NaughtyAmericaScene.new(
107
+ collection: collection(scene),
108
+ actors: actors(scene),
109
+ date_released: date_released(scene),
110
+ remastered: remastered?(scene),
111
+ title: title(scene),
112
+ id: id(scene)
113
+ )
114
+ end.compact
115
+ end
116
+
117
+ def title(scene)
118
+ scene_path(scene).split("-")[..-2].join(" ").humanize
119
+ end
120
+
121
+ def id(scene)
122
+ id = scene_path(scene).split("-").last
123
+ Integer(id) ? id.to_s : ""
124
+ end
125
+
126
+ def scene_path(scene)
127
+ URI(scene.css("a").first["href"]).path.split("/").last
128
+ end
129
+
130
+ def remastered?(scene)
131
+ scene.css("a").any? { |x| x.text.strip.upcase == "REMASTERED HD" }
132
+ end
133
+
134
+ def vr?(scene)
135
+ scene.css("a").any? { |x| x.text.strip == "VR" }
136
+ end
137
+
138
+ def collection(scene)
139
+ scene.css(".site-title").text.strip
140
+ end
141
+
142
+ def actors(scene)
143
+ scene.css(".contain-actors a").map { |x| x.text.strip }
144
+ end
145
+
146
+ def date_released(scene)
147
+ Time.strptime(scene.css(".entry-date").text.strip, "%b %d, %Y")
148
+ end
149
+
150
+ def parent_dir(filename)
151
+ path = Pathname.new(File.join(Dir.pwd, filename))
152
+ path.dirname.each_filename.to_a.last
153
+ end
154
+
155
+ def fetch_actor_page!(actor, page:)
156
+ actor_name_normalised = actor.downcase.gsub("\s", "-")
157
+ endpoint = File.join(ACTOR_ENDPOINT, actor_name_normalised)
158
+ query = { related_page: page }
159
+ XxxRename.logger.debug "API path: #{endpoint}, query: #{query}"
160
+ resp = self.class.get(endpoint, query: query, follow_redirects: false)
161
+ case resp.code
162
+ when 200 then Nokogiri::HTML(resp.body)
163
+ when 301 then raise Errors::NoMatchError.new(Errors::NoMatchError::ERR_NW_REDIRECT, page)
164
+ when 404 then raise Errors::NoMatchError.new(Errors::NoMatchError::ERR_NO_RESULT, actor_name_normalised)
165
+ when 503 then raise SiteClients::Errors::SiteClientUnavailableError, self.class.base_uri
166
+ else raise "Something went wrong #{resp.code}"
167
+ end
168
+ end
169
+
170
+ def scene_store
171
+ @scene_store ||= Data::NaughtyAmericaDatabase.new(site_config.database).store
172
+ end
173
+
174
+ class NaughtyAmericaScene
175
+ attr_reader :actors, :collection, :date_released, :remastered, :title, :id
176
+
177
+ COLLECTION_ABBRS = {
178
+ "americandaydreams" => "add",
179
+ "diaryofananny" => "don",
180
+ "housewife1on1" => "h1on1",
181
+ "ihaveawife" => "ihw",
182
+ "fasttimes" => "ftna",
183
+ "lasluts" => "las",
184
+ "latinadultery" => "lad",
185
+ "momsmoney" => "momo",
186
+ "mrscreampie" => "namcp",
187
+ "mywifeismypornstar" => "mwmp",
188
+ "naughtyamerica" => "nam",
189
+ "naughtyathletics" => "nath",
190
+ "naughtybookworms" => "nbw",
191
+ "naughtyweddings" => "naw",
192
+ "neighboraffair" => "naf",
193
+ "seducedbycougar" => "sbc",
194
+ "watchyourmom" => "natngf",
195
+ "dirtywivesclub" => "nadwc"
196
+ }.freeze
197
+
198
+ ACTOR_ABBRS = {
199
+ "mrpete" => %w[mrpete pete],
200
+ "ryandriller" => %w[ryandriller ryan driller]
201
+ }.freeze
202
+
203
+ def initialize(collection:, actors:, date_released:, remastered:, title:, id:)
204
+ @collection = collection
205
+ @actors = actors
206
+ @date_released = date_released
207
+ @title = title
208
+ @id = id
209
+ @remastered = remastered
210
+ end
211
+
212
+ def condensed_collection
213
+ col = COLLECTION_ABBRS[collection.normalize]
214
+ return col if col
215
+
216
+ collection.split(" ").map { |x| x[0, 1] }.join("").downcase
217
+ end
218
+
219
+ def female_actors
220
+ actors.select { |x| ActorsHelper.instance.female? x }
221
+ end
222
+
223
+ def male_actors
224
+ actors.select { |x| ActorsHelper.instance.male? x }
225
+ end
226
+
227
+ def condensed_actor(actor)
228
+ act = ACTOR_ABBRS[actor.normalize]
229
+ return act if act
230
+
231
+ [actor.downcase.normalize, actor.split(" ").first&.downcase]
232
+ end
233
+
234
+ def remastered?
235
+ remastered
236
+ end
237
+
238
+ def match_unprocessed?(condensed_title)
239
+ dup = condensed_title.dup
240
+ dup.slice!(condensed_collection)
241
+ dup.slice!("rem") if remastered?
242
+ actors.each { |x| condensed_actor(x).each { |y| dup.slice!(y) } }
243
+ dup == ""
244
+ end
245
+
246
+ def match_processed?(scene_data)
247
+ arity = []
248
+ arity << (scene_data.actors - actors == [])
249
+ arity << (scene_data.collection.normalize == collection.normalize)
250
+ arity << (scene_data.title.normalize == title.normalize) unless scene_data.title.nil? || scene_data.title.empty?
251
+ arity << (scene_data.id == id) unless scene_data.id.nil? || scene_data.id.empty?
252
+ arity.none?(false)
253
+ end
254
+
255
+ def to_struct
256
+ actors.each { |x| ActorsHelper.instance.auto_fetch x }
257
+
258
+ Data::SceneData.new(
259
+ female_actors: female_actors,
260
+ male_actors: male_actors,
261
+ actors: actors,
262
+ title: title,
263
+ collection: collection,
264
+ collection_tag: "NA",
265
+ id: id,
266
+ date_released: date_released
267
+ )
268
+ end
269
+ end
270
+ end
271
+ end
272
+ end
@@ -0,0 +1,84 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "nokogiri"
4
+ require "xxx_rename"
5
+
6
+ module XxxRename
7
+ module SiteClients
8
+ class Nfbusty < Base
9
+ include HTTParty
10
+
11
+ base_uri "https://nfbusty.com"
12
+ site_client_name :nf_busty
13
+
14
+ SCENE_TITLE_REGEX = /^(?<scene_title>^.*)\s-\sS\d*:E\d*$/x.freeze
15
+ PAGE_COUNTER_REGEX = /(?<first>\d+)\sof\s(?<last>\d+)/x.freeze
16
+ FILE_REGEX = /^nfbusty_(?<scene_title>\w*)_\d+\.\w+$/x.freeze
17
+
18
+ def search(filename)
19
+ if response.empty?
20
+ XxxRename.logger.info "NFBusty extracts all the scenes before matching. This process may take some time.".colorize(:red)
21
+ fetch_all_scenes
22
+ end
23
+
24
+ scene_match = filename.match(FILE_REGEX)
25
+ raise Errors::NoMatchError.new(Errors::NoMatchError::ERR_NO_METADATA, filename) if scene_match.nil?
26
+
27
+ title = scene_match[:scene_title].normalize
28
+ @response[title] || raise(Errors::NoMatchError.new(Errors::NoMatchError::ERR_NO_RESULT, filename))
29
+ end
30
+
31
+ private
32
+
33
+ def response
34
+ @response ||= {}
35
+ end
36
+
37
+ def last_page?(doc)
38
+ page_text = doc.css(".dropdown-toggle").text.strip
39
+ match = page_text.match PAGE_COUNTER_REGEX
40
+ raise "Unable to parse page counter" if match.nil?
41
+
42
+ true if match[:first] == match[:last]
43
+ end
44
+
45
+ def fetch_all_scenes(page = 0)
46
+ XxxRename.logger.debug "Fetching Page #{"#".to_s.colorize(:blue) + page.to_s.colorize(:blue)}."
47
+
48
+ doc = Nokogiri::HTML request_video_html(page)
49
+ doc.css(".content-grid").css(".row").css(".content-grid-item").each do |element|
50
+ full_title = element.css(".caption-header").css(".title").text.strip
51
+ matched_title = full_title.match(SCENE_TITLE_REGEX)
52
+ next if matched_title.nil?
53
+
54
+ title = matched_title[:scene_title]
55
+ XxxRename.logger.debug("Extracted Scene #{title.to_s.colorize(:blue)}")
56
+ normalized_title = title.normalize
57
+
58
+ @response[normalized_title] = Data::SceneData.new(
59
+ {
60
+ collection: "NFBusty",
61
+ collection_tag: "NF",
62
+ title: title,
63
+ id: nil,
64
+ date_released: Time.strptime(element.css(".date").text.strip, "%b %e, %Y")
65
+ }.merge(actors_hash(element.css(".models").css(".model").map { |model| model.text.strip }))
66
+ )
67
+ end
68
+ return if last_page?(doc)
69
+
70
+ fetch_all_scenes(page + 1)
71
+ end
72
+
73
+ # @param [Integer] page
74
+ def request_video_html(page)
75
+ resp = self.class.get("/video/gallery/#{page * 12}").body
76
+ case resp.code
77
+ when 200 then resp
78
+ when 503 then raise SiteClients::Errors::SiteClientUnavailableError, self.class.base_uri
79
+ else raise "Something went wrong #{resp.code}"
80
+ end
81
+ end
82
+ end
83
+ end
84
+ end
@@ -0,0 +1,89 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "xxx_rename/utils"
4
+
5
+ module XxxRename
6
+ module SiteClients
7
+ module QueryGenerator
8
+ class Base
9
+ SearchParameters = Struct.new(:title, :id, :female_actors, :movie, :collection,
10
+ :male_actors, :actors, :collection_tag, :date_released,
11
+ :processed, :index, keyword_init: true)
12
+
13
+ attr_reader :filename, :processed_file_patterns, :source_pattern
14
+
15
+ def self.generate(_filename, *_patterns)
16
+ raise "Not Implemented"
17
+ end
18
+
19
+ def self.generic_generate(filename, patterns)
20
+ new(filename, [], patterns).parse
21
+ end
22
+
23
+ # @param [String] filename
24
+ # @param [Array[String]] source_pattern
25
+ # @param [Array[String]] processed_file_patterns
26
+ def initialize(filename, source_pattern, processed_file_patterns)
27
+ @filename = File.basename(filename, File.extname(filename))
28
+ @source_pattern = source_pattern
29
+ @processed_file_patterns = processed_file_patterns
30
+ end
31
+
32
+ # Attempt to generate search parameters using three approaches
33
+ # 1. Use the source format if passed (handled by base)
34
+ # 2. Assume the file had already been processed and use `ProcessedFile` (handled by base using ProcessedFile.parse)
35
+ # 3. Use any formats given by the query generator
36
+ # 4. Treat the file as downloaded from official source (handled by each site client query generator)
37
+ # @return [Nil, XxxRename::Data::SceneData]
38
+ def parse
39
+ parse_file_with_source_pattern || # Use the user provided source format
40
+ parse_file || # Assume file format matches default format of CLI
41
+ parse_file_with_patterns # Use any formats given by the query generator
42
+ end
43
+
44
+ private
45
+
46
+ def parse_file
47
+ parse_file!
48
+ rescue XxxRename::Errors::ParsingError, Dry::Struct::Error
49
+ nil
50
+ end
51
+
52
+ def parse_file!
53
+ ProcessedFile.parse(filename)
54
+ end
55
+
56
+ def parse_file_with_source_pattern
57
+ parse_file_with_source_pattern!
58
+ rescue XxxRename::Errors::ParsingError, Dry::Struct::Error
59
+ nil
60
+ end
61
+
62
+ def parse_file_with_source_pattern!
63
+ source_pattern.map do |sp|
64
+ resp = ProcessedFile.strpfile(filename, sp)
65
+ return resp unless resp.nil?
66
+ end
67
+ nil
68
+ end
69
+
70
+ def parse_file_with_patterns
71
+ processed_file_patterns.compact
72
+ .map { |x| parse_file_with_pattern(x) }
73
+ .compact
74
+ .first
75
+ end
76
+
77
+ def parse_file_with_pattern!(pattern)
78
+ ProcessedFile.strpfile(filename, pattern)
79
+ end
80
+
81
+ def parse_file_with_pattern(pattern)
82
+ parse_file_with_pattern!(pattern)
83
+ rescue XxxRename::Errors::ParsingError, Dry::Struct::Error
84
+ nil
85
+ end
86
+ end
87
+ end
88
+ end
89
+ end
@@ -0,0 +1,36 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "xxx_rename/site_clients/query_generator/base"
4
+
5
+ module XxxRename
6
+ module SiteClients
7
+ module QueryGenerator
8
+ class EvilAngel < Base
9
+ extend Utils
10
+
11
+ def self.generate(filename, source_format)
12
+ if (data = new(filename, source_format, []).parse)
13
+ SearchParameters.new(
14
+ title: data.title,
15
+ id: data.id,
16
+ actors: data.actors,
17
+ processed: true
18
+ )
19
+ else
20
+ # Make sure to do this match to prevent unnecessary calls to API
21
+ return unless filename.match?(Constants::EVIL_ANGEL_ORIGINAL_FILE_PATTERN)
22
+
23
+ match = filename.match(Constants::EVIL_ANGEL_ORIGINAL_FILE_PATTERN)
24
+
25
+ SearchParameters.new(
26
+ actors: match[:actors]&.split("_"),
27
+ title: match[:title].titleize_custom,
28
+ index: match[:index],
29
+ processed: false
30
+ )
31
+ end
32
+ end
33
+ end
34
+ end
35
+ end
36
+ end
@@ -0,0 +1,27 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "xxx_rename/site_clients/query_generator/base"
4
+
5
+ module XxxRename
6
+ module SiteClients
7
+ module QueryGenerator
8
+ class Goodporn < Base
9
+ extend Utils
10
+
11
+ def self.generate(filename, source_format)
12
+ if (data = new(filename, source_format, []).parse)
13
+ "#{data.collection} #{data.title} #{data.date_released.strftime("%m %d %Y")}"
14
+ .downcase
15
+ .gsub(/[^\w\s]/, "")
16
+ .gsub(/\s+/, "-")
17
+ else
18
+ # Make sure to do this match to prevent unnecessary calls to API
19
+ return unless filename.match? Constants::GOODPORN_ORIGINAL_FILE_FORMAT
20
+
21
+ File.basename(filename, ".*").split("_")[0]
22
+ end
23
+ end
24
+ end
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,26 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "xxx_rename/site_clients/query_generator/base"
4
+
5
+ module XxxRename
6
+ module SiteClients
7
+ module QueryGenerator
8
+ class MgPremium < Base
9
+ extend Utils
10
+
11
+ def self.generate(filename, source_format)
12
+ if (data = new(filename, source_format, []).parse)
13
+ SearchParameters.new(title: data.title)
14
+ else
15
+ # Make sure to do this match to prevent unnecessary calls to API
16
+ return unless filename.match? Constants::MG_PREMIUM_ORIGINAL_FILE_FORMAT
17
+
18
+ basename = File.basename(filename, ".*")
19
+ scene_title = basename.split("_")&.first&.split("-")
20
+ SearchParameters.new(title: adjust_apostrophe(scene_title))
21
+ end
22
+ end
23
+ end
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,24 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "xxx_rename/site_clients/query_generator/base"
4
+
5
+ module XxxRename
6
+ module SiteClients
7
+ module QueryGenerator
8
+ class NaughtyAmerica < Base
9
+ extend Utils
10
+
11
+ def self.generate(filename, source_format)
12
+ if (data = new(filename, source_format, []).parse)
13
+ SearchParameters.new(**data.to_h)
14
+ else
15
+ # Make sure to do this match to prevent unnecessary calls to API
16
+ return unless filename.match? Constants::NAUGHTY_AMERICA_ORIGINAL_FILE_REGEX
17
+
18
+ filename.match(Constants::NAUGHTY_AMERICA_ORIGINAL_FILE_REGEX)[:compressed_scene]
19
+ end
20
+ end
21
+ end
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,21 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "xxx_rename/site_clients/query_generator/base"
4
+
5
+ module XxxRename
6
+ module SiteClients
7
+ module QueryGenerator
8
+ class StashDb < Base
9
+ extend Utils
10
+
11
+ def self.generate(filename, source_format)
12
+ return unless (data = new(filename, source_format, []).parse)
13
+
14
+ SearchParameters.new(**data.to_h.slice(:title, :id, :female_actors, :movie, :collection,
15
+ :male_actors, :actors, :collection_tag, :date_released,
16
+ :processed, :index))
17
+ end
18
+ end
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,27 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "xxx_rename/site_clients/query_generator/base"
4
+
5
+ module XxxRename
6
+ module SiteClients
7
+ module QueryGenerator
8
+ class Vixen < Base
9
+ extend Utils
10
+
11
+ PATTERN_1 = "%actors [T] %title [S] %collection [ID] %id"
12
+
13
+ def self.generate(filename, source_format)
14
+ if (data = new(filename, source_format, [PATTERN_1]).parse)
15
+ SearchParameters.new(**data.to_h.slice(:title, :id, :female_actors, :collection, :male_actors, :actors))
16
+ else
17
+ re_match = filename.match(Constants::VIXEN_MEDIA_ORIGINAL_FILE_REGEX_1) ||
18
+ filename.match(Constants::VIXEN_MEDIA_ORIGINAL_FILE_REGEX_2)
19
+ return if re_match.nil?
20
+
21
+ SearchParameters.new(id: re_match[:id], collection: re_match[:collection])
22
+ end
23
+ end
24
+ end
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,39 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "xxx_rename/site_clients/query_generator/base"
4
+
5
+ module XxxRename
6
+ module SiteClients
7
+ module QueryGenerator
8
+ class Whale < Base
9
+ extend Utils
10
+
11
+ # Generated using default format
12
+ PATTERN_1 = "%female_actors [T] %title [%collection_tag_2] %collection [ID] %id"
13
+ PATTERN_2 = "%female_actors [T] %title [%collection_tag_2] %collection"
14
+
15
+ def self.generate(filename, source_format)
16
+ query = new(filename, source_format, [PATTERN_1, PATTERN_2])
17
+ resp = query.parse
18
+ if resp
19
+ SearchParameters.new(
20
+ collection: resp.collection.normalize.to_sym,
21
+ title: resp.title&.downcase&.gsub(/\s/, "-"),
22
+ id: resp.id.to_s
23
+ )
24
+ else
25
+ match = filename.match(Constants::WHALE_ORIGINAL_FILE_PATTERN)
26
+ return if match.nil?
27
+
28
+ SearchParameters.new(
29
+ collection: match[:site]&.to_sym,
30
+ title: match[:title],
31
+ # At this time, we don't know what the id tag of the scene is
32
+ id: ""
33
+ )
34
+ end
35
+ end
36
+ end
37
+ end
38
+ end
39
+ end
@@ -0,0 +1,14 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "xxx_rename/site_clients/mg_premium"
4
+
5
+ module XxxRename
6
+ module SiteClients
7
+ class RealityKings < MGPremium
8
+ site_client_name :reality_kings
9
+ def initialize(config)
10
+ super(config, site_url: "https://www.realitykings.com")
11
+ end
12
+ end
13
+ end
14
+ end