Custom Collections Library

All about user-defined episode / movie / file name format expressions
Post Reply
AbedlaPaille
Posts: 107
Joined: 12 Apr 2020, 04:02

Custom Collections Library

Post by AbedlaPaille »

You know the Collections page in Plex? Some people tune it with custom collections for an easier access to their media. I did something similar here. The scheme uses 7 top level folder thematics (so far!) and checks for a match in that order :
  • Studios
    • Marvel
    • Pixar
    • Ghibli
  • Collections (If more than 1 item)
  • Directors
    • Alfred Hitchcock
    • Joel Coen
    • Terry Gilliam|Terry Jones|Charles Crichton
    • Quentin Tarantino
    • Quentin Dupieux
    • Stanley Kubrick
    • Mel Brooks
    • Martin Scorsese
    • Wes Anderson
    • Woody Allen
    • Michael Moore
    • Clint Eastwood
    • Gregg Araki
    • Akira Kurosawa
  • Older Movies (Before 1965)
  • French Movies
  • Foreign Movies (neither French nor English)
  • Genre, Custom order
I used a year prefix to sort Directors and Studios Collections by release date and a collection index prefix for Normal Collections.
E:/Films Custom/Directors/Hitchcock Collection/1960. Psycho/Psycho (1960) [BluRay 720p AVC 1.1 Mbps]
E:/Films Custom/Studios/Pixar Collection/2004. The Incredibles/The Incredibles (2004) [360p XviD 0.9 Mbps]
E:/Films Custom/Studios/MCU Collection/2018. Avengers - Infinity War/Avengers - Infinity War (2018) [BluRay 1080p 5.1 HEVC 10bit 2.2 Mbps]
E:/Films Custom/Collections/Mad Max Collection/1. Mad Max (1979)/Mad Max (1979) [480p XviD 2.2 Mbps]
Foreign Movies get a Language subfolder, primary title displayed in the tail
E:/Films Custom/Foreign Movies/German/The Wave (2008)/The Wave (2008) (Die Welle) [480p XviD 0.9 Mbps]
E:/Films Custom/Foreign Movies/Italian/Cinema Paradiso (1988)/Cinema Paradiso (1988) (Nuovo Cinema Paradiso) [480p AVC 1.2 Mbps]
Remaining movies get sorted by genre according to this order

Code: Select all

