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
@@ -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
|