//by @xeviff /** RUTAS **/ def inicialsActivades=true def root = '/pelis/' def rutaOK = root+"Pelis/plain/" def ruta = rutaOK def ruta_docu = root+"Documentales/plain/" def ruta_anime = root+"Pelis_anime/plain/" def ruta_animacion = root+"Pelis_animacion/" def ruta_infantil = root+"Pelis_infantiles/" def ruta_cat = root+"Pelis_amb_cat/" def ruta_esp = root+"Pelis_esp/plain/" def ruta_semiesp = root+"Pelis_esp/posible_esp/" def ruta_retro = root+"Pelis_retro/plain/" def ruta_estrenos = root+"Pelis_estrenos/plain/" def ruta_classic = root+"Pelis_classic/" def ruta_asiaticas = root+"Pelis_asiaticas/" def rutaKO = root+"error/" /**********/ /*TEST*/ /*def x = (certification =='PG.7' || certification =='G') return certification + genres +x*/ //resultado = info.ProductionCountries //return certification //return genres+genres.contains('Animación')//+anime //return genres.contains('Comedia') //return genres.contains('Familia') //return tieneGeneroFamilia(genres) //return (genres[1]=~ /Animaci\p{L}n/).find() //return tmdbid //return localize.cat.n //return primaryTitle+' cat: '+localize.cat.n+' esp:'+localize.Spanish.n //return primaryTitle+' '+localize.Catalan.plex.name /**/ /* HARDCODED */ def skipAudioCheck = true def infantilHardCoded = false /*************/ /* Excepciones */ /***************/ /** Audio (definición) **/ def hayEAC3=false def getAudiosFromListByFormat (format, listAudios) { def result=[] for (singleAudio in listAudios) { if (singleAudio.Format==format) { result.add(singleAudio) if ("EAC3"==format) hayEAC3=true } } return result } def getBestChannelFromList (audiosFormatFound) { def bestChanel def currentValue=0 for (myAudio2 in audiosFormatFound) { if (myAudio2.Channels>currentValue) { currentValue = myAudio2.Channels bestChanel = myAudio2 } } return bestChanel } def getMaxQuality (listOfLanguageAudio) { def formatSet = ["PCM", "MLP FBA" ,"DTS", "FLAC", "AC-3", "E-AC-3", "EAC3", "AAC", "MPEG Audio", "MP3"] for (cFormat in formatSet) { def audiosFormatFound = getAudiosFromListByFormat(cFormat, listOfLanguageAudio); if (!audiosFormatFound.isEmpty()) { return getBestChannelFromList(audiosFormatFound) } } //no debería llegar aquí, si lo hace hay que documentar el problema indicando el/los formato/s no encontrado/s def formatosInvolucradosProblema='[formato_audio_no_encontrado-' for (audioFormatNotFound in listOfLanguageAudio) { formatosInvolucradosProblema = formatosInvolucradosProblema+' '+audioFormatNotFound.Format } formatosInvolucradosProblema=formatosInvolucradosProblema+']' throw new Exception(formatosInvolucradosProblema) } def bloqueAudio def printAudio (audio2Print) { def idioma def idiomaOrigin = audio2Print.Language_String if (idiomaOrigin==null) { idiomaOrigin = audio2Print.Title if (idiomaOrigin =~ /(?i)\bcat\b/) idioma = "Cat" else if (idiomaOrigin =~ /(?i)\bcast\b|\bspa\b/) idioma = "Es" } else { idioma = idiomaOrigin.replace("Catalan","Cat").replace("Espanol / Espanol", "Es").replaceFirst(/(?i)(spanish|espa.ol)/,"Es") } def formato_audio = audio2Print.Format_Commercial.replace("Dolby Digital":"Dolby").replace(" Plus","+") .replace("DTS-HD Master Audio","DTS-MA").replace("DTS-HD High Resolution Audio","DTS-HD-H") .replace("MPEG Audio","MPEG").replace("HE-AAC","AAC+") .replace(" with Dolby Atmos", "Atmos") def canales = audio2Print.Channels.replace(2:'2.0', 6:'5.1', 8:'7.1') return idioma + ' ' + formato_audio + ' ' + canales } /***********/ /* otras funciones */ def tieneGeneroAnimacion (generos) { for (genero in generos) { if (genero =~ /Anima[c|t]i\p{L}n/) return true } return false } def tieneGeneroFamilia (generos) { for (genero in generos) { if (genero =~ /Familia|Family/) return true } return false } def tieneGeneroDocumental (generos) { for (genero in generos) { if (genero =~ /Documental|Documentary/) return true } return false } def esDocumental (generos, title) { def noJackass = !(title =~ /Jackass/) return tieneGeneroDocumental(generos) && noJackass } /**/ def getInicial () { def nomIngles = localize.English.n if (nomIngles.startsWith("The ") || nomIngles.startsWith("A ")) nomIngles = nomIngles.replaceFirst("The ",'').replaceFirst("A ",'') def ini0 = nomIngles[0].toUpperCase() def ini1 = nomIngles[1].toUpperCase() def iniClear = ini0.replaceAll(/[¡¿'#*\(]/,ini1) def inicial = iniClear.replaceAll(/[0-9]/,'#')+'/' return inicial } def fromEspPlatform (plataforma) { return plataforma =~ /(?i)\bFLIXOLE\b|\bRTVE\b/ } try { //empieza el script /** Tipo de archivo incorrecto **/ def esFicheroMetadatos = false def tipoMetadato def nombreWbloqueMediainfo if (ext=="jpg" || ext=="nfo" || ext=="png") { esFicheroMetadatos = true tipoMetadato = fn.find( //coge el contenido que encaja /(?=\-[^-]+$)(.*)(? 30 && numericBps >= 26000000) ? "4K-UHDRemux" : (peso > 15) ? "4K-UHDRip" : "4K-MicroUHD" : (vf == '1080p') ? //1080 (peso > 15 && numericBps >= 18000000) ? "1080-BDRemux" : (numericBps > 8000000) ? "1080-HD" : "1080-MicroHD" : vf //720 def calidadF = calidad=="4K-UHDRemux" ? "4K" : calidad=="4K-UHDRip" ? "4K" : calidad=="4K-MicroUHD" ? "micro4K" : calidad=="1080-BDRemux" ? "HD" : calidad=="1080-HD" ? "HD" : calidad=="1080-MicroHD" ? "microHD" : calidad=="SD" ? vf // Los SD vamos a poner su resolución : calidad //tal cual /***************************/ /** Audio (ejecución) **/ def catalanAudios=[] def spanishAudios=[] def englishAudios=[] def otherAudios=[] def audioDeclUndefined=false for (item in audio) { def idioma try { idioma = item.Language_String if (idioma==null) otherAudios.add("audio_no_def") //throw new Exception("[idioma_audio_no_definido0]") if ("Catalan"==idioma) catalanAudios.add(item) else if (idioma=~/(?i)(Spanish|Espa.ol)/) spanishAudios.add(item) else if ("English"==idioma) englishAudios.add(item) else if ("Undefined"==idioma) audioDeclUndefined=true else otherAudios.add(item) } catch (err) { if (idioma==null) { try { //si tampoco tiene item.Title def audioTitle=item.Title if (audioTitle!=null) { if (any{audioTitle}{0} =~ /(?i)\bcat\b/) catalanAudios.add(item) else if (any{audioTitle}{0} =~ /(?i)\bcast\b|\bspa\b/) spanishAudios.add(item) else if (any{audioTitle}{0} =~ /(?i)\bingl.es\b|\beng\b/) englishAudios.add(item) else otherAudios.add(item) } } catch (ex) {} } else if (!skipAudioCheck) throw err } } if (audioDeclUndefined || (catalanAudios.isEmpty() && spanishAudios.isEmpty() && englishAudios.isEmpty() && otherAudios.isEmpty()) ) { if (!skipAudioCheck) throw new Exception("[idioma_audio_no_definido]") } def tenimCat=false if (!catalanAudios.isEmpty()) { //tenim català tenimCat=true def maxCat = getMaxQuality(catalanAudios) def blocCat = printAudio(maxCat) def tenimEsp = !spanishAudios.isEmpty() def blocEsp='' if (tenimEsp) { def maxEsp = getMaxQuality(spanishAudios) blocEsp = ', '+printAudio(maxEsp) } bloqueAudio = blocCat + blocEsp } else if (!spanishAudios.isEmpty()) { //tenemos español def maxEsp = getMaxQuality(spanishAudios) bloqueAudio = printAudio(maxEsp) } else if (!englishAudios.isEmpty()) { //tenemos español if (!skipAudioCheck) throw new Exception("[idioma_audio_solo_ingles]") } else if (!otherAudios.isEmpty()) { //tenemos español if (!skipAudioCheck) throw new Exception("[idioma_audio_marginal]") } else { if (!skipAudioCheck) throw new Exception("[idioma_audio_no_encontrado]") } if (bloqueAudio==null) bloqueAudio = "audio_no_def" /***********/ //todo lo demás solo interesa para el fichero que contiene la pelicula //if (esFicheroMetadatos==false) { /** Formato distribución **/ formato_distribucion = fn=~/(?i)\bblu.?ray\b/ ? 'BDRip' : fn=~/(?i)\bdrip\b/ ? 'BDRip' : fn=~/(?i)\bDVD.?RIP\b/ ? 'DVDRip' : fn=~/(?i)\bHDiTunes\b/ ? 'HDiTunes' : fn=~/(?i)\bTV.?RIP\b/ ? 'TVRip' : fn=~/(?i)\bWEB.?Screener\b/ ? 'WEB-SRC' : 'no_encontrado' def plataforma def esWEB_DL=false if (formato_distribucion=='no_encontrado') { esWEB_DL = fn=~/(?i)\bWEB.??(DL|RIP)\b/ //WEB-DL o WEB-RIP (todo junto o con punto/guión/etc) if (esWEB_DL) { def web_x = fn=~/(?i)\bWEB.?DL\b/ ? 'WEB-DL' : 'WEB-RIP' //guardar el que es plataforma = fn.find( //coge el contenido que encaja /(?i)\bSATRIP\b|\bDVB\b|\bFLXL\b|\bAMZN?\b|\bNF\b|\bHBO\b|\bHBO.?MAX\b|\bHMAX\b|\bHULU\b|\bA3P\b|\bDPLY\b|\bSTARZ\b|\bFILMIN\b|\bFLMN\b|\bNETFLIX\b|\bDSN.?\b|\bDSP+?\b|\bRTVE\b|\bFLIXOLE\b/ ) if (plataforma!=null) plataforma = plataforma.replace("MVPLUS","MV+") formato_distribucion = web_x+(plataforma!=null?(' '+plataforma.toUpperCase()):'') //web-dl/rip + plataforma(si hay) } else { if (hayEAC3) //por el audio también se determina que es web-dl formato_distribucion = 'WEB-DL' else { def otrosFD = fn.find( /(?i)\bMTL\b |\bMUBI\b/ ) if (otrosFD!= null && !otrosFD.isEmpty()) formato_distribucion = otrosFD.toUpperCase() //si son estos, se setea } } } /**********/ /** Formato distribución 2ª ronda**/ //formato_distribucion = formato_distribucion=='no_encontrado'? '' : ' '+formato_distribucion if (formato_distribucion=='no_encontrado') { formato_distribucion = calidad=="4K-UHDRemux" ? "UHDRemux" : calidad=="4K-UHDRip" ? "UHDRip" : calidad=="4K-MicroUHD" ? "UHDRip" : calidad=="1080-BDRemux" ? "BDRemux" : calidad=="1080-HD" ? "DBRip" : calidad=="1080-MicroHD" ? "BDRip" : '' //no_encontrado -> '' } else { if (calidad=~/(?i)\remux\b/) { formato_distribucion = calidad=="4K-UHDRemux" ? "UHDRemux" : calidad=="1080-BDRemux" ? "BDRemux" : '' //no_encontrado -> '' } } if (formato_distribucion!='') formato_distribucion=' '+formato_distribucion /**********************************/ /**** Nombre pelicula ****/ def nombrePelicula_formatoPlex def tieneQueUsarSpa=true if (tenimCat) { try { if (primaryTitle!=localize.Catalan.n) { tieneQueUsarSpa = false nombrePelicula_formatoPlex = localize.Catalan.plex.name } } catch (err) { tieneQueUsarSpa=true } } if (tieneQueUsarSpa) nombrePelicula_formatoPlex = localize.Spanish.plex.name /*************************/ /**** HDR ********/ def hdr_info='' try{ def mHDRCol = ["BT.709" : "NO", "BT.2020" : "YES"] def hdr_info_old = (bitdepth >= 10 && mHDRCol.get(self.video[0].colourprimaries) == "YES" ) ? ' HDR' : '' def _HDRMap = [ "HDR10": "HDR10", "SMPTE ST 2086": "HDR10", "SMPTE ST 2094 App 4": "HDR10+", "Dolby Vision / SMPTE ST 2086": "Dolby Vision", "Dolby Vision / HDR10": "Dolby Vision", ] def vid = video.first() String _HDR switch (bitdepth) { case { it > 8 }: _HDR = any { vid["HDR_Format_Commercial"] } { vid["HDR_Format"] } { hdr } { null } break default: "$bitdepth-bit" break } def hdr_info_ = _HDRMap.find { k, v -> k =~ _HDR }?.value if (hdr_info_!=null) hdr_info=' '+hdr_info_ } catch (err) {} /*****************/ /**** Profundidad de color */ def profundidadColor='' try{profundidadColor = bitdepth+"bits" } catch(err){} /**************************/ /**** Profundidad vídeo ****/ def myBitrate = 'noBRdef' try{ myBitrate = mbps.replace(/.0/,'').replace(' ','') }catch(err){} def myFps = ' FRvar' try { myFps = ' '+fps.replace(/.0/,'').replace(' ','') }catch(err){} /***************************/ /* RESULTADO MEDIAINFO */ def bloqueCalidadVideo = calidadF+formato_distribucion+hdr_info def bloqueProfundidad = myBitrate+myFps if (bloqueProfundidad!='' && profundidadColor!='') bloqueProfundidad=' '+bloqueProfundidad nombreWbloqueMediainfo = nombrePelicula_formatoPlex +' ['+codecVideo+' '+bloqueCalidadVideo+']['+profundidadColor+bloqueProfundidad+']'+' ['+bloqueAudio+']' //+' {imdb-'+imdbid+'}' //} /**************************************/ /**** Carpeta / tipo contenido *******/ def generes def errorNoGenero=false try {generes=genres} catch (err) {errorNoGenero=true} def esDocu = esDocumental(generes, localize.English.n) def esAnime = anime || (tieneGeneroAnimacion(generes) && info.ProductionCountries.contains("JP")) if (esAnime) { def noAnimeListEx = [351460] if (noAnimeListEx.contains(tmdbid)) esAnime=false } def esAnimacion = tieneGeneroAnimacion(generes) if (esAnimacion) { def noAnimacionListEx = [554377, 708962, 35114] if (noAnimacionListEx.contains(tmdbid)) esAnimacion=false } //infantil def infantil=false def famyListEx = [575100] def noFamyListEx = [10637, 6639, 336121, 248688] if (famyListEx.contains(tmdbid)) infantil=true else if (noFamyListEx.contains(tmdbid)) infantil=false else { if (tieneGeneroFamilia(generes)) { infantil=true if (y<1980 && !esAnimacion) infantil=false } else { def certificacio try {certificacio=certification} catch (err) { certificacio = info.certifications.ES if (certificacio==null) certificacio = info.certifications.DE } if (certificacio!=null) { def familyCert = ['A', 'G', 'APTA', 'TP'] if (familyCert.contains(certificacio)) infantil=true } def certsMap = info.certifications if (certsMap.size()>0) { def noNens=false certsMap.each { key, val -> def num = val.findAll( /\d+/ )*.toInteger() if (num!=null && num[0]!=null) { try{ if (num[0]<8 && num[0]>1) { infantil=true } else if (num[0]>8) { noNens=true } }catch (err) {} } } if (infantil && noNens) infantil=false } } } //excepcions espanyoles def semiEsp def probablEsp = info.ProductionCountries.contains("ES") def espanyola = fromEspPlatform(plataforma) || (probablEsp && info.ProductionCountries.size()==1) if (probablEsp && info.ProductionCountries.size()>1) semiEsp = true def espListEx = [401545, 584427, 589203, 655187, 441614, 517327, 516856, 351097, 267579, 573150, 437036, 56812, 11429, 127864, 510318, 209251, 443585, 33273, 8881, 351809, 499547, 351145, 684471] def noEspListEx = [290859, 1562, 530915, 329718, 248842, 353979, 34186, 2395, 735129, 421792, 335984, 591789, 429, 26388, 18898, 266396, 85872, 352161, 43020, 339967, 446696, 38031] if (noEspListEx.contains(tmdbid)) { semiEsp=false espanyola=false } else if (espListEx.contains(tmdbid)) espanyola=true //asiaticas def asiatica = false if (info.ProductionCountries.size()>0) { def paisesAsiaticos = ["CN", "HK", "JP", "KP", "KR", "TH", "NP", "TW", "PH", "MO"] def matchP = paisesAsiaticos.intersect(info.ProductionCountries) if (matchP.size()==info.ProductionCountries.size()) asiatica=true } //tria if (tenimCat) ruta = ruta_cat else if (esDocu) ruta = ruta_docu else if (esAnime) ruta = ruta_anime else if (infantil) ruta = ruta_infantil else if (esAnimacion) ruta = ruta_animacion else if (asiatica) ruta = ruta_asiaticas else if (espanyola) ruta = ruta_esp else if (semiEsp) ruta = ruta_semiesp else if (y<1980) ruta = ruta_classic else if (y<2000) ruta = ruta_retro if (ruta==rutaOK && y>=2021) ruta = ruta_estrenos /********************************************/ /**************************************/ //if (errorNoGenero && !tenimCat && ruta!=ruta_classic && ruta!=ruta_retro && !espanyola && !semiEsp && !infantil && ruta!=ruta_estrenos ) // throw new Exception("[genero_no_especificado]") /*** RESULTADO FINAL ***/ def inicial='' def inicialsRequerides = ruta==rutaOK || ruta==ruta_retro || ruta==ruta_infantil if (inicialsActivades && inicialsRequerides) { inicial = getInicial() } def tmdb = " {tmdb-"+tmdbid+"}" def nomPrincipal = esFicheroMetadatos ? nombreWbloqueMediainfo+tipoMetadato : nombreWbloqueMediainfo def tracker = fn.find(/(?i)\bHDO(limpo)?\b/) def extras = tracker != null ? ' ['+tracker.replace("HDOlimpo", "HDO")+']' : '' def resultado = ruta + //directorios //nombre fichero inicial + localize.English.plex.name + '/' + nomPrincipal + extras + tmdb //(esFicheroMetadatos ? localize.Spanish.plex.name+tipoMetadato : nombreWbloqueMediainfo) return resultado } catch (err) { String str= err.getStackTrace().toString() def pattern = ( str =~ /groovy.(\d+)./ ) return " Error at line number = " + pattern[0][1] + ". more: "+str def rutaMotivoErr def msgErr = err.getMessage() if (msgErr=="[formato_fichero_noestarndar]" || msgErr=="[video_roto]") rutaMotivoErr="/fichero/" else if (msgErr=="[genero_no_especificado]" || msgErr=="[certificado_edad_no_especificado]") { rutaMotivoErr="/themoviedb/" } else if (msgErr.startsWith("[idioma_audio")) { rutaMotivoErr="/audio/" } else { def errSplitted = msgErr.split("\\-") return msgErr if (errSplitted==null) { rutaMotivoErr="/error_desconocido/" } else { def errType = errSplitted[0] if (errType=="[formato_audio_no_encontrado") rutaMotivoErr="/audio/" else if (errType.startsWith("[idioma_audio")) rutaMotivoErr="/idioma/" else { String str2= err.getStackTrace().toString() def pattern2 = ( str2 =~ /groovy.(\d+)./ ) return " Error at line number = " + pattern2[0][1] } } } def resultado = rutaKO + rutaMotivoErr + msgErr + '/' + localize.English.plex.name + '/' + fn return resultado }