From 729613409d9b3dbe0578991aa2c4e65313c05a27 Mon Sep 17 00:00:00 2001 From: root Date: Tue, 11 Apr 2023 05:02:43 +0200 Subject: [PATCH] first commit --- MaNGranA_Pelis(original).groovy | 544 +++++++++++++++++ README.md | 1 + docker/._DAV/MaNGranA_Pelis.groovy.dir | 0 docker/._DAV/MaNGranA_Pelis.groovy.pag | Bin 0 -> 1024 bytes .../@eaDir/MaNGranA_Pelis.groovy@SynoEAStream | Bin 0 -> 176 bytes ...NGranA_Pelis_Organizer.groovy@SynoEAStream | Bin 0 -> 176 bytes .../Mangrana_Series.groovy@SynoEAStream | Bin 0 -> 176 bytes ...Mangrana_Series_rename.groovy@SynoEAStream | Bin 0 -> 176 bytes docker/MaNGranA_Pelis.groovy | 550 ++++++++++++++++++ docker/MaNGranA_Pelis_Organizer.groovy | 277 +++++++++ docker/Mangrana_Series.groovy | 149 +++++ docker/Mangrana_Series_rename.groovy | 353 +++++++++++ 12 files changed, 1874 insertions(+) create mode 100755 MaNGranA_Pelis(original).groovy create mode 100644 README.md create mode 100755 docker/._DAV/MaNGranA_Pelis.groovy.dir create mode 100755 docker/._DAV/MaNGranA_Pelis.groovy.pag create mode 100755 docker/@eaDir/MaNGranA_Pelis.groovy@SynoEAStream create mode 100755 docker/@eaDir/MaNGranA_Pelis_Organizer.groovy@SynoEAStream create mode 100755 docker/@eaDir/Mangrana_Series.groovy@SynoEAStream create mode 100755 docker/@eaDir/Mangrana_Series_rename.groovy@SynoEAStream create mode 100755 docker/MaNGranA_Pelis.groovy create mode 100755 docker/MaNGranA_Pelis_Organizer.groovy create mode 100755 docker/Mangrana_Series.groovy create mode 100755 docker/Mangrana_Series_rename.groovy diff --git a/MaNGranA_Pelis(original).groovy b/MaNGranA_Pelis(original).groovy new file mode 100755 index 0000000..72ea656 --- /dev/null +++ b/MaNGranA_Pelis(original).groovy @@ -0,0 +1,544 @@ +//by @xeviff +/** RUTAS **/ +def inicialsActivades=true +def root = '/pelis/' +def rutaOK = root+"Pelis/" +def ruta = rutaOK +def ruta_docu = root+"Documentales/" +def ruta_anime = root+"Pelis_anime/" +def ruta_animacion = root+"Pelis_animacion/" +def ruta_infantil = root+"Pelis_infantiles/" +def ruta_cat = root+"Pelis_amb_cat/" +def ruta_cat_anime = root+"Pelis_cat_anime/" +def ruta_esp = root+"Pelis_esp/" +def ruta_semiesp = root+"Pelis_semiesp/" +def ruta_esp_retro = root+"Pelis_esp_retro/" +def ruta_esp_classic = root+"Pelis_esp_classic/" +def ruta_retro = root+"Pelis_retro/" +def ruta_estrenos = root+"Pelis_estrenos/" +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 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 +} +/**/ + +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 && bitrate >= 26000000) + ? "4K-UHDRemux" + : (peso > 15) + ? "4K-UHDRip" + : "4K-MicroUHD" + : (vf == '1080p') ? //1080 + (peso > 15 && bitrate >= 18000000) + ? "1080-BDRemux" + : (bitrate > 8000000) + ? "1080-HD" + : "1080-MicroHD" + : vf //720 + + def carpetaCalidad = calidad +'/' + + 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) 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 throw err + } + } + + if (audioDeclUndefined || (catalanAudios.isEmpty() && spanishAudios.isEmpty() && englishAudios.isEmpty() && otherAudios.isEmpty()) ) { + 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 + throw new Exception("[idioma_audio_solo_ingles]") + } else if (!otherAudios.isEmpty()) { //tenemos español + throw new Exception("[idioma_audio_marginal]") + } else { + throw new Exception("[idioma_audio_no_encontrado]") + } + /***********/ + + //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/ ? 'BDRemux' : + 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 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 + def 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/ ) + 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 -> '' + } + 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.round(1)+"Mbps").replace(/.0/,'') }catch(err){} + def myFps = ' FRvar' + try { myFps = ' '+(fps.round(1)+"fps").replace(/.0/,'') }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 + 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', 'PG.7', '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") + if (probablEsp && info.ProductionCountries.contains("US")) probablEsp=false + def espanyola = 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"] + 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 (espanyola) { + if (y<1980) ruta = ruta_esp_classic + else if (y<2000) ruta = ruta_esp_retro + else ruta = ruta_esp + } + else if (semiEsp) ruta = ruta_semiesp + else if (infantil) ruta = ruta_infantil + else if (esAnime) ruta = ruta_anime + else if (esAnimacion) ruta = ruta_animacion + else if (asiatica) { + ruta = ruta_asiaticas + carpetaCalidad='' + carpetaCodec='' + } + else if (y<1980) ruta = ruta_classic + else if (y<2000) ruta = ruta_retro + if (tenimCat && esAnime) ruta = ruta_cat_anime + if (ruta==rutaOK && y>=2021) ruta = ruta_estrenos + /********************************************/ + /**************************************/ + + if (errorNoGenero && !tenimCat && ruta!=ruta_classic && ruta!=ruta_retro && !espanyola && !semiEsp && !infantil && ruta!=ruta_esp_retro && ruta!=ruta_esp_classic && ruta!=ruta_estrenos ) + throw new Exception("[genero_no_especificado]") + + /*** RESULTADO FINAL ***/ + def inicial='' + def nomIngles = localize.English.n + def inicialsRequerides = (ruta==rutaOK || ruta==ruta_retro) && (carpetaCodec=='otrosCodecs/' || carpetaCodec=='x265/') && carpetaCalidad=='1080-MicroHD/' + if (inicialsActivades && inicialsRequerides) { + def ini0 = nomIngles[0].toUpperCase() + def ini1 = nomIngles[1].toUpperCase() + def iniClear = ini0.replaceAll(/[¡¿'#*\(]/,ini1) + inicial = iniClear.replaceAll(/[0-9]/,'zNum')+'/' + } + 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 + carpetaCodec + carpetaCalidad + //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 + '/' + fn + + return resultado +} \ No newline at end of file diff --git a/README.md b/README.md new file mode 100644 index 0000000..5670a6f --- /dev/null +++ b/README.md @@ -0,0 +1 @@ +# filebot_presets diff --git a/docker/._DAV/MaNGranA_Pelis.groovy.dir b/docker/._DAV/MaNGranA_Pelis.groovy.dir new file mode 100755 index 0000000..e69de29 diff --git a/docker/._DAV/MaNGranA_Pelis.groovy.pag b/docker/._DAV/MaNGranA_Pelis.groovy.pag new file mode 100755 index 0000000000000000000000000000000000000000..130d0aa038ff147bb9f5a36ebe82053389c3f959 GIT binary patch literal 1024 zcmeH@F$%&k6hJ?ICwFIa0EL*gAlZUdLCh9(u4#&awt*x)g{SZ)9>T*o3RS_?S>OJ6 z@J4XQ8(#5(XRJ|Sh7%kk{P`dF;RCdXQJC|CZ4XkFVY iLx4dp_8dCj@}N(qDZ;F=+PmPYIMc4-AXiG{LWu`i4@RN@ literal 0 HcmV?d00001 diff --git a/docker/@eaDir/MaNGranA_Pelis.groovy@SynoEAStream b/docker/@eaDir/MaNGranA_Pelis.groovy@SynoEAStream new file mode 100755 index 0000000000000000000000000000000000000000..91a0314ede2dd2a4c13da08542ef6559a344990e GIT binary patch literal 176 zcmZQz6=P>$Vqox1Ojhs@R)|o50+1L3ClDI}aUBqY_#1$j2;dkJ5(HHS(y;)D1)zKw z#Rz090AirHRC0c$Vqox1Ojhs@R)|o50+1L3ClDI}aUBqY_#1$j2;dkJ5(HHS(y;)D1)zKw z#Rz090AirHRC0c$Vqox1Ojhs@R)|o50+1L3ClDI}aUBqY_#1$j2;dkJ5(HHS(y;)D1)zKw z#Rz090AirHRC0c$Vqox1Ojhs@R)|o50+1L3ClDI}aUBqY_#1$j2;dkJ5(HHS(y;)D1)zKw z#Rz090AirHRC0ccurrentValue) { + 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 && bitrate >= 26000000) + ? "4K-UHDRemux" + : (peso > 15) + ? "4K-UHDRip" + : "4K-MicroUHD" + : (vf == '1080p') ? //1080 + (peso > 15 && bitrate >= 18000000) + ? "1080-BDRemux" + : (bitrate > 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.round(1)+"Mbps").replace(/.0/,'') }catch(err){} + def myFps = ' FRvar' + try { myFps = ' '+(fps.round(1)+"fps").replace(/.0/,'') }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', 'PG.7', '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"] + 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 (espanyola) ruta = ruta_esp + else if (semiEsp) ruta = ruta_semiesp + 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 (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 +} \ No newline at end of file diff --git a/docker/MaNGranA_Pelis_Organizer.groovy b/docker/MaNGranA_Pelis_Organizer.groovy new file mode 100755 index 0000000..ec54866 --- /dev/null +++ b/docker/MaNGranA_Pelis_Organizer.groovy @@ -0,0 +1,277 @@ +//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_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/" +/**********/ + + + +/* 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 +} + +try { //empieza el script + + if (ext!="mkv" && ext!="avi" && ext!="mp4") { + throw new Exception("[formato_fichero_noestarndar]") + } + try { + video + } catch (e) { + throw new Exception("[video_roto]") + } + /********************************/ + + + + /** 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) 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 throw err + } + } + + if (audioDeclUndefined || (catalanAudios.isEmpty() && spanishAudios.isEmpty() && englishAudios.isEmpty() && otherAudios.isEmpty()) ) { + throw new Exception("[idioma_audio_no_definido]") + } + def tenimCat=false + if (!catalanAudios.isEmpty()) { //tenim català + tenimCat=true + def tenimEsp = !spanishAudios.isEmpty() + } else if (!spanishAudios.isEmpty()) { //tenemos español + + } else if (!englishAudios.isEmpty()) { + throw new Exception("[idioma_audio_solo_ingles]") + } else if (!otherAudios.isEmpty()) { + throw new Exception("[idioma_audio_marginal]") + } else { + throw new Exception("[idioma_audio_no_encontrado]") + } + /***********/ + + + /**************************************/ + /**** 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', 'PG.7', '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") + if (probablEsp && info.ProductionCountries.contains("US")) probablEsp=false + def espanyola = 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"] + def matchP = paisesAsiaticos.intersect(info.ProductionCountries) + if (matchP.size()==info.ProductionCountries.size()) asiatica=true + } + + //tria + if (esDocu) ruta = ruta_docu + else if (espanyola) ruta = ruta_esp + else if (semiEsp) ruta = ruta_semiesp + 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 (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_esp_retro && ruta!=ruta_esp_classic && 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 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 + '/' + fn + + 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 + '/' + fn + + return resultado +} \ No newline at end of file diff --git a/docker/Mangrana_Series.groovy b/docker/Mangrana_Series.groovy new file mode 100755 index 0000000..58456e8 --- /dev/null +++ b/docker/Mangrana_Series.groovy @@ -0,0 +1,149 @@ + +def server=true +def root = '/series/' +def rutaSeries = root+'NSeries/' +def ruta_docu = root+'Series_docu/' +def ruta_animacion = root+'Series_animacion/' +def ruta_anime = root+'Series_anime/' +def ruta_antiguas = root+'Series_antiguas/' +def ruta_esp = root+'Series_esp' +def ruta_teen = root+'Series_familiar' +def ruta_infantil = root+'Series_infantil' +def ruta_programastv = root+'programas_tv' + +def rutaKO = root+'error/' +def ruta = rutaSeries + + +/* otras funciones */ +def tieneGeneroAnimacion (generos) { + for (genero in generos) { + if (genero =~ /Anima[c|t]i\p{L}n/) + return true + } + return false +} +def tieneGeneroAnime (generos) { + for (genero in generos) { + if (genero =~ /Anime/) + 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 tieneGeneroReality (generos) { + for (genero in generos) { + if (genero =~ /Reality/) + return true + } + return false +} +/**/ + + +try { //empieza el script + + try{ + media + } catch (err) {throw new Exception("[no_media]")} + + + /**************************************/ + /**** Carpeta / tipo contenido *******/ + def generes + def errorNoGenero=false + try {generes=genres} catch (err) {errorNoGenero=true} + def certificacio + try {certificacio=certification} catch (err) {} + def esDocu = tieneGeneroDocumental(generes) + def esAnime = anime || tieneGeneroAnime(generes) + def esAnimacion = tieneGeneroAnimacion(generes) + def esTeen = tieneGeneroFamilia(generes) && (certificacio==null || certificacio =~ /TV-14|TV-P?G/) + //return certificacio + " - " + generes + " - so: " + esTeen + def esInfantil = esAnimacion && certificacio =~ /TV-Y|TV-Y7|TV-P?G/ + def esReality = tieneGeneroReality(generes) + //esp? + def esEsp=false + def spanishNetwork = info.Network.find(/(?i)\bTVE\b|\bmovistar\b|\bAtresmedia\b|\bcanal 9\b|\bPlayz\b|\bATRES\b|\bETB1\b|\bTV3\b|\btelecinco\b|\bcanal+\b|\bgalicia\b|\bfox españa\b|\blasexta\b|\bantena 3\b/ ) + if (spanishNetwork!=null) esEsp=true + //tria + /*if (tenimCat) ruta = ruta_cat + else */if (esDocu) ruta = ruta_docu + else if (esReality) ruta = ruta_programastv + else if (esAnime) ruta = ruta_anime + else if (esInfantil) ruta = ruta_infantil + else if (esAnimacion) ruta = ruta_animacion + else if (esEsp) ruta = ruta_esp + else if (y < 1990) ruta = ruta_antiguas + else if (esTeen) ruta = ruta_teen + /****************************************/ + /****************************************/ + + /****************************/ + /**** Nombre de fichero *******/ + + def nombreSerie = '/' + localize.English.ny + '/' + def temporada = episode.special ? + 'Specials'+'/' : + 'Temporada '+ s.pad(2) + '/' + + /****************************/ + /**** RUTA FINAL *******/ + + def resultado = ruta + nombreSerie + temporada + fn + return resultado + + +} catch (err) { + + + String str= err.getStackTrace().toString() + def pattern = ( str =~ /groovy.(\d+)./ ) + return " Error at line number = " + pattern[0][1] + + + def rutaMotivoErr + def msgErr = err.getMessage() + if (msgErr=="[formato_fichero_noestarndar]" || msgErr=="[video_roto]" || msgErr=="[no_media]") + rutaMotivoErr="/fichero/" + else if (msgErr=="[genero_no_especificado]" || msgErr=="[certificado_edad_no_especificado]") { + rutaMotivoErr="/themoviedb/" + } else if (msgErr.startsWith("[idioma_audio")) { + rutaMotivoErr="/audio/" + } else if (msgErr.startsWith("[bitrate_demasiado_alto]")) { + rutaMotivoErr="/bitrate/" + } else { + def errSplitted = msgErr.split("\\-") + if (errSplitted==null) { + rutaMotivoErr="/error_desconocido/" + } else { + return msgErr + def errType = errSplitted[0] + if (errType=="[formato_audio_no_encontrado") + rutaMotivoErr="/audio/" + else if (errType.startsWith("[idioma_audio")) + rutaMotivoErr="/idioma/" + else { + rutaMotivoErr="/error_desconocido/" + msgErr = "[error_inesperado]" + } + } + } + + def resultado = rutaKO + rutaMotivoErr + msgErr + '/' + fn + + return resultado +} \ No newline at end of file diff --git a/docker/Mangrana_Series_rename.groovy b/docker/Mangrana_Series_rename.groovy new file mode 100755 index 0000000..a0871d6 --- /dev/null +++ b/docker/Mangrana_Series_rename.groovy @@ -0,0 +1,353 @@ + +def server=true +def root = '/series/' +def rutaSeries = root+'NSeries/' +def ruta_docu = root+'Series_docu/' +def ruta_animacion = root+'Series_animacion/' +def ruta_anime = root+'Series_anime/' +def ruta_antiguas = root+'Series_antiguas/' +def ruta_esp = root+'Series_esp' +def ruta_teen = root+'Series_familiar' +def ruta_infantil = root+'Series_infantil' +def ruta_programastv = root+'programas_tv' + +def rutaKO = root+'error/' +def ruta = rutaSeries + +def ignorarAudioNoDef = true + +/** 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", "HE-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 = audio2Print.Language_String.replace("Catalan","Cat").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 tieneGeneroAnime (generos) { + for (genero in generos) { + if (genero =~ /Anime/) + 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 tieneGeneroReality (generos) { + for (genero in generos) { + if (genero =~ /Reality/) + return true + } + return false +} +def normalitzarText(txt) { + return txt.replaceAll(':','.').replaceAll('\\?','¿').replaceAll('\\"','-') +} +/**/ + + +try { //empieza el script + + try{ + media + } catch (err) {throw new Exception("[no_media]")} + + /** Audio (ejecución) **/ + def catalanAudios=[] + def spanishAudios=[] + def englishAudios=[] + def otherAudios=[] + def audioDeclUndefined=false + def audiosFantasma='' + for (item in audio) { + def idioma + try { + idioma = item.Language_String + if (idioma==null) 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 + audiosFantasma=' '+audiosFantasma+item.Title + } catch (ex) {throw new Exception("[idioma_audio_no_definido]")} + } else throw err + } + } + def audioNodef = false + if (!ignorarAudioNoDef) { + if (audioDeclUndefined || (catalanAudios.isEmpty() && spanishAudios.isEmpty() && englishAudios.isEmpty() && otherAudios.isEmpty()) ) { + audioNodef = false + throw new Exception("[idioma_audio_no_definido]") + } + } + if (!audioNodef) { + 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 + throw new Exception("[idioma_audio_solo_ingles]") + } else if (!otherAudios.isEmpty()) { //tenemos español + throw new Exception("[idioma_audio_marginal]") + } else { + throw new Exception("[idioma_audio_no_encontrado]") + } + } else { + bloqueAudio = "NoDef" + } + /***********/ + + /** Codec Vídeo: en carpeta y en nombre fichero **/ + def codecVideo = (any{vc}{0} =~ /HEVC|265|ATEME/ ) ? 'HEVC' : + (any{vc}{0} =~ /264/) ? 'AVC' : vc + /**************/ + + /** Formato distribución **/ + formato_distribucion = + fn=~/(?i)\bblu.?ray\b/ ? 'BDRip' : + fn=~/(?i)\bBDrip\b/ ? 'BDRip' : + fn=~/(?i)\bDVD.?RIP\b/ ? 'DVDRip' : + fn=~/(?i)\bHDiTunes\b/ ? 'HDiTunes' : + fn=~/(?i)\bTV.?RIP\b/ ? 'TVRip' : + fn=~/(?i)\bahdtv\b/ ? 'AHDTV' : + fn=~/(?i)\bWEB.?Screener\b/ ? 'WEB-SRC' : + 'no_encontrado' + + def esWEB_DL=false + if (formato_distribucion=='no_encontrado') { + esWEB_DL = fn=~/(?i)\bWEB.??(D.?|RIP)\b/ //WEB-DL o WEB-RIP (todo junto o con punto/guión/etc) + + if (esWEB_DL) { + def web_x = fn=~/(?i)\bWEB.?D.?\b/ ? 'WEB-DL' : 'WEB-RIP' //guardar el que es + def plataforma = fn.find( //coge el contenido que encaja + /(?i)\bSATRIP\b|\bDVB\b|\bFLXL\b|\bAMZN?\b|\bAMNZ?\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|\bDNSP\b|\bMVPLUS\b|\bM\+\b|\bAPTV\b|\bAMC\b/ ) + if (plataforma!=null) plataforma = plataforma.replace("MVPLUS","MV+").replace("AMNZ", "AMZN").replace("DSNY", "DSN").replace("DSNP", "DSN") + 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 + } + } + } + if (formato_distribucion=='no_encontrado') formato_distribucion=''; + if (formato_distribucion!='') formato_distribucion=' '+formato_distribucion + /*****************************/ + + /**** Profundidad de color */ + def profundidadColor='' + try{profundidadColor = bitdepth+"bits " } catch(err){} + /**************************/ + + /**** Profundidad vídeo ****/ + def myBitrate = 'noBRdef' + try{ myBitrate = (mbps.round(1)+"Mbps").replace(/.0/,'') }catch(err){} + //if (bitrate >= 10000000) throw new Exception("[bitrate_demasiado_alto]") + def infoBitrate = mbps < 11 ? myBitrate + : mbps < 15 ? myBitrate+' (BITRATE_S)' + : mbps < 20 ? myBitrate+' (BITRATE_M)' + : mbps < 25 ? myBitrate+' (BITRATE_L)' + : myBitrate+' (BITRATE_XL)' + def myFps = ' FRvar' + try { myFps = ' '+(fps.round(1)+"fps").replace(/.0/,'') }catch(err){} + /************ ***************/ + + + /**************************************/ + /**** Carpeta / tipo contenido *******/ + def generes + def errorNoGenero=false + try {generes=genres} catch (err) {errorNoGenero=true} + def certificacio + try {certificacio=certification} catch (err) {} + def esDocu = tieneGeneroDocumental(generes) + def esAnime = anime || tieneGeneroAnime(generes) + def esAnimacion = tieneGeneroAnimacion(generes) + def esTeen = tieneGeneroFamilia(generes) && (certificacio==null || certificacio =~ /TV-14|TV-P?G/) + //return certificacio + " - " + generes + " - so: " + esTeen + def esInfantil = esAnimacion && certificacio =~ /TV-Y|TV-Y7|TV-P?G/ + def esReality = tieneGeneroReality(generes) + //esp? + def esEsp=false + def spanishNetwork + try{ spanishNetwork = info.Network.find(/(?i)\bTVE\b|\bmovistar\b|\bAtresmedia\b|\bcanal 9\b|\bPlayz\b|\bATRES\b|\bETB1\b|\bTV3\b|\btelecinco\b|\bcanal+\b|\bgalicia\b|\bfox españa\b|\blasexta\b|\bantena 3\b/ )} catch(e){} + if (spanishNetwork!=null) esEsp=true + //tria + /*if (tenimCat) ruta = ruta_cat + else */if (esDocu) ruta = ruta_docu + else if (esReality) ruta = ruta_programastv + else if (esAnime) ruta = ruta_anime + else if (esInfantil) ruta = ruta_infantil + else if (esAnimacion) ruta = ruta_animacion + else if (esEsp) ruta = ruta_esp + else if (y < 1990) ruta = ruta_antiguas + else if (esTeen) ruta = ruta_teen + /****************************************/ + /****************************************/ + + /****************************/ + /**** Nombre de fichero *******/ + def cuaTvdb = " {tvdb-"+id+"}" + def pathNombreSerie = '/' + normalitzarText(localize.English.ny) + cuaTvdb + '/' + def temporada = episode.special ? + 'Specials'+'/' : + 'Temporada '+ s.pad(2) + '/' + + def volemInicials = false + def nomIngles = localize.English.n + def titol='' + def ini0 = nomIngles[0].toUpperCase() + def ini1 = nomIngles[1].toUpperCase() + def iniClear = ini0.replaceAll(/[¡¿'#*\(]/,ini1) + def inicial = volemInicials ? ruta==rutaSeries ? iniClear.replaceAll(/[0-9]/,'0-9') + '/' : '' : '' + + try { + def titolCapitol = normalitzarText(localize.Spanish.t) + titol = ' - ' + titolCapitol + } catch (err) { /*nada*/ } + + def nombreSerie = normalitzarText(localize.Spanish.ny) + def nombreArchivo = nombreSerie + ' - ' + s00e00 + titol + + def resolucion = ['480p', '576p', '360p', '240p'].contains(vf) ? 'SD' //SD + : (vf == '2160p') ? //4K + '4K' + : //1080 o 720 + vf + + def tracker = fn.find(/(?i)\bHDO(limpo)?\b|\bredbits\b/) + def cuaTracker = tracker != null ? ' ['+tracker.replace("HDOlimpo", "HDO")+']' : '' + + + /****************************/ + /**** RUTA FINAL *******/ + + def resultado = ruta + inicial + pathNombreSerie + temporada + nombreArchivo + ' [' + codecVideo +' '+ resolucion + formato_distribucion+']['+profundidadColor+infoBitrate+myFps+']'+' ['+bloqueAudio+']' + cuaTracker + return resultado + + +} catch (err) { + + /* + String str= err.getStackTrace().toString() + def pattern = ( str =~ /groovy.(\d+)./ ) + return " Error at line number = " + pattern[0][1] + */ + + def rutaMotivoErr + def msgErr = err.getMessage() + if (msgErr=="[formato_fichero_noestarndar]" || msgErr=="[video_roto]" || msgErr=="[no_media]") + rutaMotivoErr="/fichero/" + else if (msgErr=="[genero_no_especificado]" || msgErr=="[certificado_edad_no_especificado]") { + rutaMotivoErr="/themoviedb/" + } else if (msgErr.startsWith("[idioma_audio")) { + rutaMotivoErr="/audio/" + } else if (msgErr.startsWith("[bitrate_demasiado_alto]")) { + rutaMotivoErr="/bitrate/" + } else { + def errSplitted = msgErr.split("\\-") + if (errSplitted==null) { + rutaMotivoErr="/error_desconocido/" + } else { + return msgErr + def errType = errSplitted[0] + if (errType=="[formato_audio_no_encontrado") + rutaMotivoErr="/audio/" + else if (errType.startsWith("[idioma_audio")) + rutaMotivoErr="/idioma/" + else { + rutaMotivoErr="/error_desconocido/" + msgErr = "[error_inesperado]" + } + } + } + def cuaTvdb = " {tvdb-"+id+"}" + def pathNombreSerieErr = '/' + normalitzarText(localize.English.ny) + cuaTvdb + '/' + + def resultado = rutaKO + rutaMotivoErr + msgErr + '/' + pathNombreSerieErr + fn + + return resultado +} \ No newline at end of file