I'm not yet ready to run scripts on my files; too many exceptions to any given set of rules, to let it automatically run.
So I'm quite happy using the GUI & revising format code.
I've found some useful Groovy programming references, but a few things still elude me, and I'm hoping some kind soul can look at my code & suggest some improvements.
I have streamlined it as best I can (so far), and I'm sure there are still efficiency hacks that can be found - for now, I'm content in understanding the code as it is, but could use some assistance fixing a few still-unknowns.
Below the examples is my code (with documentation), line-broken for readability.
I've tweaked a few workarounds to some of these issues just below, but if anyone can suggest fixes, much appreciated.
I know red's a busy guy; anyone else willing to review this & take a crack at (any of) these?
Once I've got it figured out (or, once someone has helped me determine the best method/s), I want to document all of this for reference in future.
What I'm still struggling with (examples):
Formatting
1) Au --> AU will capitalize the 2-letter phrase "Au". I want this for references to Australia (i.e. when a show name has a UK version & an AU version. So I want this working for instances of " (Au)" or " Au" but not " Audition".
I'm having trouble finding the code for a LITERAL interpretation of round brackets - so that " (Au)" is seen as "space-openbracket-A-u-closebracket".
I can find that \b refers to a space before the next characters, which it would in the case of a "showname (country)", but I'm still seeing instances where it doesn't quite work.
2) AM/PM, A.M./P.M. --> I'd like these to show the periods if they're part of the name, but no periods if they're not.
I've tried various replace functions, but I keep getting instances of "A Madman" coming back as "A.M.dman" or "aM" or something else that's not right.
3) Roman Numerals
The code covers anything in RN except '500' ('D') - when included, any names/titles with "Did" in them, gets uppercased, since both D & I are in the phrase.
Any thoughts on expanding the brief one-liner? Or would I be better off simply using direct replaceAll instances to "DI", "DV", "DX", "DC", etc... ??
4) multiple replaceAll's exist with strings along with 'not-sure-what-to-call-these' (.replaceAll(/[?|]/, "!") ) to cover various scenarios. I'd like to make these better, perhaps using a TV Replacements.csv file - note that Scottish-type names ('McTaggart') are using a straight "replace Mct with McT" format; I'd like to set all letters up for this, without repeating it 26 times - perhaps a code for {n.replaceAll ('Mc*'), ('Mc')+('*').uppercase} or similar...
Filename replacing
5) When there are crossover episodes between 2 shows, I like to keep a copy of the 'real show' with 'this show'.
I rename the copy as 'this show s00e00a' - 'real show s00e00...'
Ex: Without a Trace S06E06 aired just after CSI S08E06, so in the CSI folder, it's
CSI S08E06a- Without a Trace S06E06 - Where & Why - 2007-11-08 [Action, Adventure, Crime, Drama]
I know this could be done with a {fn} expression, but I'm stumped & starting this bit from scratch.
Of course, the file would need to be named CSI S08E06a manually first, so that it could have a function performed on it. How can I I.D. the 'a' (or 'b' or 'c') that I placed in the episode number, and pull the inner show name WAT from it? Or is this just TOO picky... There may only be a dozen instances of this in my collection, but if it CAN be done, I want to try & figure out HOW to...
Ideally, I want to replace the 'a' file as a 'b' file, and add an 'a' to the actual show filename:
In this case, CSI S08E06a becomes CSI S08E06b - WAT... and CSI S08E06 becomes CSI S08E06a
I like to keep the files as close to 'in order' as I can, alphanumerically.
Anyone done anything similar?
Missing fields
6) I've brought this up in another post, but I'll try here fresh...
Some (a very few - like a half-dozen) shows out of 6,000 - get returned by TVRage without a genre - not a 'blank' result, but a 'missing field'.
My code replaces a blank result with the phrase 'GENRE', but on these few, it is coming back empty.
Crude Britannia- The Story of North Sea Oil (2009, NETWORK) S01E01 - Episode 1 (2009-06-18) [] is an example show.
My format brings up the AIRDATE, but no NETWORK or GENRE. Only the GENRE is 'missing' from the resulting data.
The blank NETWORK field, correctly gets replaced with the phrase 'NETWORK', but genre is blank (the last bit of the code, which results in a '[]' but should be '[GENRE]'.
I have just recently figured out that TVRage data comes back with some blank genres, even when there is data on the show profile; don't know if it's an issue with their dbase, or API, or something else.
CSVs
7) I use a TV Network.csv file to determine country of origin
I have seen references (usually to script/CLI efforts) in the forums to using a TV Show.csv to keep a list of shows standard when renaming... that is; when the filename is TBBT, to use showname 'The Big Bang Theory', etc.
I've got most filenames set now; so I'd like to have the {fn} check against the CSV & never try to match another similarly-named show.
I've used MediaIndex to create a detailed file of names/specs which can provide the base CSV to check against.
I'm not quite sure how to do this one. ??
8) Also for CSVs, I'd like to set a TV Genres.csv file to check - essentially, "if Comedy is one of the genres returned, use Comedy" as opposed to doing a long if/then statement as it's set for right now, which is inefficient & clunky, as the genres are not sorted alphabetically when returned.
Code: Select all
{
//
Section 1
1) Set location for sorted files to go (Z:\Premiers\SORTED) - I prefer the Z: drive to \\Drobo5N\DRT-Media as it is shorter for the GUI, and Z: should always exist if I'm managing the files.
2) Check genres - if any of the genres are X, then use Y - this selects all Comedy as a primary sort, then Sci Fi, etc...
3) If no specific genre found, use '_NO_GENRE'.
NOTE: folder path slash must be right up against the brackets, else a blank space will appear. This may be correctable, but I haven't found a solution yet, to allow the next field to be on a separate line.
4a) If a series start year (y) exists, then use it to sort into decades (i.e. 1987 becomes 1980s).
4b) If no series start year exists, try the airdate year - this particular formatting is for my Premiers collection, so all episodes are S01E01 anyway.
4c) If neither year exists, set field to 'YEAR' so it can be sorted separately, for later review.
NOTE: folder path slash must be right up against the brackets, else a blank space will appear. This may be correctable, but I haven't found a solution yet, to allow the next field to be on a separate line.
5a) Series name (n) with the typical Uppercase first letter, lower rest of word; A/An/The to the back of the title, and a few punctuation corrections (characters Windows doesn't like in filenames).
5b) Set numerical references (1st, 2nd, 3rd...) to lowercase to avoid 1St, 2Nd, 3Rd...
5c) Set Roman Numerals to uppercase.
5d) Set common uppercase words.
5e) Set common lowercase words.
5f) Set a few unique 'phrases' that might otherwise be considered a word if part of another word.
5g) STILL ISSUES WITH some - US, AU, etc. - there should be a more defined formatting option I haven't discovered yet...
6a) TVRage brings back a lot of 'empty' genres & networks, despite them having data. FB is treating some of the blanks as 'blank' and some as 'missing', thus I cannot figure a way to cover both with one function.
6b) When there is NO GENRE RESULT, try full line with Z:\...
6c) When this fails (seemingly depends on the db in use) where genre & network are blank/missing, try dropping the any-genres from inside the first curly-bracket and the curly-bracket 'GENRES' just before the folder slash at the end of the operation.
6d) Still working on this.........
}
{
//
Section 1a
-add a check to replace the showname (YEAR) with blank, so that the Y or AIRDATE will pick it up, avoiding a duplicate, i.e. Abcde (2011) (2011, ABC, #12345)...
}
Z:\Premiers\SORTED\{if(genres.contains
('Comedy')) {'Comedy'} else if (genres.contains
('Science Fiction')) {'Sci Fi'} else if (genres.contains
('Science-Fiction')) {'Sci Fi'} else if (genres.contains
('Fantasy')) {'Fantasy'} else if (genres.contains
('Action')) {'Action'} else if (genres.contains
('Thriller')) {'Thriller'} else if (genres.contains
('Documentary')) {'Documentary'} else if (genres.contains
('Reality')) {'Reality'} else if (genres.contains
('News')) {'Documentary'} else if (genres.contains
('Drama')) {'Drama'} else if (genres.contains
('Crime')) {'Drama'} else if (genres.contains
('Horror')) {'Horror'} else if (genres.contains
('Game')) {'Game'} else if (genres.contains
('Game Show')) {'Game'} else if (genres.contains
('History')) {'History'} else if (genres.contains
('Wildlife')) {'Wildlife'} else if (genres.contains
('Travel')) {'Travel'} else if (genres.contains
('Food')) {'Food'} else if (genres.contains
('Home and Garden')) {'Home and Garden'} else if (genres.contains
('Animation')) {'Animation'} else if (genres.contains
('Children')) {'Children'} else if (genres.contains
('Family')) {'Family'} else if (genres.contains
('Special Interest')) {'Special Interest'} else if (genres.contains
('Educational')) {'Educational'} else if (genres.contains
('Lifestyle')) {'Lifestyle'} else if (genres.contains
('Mini-Series')) {'MiniSeries'} else if (genres.contains
('Talk Show')) {'Talk Show'} else if (genres.contains
('Sport')) {'Sports'} else if (genres.contains
('Sports')) {'Sports'} else if (genres[0]?.trim())
{'_GENRE_ZERO_'} else '_GENRE'}\{any{((int)y/10)+'0s'} {any{((int)airdate.year/10)+'0s'}{airdate.year}} {'_YEAR'}}\{norm = {it.upperInitial() .lowerTrail()
.replaceAll(/[`´‘’“”""]/, "'")
.replaceAll(/[:]/, "- ")
.replaceAll(/[;]/, ", ")
.replaceAll(/[?|]/, "!")
.replaceAll(/ /, " ")
.replaceAll(/[*\s]+/, " ")
.replaceAll(/\b[0-9]+(?i:Th|Nd|Rd|St|S)\b/, { it.lower() })
.replaceAll(/\b[IiVvXxLlCcMm]+\b/, { it.upper() })
.replaceAll(/\b(?i:N'| a| on| or| of| the| an| and| at| by| with| if| in| is| to| than| for| are| vs| O'| 'Til|'m|'d|'ll|'ve|' It)+\b/, {it.lower() })
.replaceAll(/\b(?i:aka|bff|chp|bmx|cmt|nfl|mtv|mvp|nyc|fbi|cia|gb|usa|cctv|csi|fyi|nasa|nypd|bbc|vcr|vhs|dvd|nz|uk|ncis|csi|pd|ocd|wwi|wkrp|bbq| tv|sg-1|fm|dj|diy|qi|rv|sos|ufo|wwi|wwii|wpc|hd| cp| cn| er| la| dds)\b/, { it.upper() })
.replaceAll(/(Dc)/, "DC").replaceAll(/(Dci)/, "DCI").replaceAll(/(Md)/, "MD").replaceAll(/(NY)/, "NY").replaceAll(/(Uk)/, "UK").replaceAll(/(Anzac)/, "ANZAC")
.replaceAll(/(Rupaul)/, "RuPaul").replaceAll(/(Versus)/, "vs").replaceAll(/(LIL')/, "Lil'")
.replaceAll(/(Mca)/, "McA") .replaceAll(/(Mcb)/, "McB") .replaceAll(/(Mcc)/, "McC") .replaceAll(/(Mcg)/, "McG") .replaceAll(/(Mcm)/, "McM") .replaceAll(/(Mcn)/, "McN") .replaceAll(/(Mct)/, "McT")
.replaceAll(/(Au )/, "AU ") .replaceAll(/( Pm)/, " PM")
.replace(" ($y)",'')
.replaceTrailingBrackets()
}
; norm(n).replaceFirst(/^(?i)(The|A|An)\s(.+)/, /$2, $1/) }
{
//
Section 2
1) Find the start year of the series & append to the (above) name.
1a) If there is anything in the year (y) then use it.
1b) Else if there is anything in the airdate then use it.
1c) Else use 'YEAR'.
-) NEED TO ADD A WAY TO ELIMINATE DUPLICATE YEARS (i.e. XYZ (2014) (2014, ABC...))
2) Find the broadcasting network of the show; else use 'NETWORK'.
3) Find the dbase ID#; else use '#ID#'.
.replaceAll(/\b[Tv]+\b/, { it.upper() }).replaceAll(/\b[T.v.]+\b/, { it.upper() })
.replaceAll('a.M.','A.M.').replaceAll('p.M.','P.M.')
}
({any{y} {any{airdate.year}{airdate.year}} {'YEAR'}},
{any{info.network} {'NETWORK'}},
#{any{info.id}{'ID#'}})
{
//
Section 3
1) Set special episode numbers (should be good with the s00e00, but just in case)
2) Set episode number format as SeasonXXEpisodeXX
3) Same operators as above to clean up episode title name (t)
}
{episode.special ? 'S00E'+special.pad(2) : s00e00} - {norm(t)}
{
//
Section 4
1) If filename (fn) contains phrase 'CD' or 'Part' or 'Pt', change to/keep as 'Pt' so a split episode doesn't try to get overwritten.
}
{fn.contains('CD1') ? ' (Pt1)':""}{fn.contains('CD2') ? ' (Pt2)':""}{fn.contains('CD3') ? ' (Pt3)':""}
{fn.contains('Part1') ? ' (Pt1)':""}{fn.contains('Part2') ? ' (Pt2)':""}{fn.contains('Part3') ? ' (Pt3)':""}
{fn.contains('Pt1') ? ' (Pt1)':""}{fn.contains('Pt2') ? ' (Pt2)':""}{fn.contains('Pt3') ? ' (Pt3)':""}
{fn.contains('(1)') ? ' (Pt1)':""}{fn.contains('(2)') ? ' (Pt2)':""}{fn.contains('(3)') ? ' (Pt3)':""}
{fn.contains('3D') || fn.contains('3-D') ? ' '+'3D':""}
{' [' + fn.matchAll(/extended|uncensored|remastered|unrated|uncut|alternate|director's.cut|special.edition|unsold.pilot|unaired.pilot|unaired.episode/)*.upperInitial()*.lowerTrail().sort().join(', ').replaceAll(/ [._]/, " ") + ']'}
{
//
Section 5
1) Check airdate for the episode airdate; if exist, use it; else check starting year; if exist, use it; else use 'NO_AIRDATE'.
2) Where no airdate exists, but year exists, use year & add '-xx-xx' to illustrate it's a fix for a missing airdate.
3) Check if any genres exist; if so, use the first 3; if not, use 'NO_GENRE'.
}
({any{airdate}{any{y}{'AIRDATE'}}}) {genres.take(3) ?: '[GENRE]'}
{
//
Section 6
1) Match the network against my CSV file to get country of origin - if not found in CSV, use the network field; research & add that network to the CSV to update.
}
({csv('B:/Downloads/Filebot/TV Networks List.csv').get(info.network) ?: info.network})