{def order = ['Animation': 1, 'Musical': 2, 'Documentary': 3, 'Family': 4, 'History': 5, 'Science Fiction': 6, 'Horror': 7, 'Fantasy': 8, 'War': 9, 'Western': 10, 'Action': 11, 'Comedy': 12, 'Crime': 13, 'Thriller': 14, 'Adventure': 15, 'Mystery': 16, 'Romance': 17, 'Drama': 18]
E:/Films Custom/Genres/Action/Sin City (2005)/Sin City (2005) [480p XviD 0.9 Mbps]
E:/Films Custom/Genres/Animation/Shrek (2001)/Shrek (2001) [360p DivX 1.1 Mbps]
Support for multiple same language subtitles
E:/Films Custom/Collections/The Dark Knight Collection/3. The Dark Knight Rises (2012)/The Dark Knight Rises (2012) [480p AVC 0.9 Mbps].fr (2)
E:/Films Custom/Collections/The Dark Knight Collection/3. The Dark Knight Rises (2012)/The Dark Knight Rises (2012) [480p AVC 0.9 Mbps].fr (1)
And a few other interesting things, i'll let you find out if you're curious ! If you want something a bit different i can help you. A million thanks to Rednoah. And Kim. I'm not sure my scheme is the best for computing power management though, can be a bit slow on an older machine. Maybe rednoah can point out bad resource usage :D

Did my best to make the code reader friendly. Hope it helps some neophyte passing by. Have a good day guys

Code: Select all

E:/Films Custom/

{ any	
	{  // Pixar, MCU and Ghibli Collections
		
		info.productionCompanies =~ /Studio Ghibli/ 
		? 'Studios/Ghibli Collection' 
		: info.productionCompanies =~ /Pixar/ 
		? 'Studios/Pixar Collection' 
		: info.productionCompanies =~ /Marvel Studios/ 
		? 'Studios/MCU Collection' 
		: ""
	}

	{  // If not, Normal Collections, process only if > 1 item, bilingual
		
		def missing = movie.collection - model.movie
	  	missing.size == movie.collection.size - 1 
	  	? "" 
	  	: info.OriginalLanguage =~ /fr/ 
	  	? 'Collections/'+localize.French.collection 
	  	: 'Collections/'+localize.English.collection.replaceAll(/[:|]/, " - ")
	}
																					 
	{  // If not, Directors Collections
	
		director =~ /Alfred Hitchcock/ 
		? 'Directors/Hitchcock Collection' 
		: director =~ /Woody Allen/ 
		? 'Directors/Woody Allen Collection' 
		: director =~ /Wes Anderson/ 
		? 'Directors/Wes Anderson Collection' 
		: director =~ /Martin Scorsese/ 
		? 'Directors/Scorsese Collection' 
		: director =~ /Mel Brooks/ 
		? 'Directors/Mel Brooks Collection' 
		: director =~ /Stanley Kubrick/ 
		? 'Directors/Kubrick Collection' 
		: director =~ /Quentin Dupieux/ 
		? 'Directors/Dupieux Collection' 
		: director =~ /Quentin Tarantino/ 
		? 'Directors/Tarantino Collection' 
		: director =~ (/Terry Gilliam|Terry Jones|Charles Crichton/) 
		? 'Directors/Monty Python Collection' 
		: director =~ /Joel Coen/ 
		? 'Directors/Coen Brothers Collection' 
		: director =~ /Gregg Araki/ 
		? 'Directors/Gregg Araki Collection' 
		: director =~ /Michael Moore/ 
		? 'Directors/Michael Moore Collection' 
		: director =~ /Clint Eastwood/ 
		? 'Directors/Clint Eastwood Collection' 
		: director =~ /Akira Kurosawa/ 
		? 'Directors/Kurosawa Collection'
		: ""
	}
	 
	{  // If not, Older Movies Collection
		
		y < 1965 
		? 'Older Movies' 
		: ""
	}
	 
	{  // If not, French Movies Collection, if not, Foreign Movies Collection and subfolders per country
	
		info.OriginalLanguage =~ /fr/ 
		? 'French Movies' 
		: info.OriginalLanguage != /en/ 
		? 'Foreign Movies/' + info.OriginalLanguage.toLocale().displayLanguage 
		: ""
	}
	 
	{  // If not, sort by Genre
	
		def order = ['Animation': 1, 'Musical': 2, 'Documentary': 3, 'Family': 4, 'History': 5, 'Science Fiction': 6, 'Horror': 7, 'Fantasy': 8, 'War': 9, 'Western': 10, 'Action': 11, 'Comedy': 12, 'Crime': 13, 'Thriller': 14, 'Adventure': 15, 'Mystery': 16, 'Romance': 17, 'Drama': 18].withDefault{ 100 }
		def map = ['Science Fiction': 'Sci-Fi']
		def genres = genres.toSorted{ order[it] }*.replace(map)
		'Genres/'+genres.first()
	}
}

/

{ any
	{  // Year first for Directors Collections
	
		director =~ (/Alfred Hitchcock|Joel Coen|Terry Gilliam|Terry Jones|Charles Crichton|Quentin Tarantino|Quentin Dupieux|Stanley Kubrick|Mel Brooks|Martin Scorsese|Wes Anderson|Woody Allen|Michael Moore|Clint Eastwood|Gregg Araki/) 
		? y+'. ' 
		: ""
	}
	
	{  // Year first for Studios Collections
	
		info.productionCompanies =~ (/Pixar|Marvel Studios|Studio Ghibli/) 
		? y+'. ' 
		: ""
	}
	
	{  // Collection index first for Collections with more than 1 item
	
		def missing = movie.collection - model.movie
		missing.size == movie.collection.size - 1 
		? "" 
		: ci+'. ' 
	}
}

{ norm = 
	{   // Illegal characters
		it.slash('-')
		  .replaceAll(/[`´‘’ʻ""“”]/, "'")
		  .replaceAll(/[:|]/, " - ")
		  .replaceAll(/[?]/, "!")
		  .replaceAll(/[*\s]+/, " ")
		  .replaceAll(/\b[IiVvXx]+\b/, { it.upper() })
		  .replaceAll(/\b[0-9](?i:th|nd|rd)\b/, { it.lower() })
	} ; 

	{  // Bilingual title
	
		info.OriginalLanguage =~ /fr/ 
		? norm(localize.French.n) 
		: norm(localize.English.n)
	}
}

{  // Year for all except Directors and Studios Collections

	director =~ (/Alfred Hitchcock|Joel Coen|Terry Gilliam|Terry Jones|Charles Crichton|Quentin Tarantino|Quentin Dupieux|Stanley Kubrick|Mel Brooks|Martin Scorsese|Wes Anderson|Woody Allen|Michael Moore|Clint Eastwood|Gregg Araki|Akira Kurosawa/) 
	? ""
	: info.productionCompanies =~ (/Pixar|Marvel Studios|Studio Ghibli/) 
	? "" 
	: ' ('+y+')'
}

/

{  // Bilingual name

	info.OriginalLanguage =~ /fr/ 
	? norm(localize.French.ny) 
	: norm(localize.English.ny)
}

{   // Primary title if neither French nor English

	info.OriginalName != n && ! (info.OriginalLanguage ==~ /(en|fr)/) 
	? ' (' + norm(primaryTitle.ascii().upperInitial()) + ')' 
	: ""
}

{ 
	tags 
	? ' ' + tags 
	: ' [' + fn.matchAll(/UNCENSORED|UNRATED|REMASTERED|EXTENDED|UNCUT|DIRECTOR\'?S[ ._-]CUT|THEATRICAL[ ._-]CUT|ULTIMATE[ ._-]CUT|FINAL[ ._-]CUT|SPECIAL[ ._-]EDITION/)*.upperInitial()*.sort().join(' ').replaceAll(/[.]/, " ") + ']' 
}

{ allOf 
	{ vs }
	{ vf }
	{ channels.match(/5.1/) }
	{ any 
		{ video.CodecID =~ /hev1|hevc|HEVC/ ? 'HEVC' : "" }
		{ video.CodecID =~ /AVC|avc|avc1/ ? 'AVC' : "" }
		{ vc }
	}
	{ if (bitdepth == 10) '10bit' }
	{ any 
		{ audio.size() > 2 ? 'MULTI' : audio.size() > 1 ? 'DUAL ' + audioLanguages.join('-').upper()  : "" }
		{ audio[0].language != /en/ ? audioLanguages[0].name.upper() : "" }
	}
	{ any 
		{ textLanguages =~ /fra/ ? 'VOSTFR' : textLanguages =~ /eng/ ? 'VOSTEN' : ""}
		{ fn.match(/VOSTFR|Vostfr|vostFR|VostFR|vostfr/).upper() } 
	}
	{ mbps }
  .joining(' ', ' [', ']')
}

{ any 
	{ ' ' + fn.match(/CD\d+/).upper()}
	{ " CD$pi" }
}

{ '.' + lang.ISO2 }

{ if (ext == 'srt' && dc > 1) " ($di)" }
Post Reply