XxxRename
A gem to rename your porn videos and integrate with your Stash app as a third- party scraper.
Currently supports the following websites:
- AdultTime*
- Babes
- Blacked
- BlackedRaw
- Brazzers
- Casting Couch
- Dark X
- Digital Playground
- Elegant Angel
- Erotica X
- Evil Angel
- Exotic4k
- FantasyHD
- GoodPorn
- Hard X
- Holed
- Jules Jordan
- Lubed
- Manuel Ferrara
- Mofos
- My Very First Time
- NF Busty
- Nanny Spy
- POVd
- PassionHD
- Puremature
- Reality Kings
- Slayed
- SpyFam
- Stash DB
- Tiny 4k
- Tushy Raw
- Tushy
- Twistys
- Vixen
- X Empire
- Wicked
- Zero Tolerance Films
Installation
gem install xxx_rename
Usage
Basic Usage
$ xxx_rename help
Commands:
xxx_rename generate FILE|FOLDER # Rename a file or all file(s) inside a given directory
xxx_rename help [COMMAND] # Describe available commands or one specific command
xxx_rename migrate --version=VERSION # Apply a rename migration file
xxx_rename rollback --version=VERSION # Rollback a migration
xxx_rename version # Print the CLI version
Generate
Generate command scans all files and stores their scraped data inside a file
stored in the xxx_rename
config directory. You can add actions that will
be performed with each successful match:
- sync_to_stash : Sync the matched details to your Stash App. This will create a movie as well on Stash if the scene belongs to a movie (which is something that Stash does not do at the moment.)
- log_rename_op : Create a migration file that logs a file with its new filename. Migrations are reversible operations that rename all files that are matched by xxx_rename.
$ xxx_rename help generate
Usage:
xxx_rename generate FILE|FOLDER
Options:
[--config=CONFIG] # path to config file
[--verbose], [--no-verbose] # enable verbose logging
[--override-site=OVERRIDE_SITE] # force use an override site
# Possible values: adult_time, babes, blacked, blacked_raw, brazzers, digital_playground, elegant_angel, evil_angel, goodporn, jules_jordan, manuel_ferrara, mofos, naughty_america, nf_busty, reality_kings, stash, tushy, tushy_raw, twistys, vixen, whale_media, wicked, x_empire, zero_tolerance
[--nested], [--no-nested] # recursively search for all files in the given directory
[--force-refresh-datastore], [--no-force-refresh-datastore] # force site client to fetch all scenes, if implemented
[--actions=ACTIONS] # action to perform on a successful match
# Possible values: sync_to_stash, log_rename_op
[--force-refresh], [--no-force-refresh] # force match scenes from original sites
[--checkpoint=CHECKPOINT] # skip all iterations until check-pointed file is matched
Description:
Scan files and generate metadata
For first time users, run the command without any flags to generate a config file in $HOME/.config/xxx_rename
$ xxx_rename generate
The cli will look for a config file in these three places in order:
* --config (This takes precedence over everything)
* $HOME/.config/xxx_rename
* HOME/xxx_rename
Examples
# Scan all files in a given directory and its sub-directories
$ xxx_rename generate . --nested
# Force the cli to use `brazzers` to match a file
$ xxx_rename generate . --verbose --override_site=brazzers
# Generate a migrations file to rename the matched files
$ xxx_rename generate . --actions=log_rename_op
Migrate
$ xxx_rename help migrate
Usage:
xxx_rename migrate --version=VERSION
Options:
[--config=CONFIG] # path to config file
[--version=VERSION] # Name of migration file to apply
# Default: latest
Description:
WARNING: This is a destructive operation as it will rename files Run this on a small subset to be sure and run it at your own risk
Rename files based on operations listed in a migration file.
All rename files are located in your `generated_files_dir` directory. Migration files are plain YAML files of format 'output_YYYYMMDDHHMM.yml'
Pass a migration file using option `--version YYYYMMDDHHMM`.
If you want to apply a migration file that you have just created, pass the --version as "latest". Or don't pass the --version flag and the CLI will use the latest version by default.
Migration files have the following format:
-
--- # 0 means the migration is not applied
# 1 means the migration is applied
# This flag prevents applying a migration that has already been applied
___MIGRATION_STATUS___: 0
# All operations are stored as an array
___RENAME_ACTIONS___:
# DO NOT MANIPULATE AN ARRAY ITEM! Doing so can result in unexpected
# behaviour. You can remove an operation from the list entirely, but
# the recommended way is to discard this migration completely,
# modify the `output_format` for your file in the config and run the
# generate command again
- !ruby/object:XxxRename::Data::FileRenameOp
attributes:
:key: eab204175567d39202c1df5895e443be # DO NOT MODIFY THIS
:directory: "/ABSOLUTE/DIRECTORY/TOFILE"
:source_filename: ORIGINAL_FILENAME.MP4
:output_filename: NEW_FILENAME.MP4
:mtime: 2000-01-01 00:00:00.000000000 +00:00
Example Usage:
$ xxx_rename migrate --version=202301131252
$ xxx_rename migrate
Rollback
$ xxx_rename help rollback
Usage:
xxx_rename rollback --version=VERSION
Options:
[--config=CONFIG] # path to config file
[--version=VERSION] # Name of migration file to apply
# Default: latest
Description:
Reverse the actions taken by the `migrate` command
Read the help command for more information
$ xxx_rename help migrate
FAQs
How does this work?
xxx_rename works assumes all files are a scene. Each scene can be matched by one (or more) site client (a site that will be scraped to fetch details). For some files that are downloaded from original sources (at this time these are mg premium sites brazzers along with evil angel, goodporn, NF busty and vixen media), xxx_rename will try to guess the site client based on the unique format of the filename themselves.
In other case, you are required to define these rules yourself in the config file. Rules are just string of tokens that generate a regex to match a file. For example, let's say you have a file like this "[EvilAngel] Blake Blossom - Facial Fantasy 3.mp4". You can create a rule in your config file like this:
evil_angel:
file_source_format:
# Notice the missing .ext in the pattern
- "[EvilAngel] %female_actors - %title"
Now, when you run the generate
command, xxx_rename will look at the rules and
match the file with evil_angel. It will then use the %title(Facial Fantasy 3)
and %female_actors([Blake Blossom]) data and search EvilAngel for a scene that
matches the parsed details from a file. This will near guarantee that the
match will be correct (which can be an issue with other tools like
stash-box or
metadataapi.net).
What are collection_tags
in the config?
Think of collection_tag
as reserved keywords. collection_tags
are three
character unique keywords that are used to associate a file with a site client.
The CLI expects all filenames to have a unique format, which can be a problem
when all files are renamed using a common format. collection_tags
introduce
just enough uniqueness in the filename to allow xxx_rename
associate them with
a site client.
What are the supported tokens
Token | Regex | Description |
---|---|---|
%title | (?<title>[\w\s\-_,'\"\.]+) | Title of the scene |
%collection | (?<collection>[\w\s\-_,'\"\.]+) | Usually the studio |
%collection_op | (?<collection>[\w\s\-_,'\"]*?) | Same as collection, but allows optional values |
%collection_tag_1 | (?<collection_tag>\w) | A single character reserved word |
%collection_tag_2 | (?<collection_tag>\w,2) | Two character reserved word |
%collection_tag_3 | (?<collection_tag>\w,3) | Three character reserved word |
%female_actors | (?<female_actors>[\w\s\-_,'\"\.]+) | Comma Separated list of names |
%male_actors | (?<male_actors>[\w\s\-_,'\"\.]+) | Comma Separated list of names |
%male_actors_op | (?<male_actors>[\w\s\-_,'\"]*)? | Same as %male_actors, but optional |
%actors | (?<actors>[\w\s\-_,'\"\.]+) | Use if there's no obvious separator between male and female actors |
%id | (?<id>(\d+\ | [a-z\-\_]+)) |
%id_op | (?<id>(\d*\ | [a-z\-\_]*))? |
%ignore_1_word | (\w\s)1 | Ignore a filler word |
%ignore_2_words | (\w\s)2 | Ignore 2 filler word |
%ignore_3_words | (\w\s)3 | Ignore 3 filler words |
%ignore_4_words | (\w\s)4 | Ignore 4 filler words |
%ignore_5_words | (\w\s)5 | Ignore 5 filler words |
%ignore_6_words | (\w\s)6 | Ignore 6 filler words |
%ignore_7_words | (\w\s)7 | Ignore 7 filler words |
%ignore_all | ".* | Ignore everything |
%yyyy_mm_dd | (?<year>\d4)_(?<month>\d1,2)_(?<day>\d1,2) | Complete year in YYYY_MM_DD for |
%dd | (?<day>\d1,2) | DD (Day of Month) |
%mm | (?<month>\d1,2) | MM (Month of Year) |
%yyyy | (?<year>\d4) | YYYY (Year) |
%yy | (?<year>\d2,4) | YY (Compressed Year) |
How does xxx_rename compare with Stash DB?
xxx_rename can be considered an extension to
Stash. It does not intend to compete with
the sheer number of features provided by Stash. In fact, stash-box is considered
a valid site client
if you want to use it. Stash DB's matches are pretty
accurate given their community contribution and phash matching algorithm.
But I also realise stash is an overkill for a lot of people. For someone who
has a casual collection and just want to organize their files with meaningful
names (compared with obfuscated names some sites use for their original files),
xxx_rename works beautifully and serves their purpose well.
You choose how you want your files to be renamed and what data you like and what you don't. Change your mind in the future? No problem, xxx_rename remembers all scenes and you can choose a new format anytime you want.
How does xxx_rename compare with namer?
namer works on a similar principle as xxx_rename, in which it also uses regexes to fetch metadata from a filename. But it matches a search using its own database metadataapi.net. While the tool is really amazing and requires little configuration from the user, it results in mismatches and you can end up with a filename that is simply incorrect.
xxx_rename works on the principle of BYOD (Bring Your Own Data). All search happens locally, there are no external servers, no tracking whatsoever and you own your database. Since there's a certain configuration required from your side, there are little chances for any errors. xxx_rename is not a swiss knife of all scrapers, it prefers correctness over convenience.
Why is Site X not supported?
Some websites are really stubborn as they do not provide a basic search facility. The biggest example of this is Naughty America, which has been a paid to find a workaround and implement from scratch. Some websites lock their search behind a paywall(membership), so while it's possible for me to implement a search functionality, it is impossible to test and maintain once the membership period is over.
What sites can be supported?
Any site that provide a meaningful filename and have a usable API/website. Raise a request on the issues page with the name of the website you want to get support for and a list of original filenames (not the actual files). I can't promise if I will be able to implement it but the request will be open for someone in the community to integrate.
Contribution
Pull requests are welcome! See Development for setup instructions.