2012-07-28 06:21:30 -04:00
|
|
|
|
|
|
|
import static net.sourceforge.filebot.WebServices.*
|
2013-02-26 14:40:24 -05:00
|
|
|
import static groovy.json.StringEscapeUtils.*
|
2012-07-28 06:21:30 -04:00
|
|
|
|
2012-07-30 08:05:18 -04:00
|
|
|
import groovy.xml.*
|
|
|
|
import net.sourceforge.filebot.mediainfo.*
|
|
|
|
|
|
|
|
|
2012-07-28 06:21:30 -04:00
|
|
|
/**
|
|
|
|
* XBMC helper functions
|
|
|
|
*/
|
2013-02-28 10:48:51 -05:00
|
|
|
def scanVideoLibrary(host, port) {
|
|
|
|
_guarded {
|
|
|
|
telnet(host, port) { writer, reader ->
|
|
|
|
writer.println("""{"jsonrpc":"2.0","method":"VideoLibrary.Scan","id":1}""")
|
|
|
|
}
|
|
|
|
}
|
2013-02-26 14:40:24 -05:00
|
|
|
}
|
|
|
|
|
2013-02-28 10:48:51 -05:00
|
|
|
def showNotification(host, port, title, message, image) {
|
|
|
|
_guarded {
|
|
|
|
telnet(host, port) { writer, reader ->
|
|
|
|
writer.println("""{"jsonrpc":"2.0","method":"GUI.ShowNotification","params":{"title":"${escapeJavaScript(title)}","message":"${escapeJavaScript(message)}", "image":"${escapeJavaScript(image)}"},"id":1}""")
|
|
|
|
}
|
2012-04-29 01:28:38 -04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2012-07-28 06:21:30 -04:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Plex helpers
|
|
|
|
*/
|
2012-12-12 14:23:59 -05:00
|
|
|
def refreshPlexLibrary(server, port = 32400) {
|
2012-07-30 08:05:18 -04:00
|
|
|
_guarded {
|
2012-12-12 14:23:59 -05:00
|
|
|
new URL("http://$server:$port/library/sections/all/refresh").get()
|
2012-07-28 06:21:30 -04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
* TheTVDB artwork/nfo helpers
|
|
|
|
*/
|
2013-02-06 10:12:19 -05:00
|
|
|
def fetchSeriesBanner(outputFile, series, bannerType, bannerType2, season, override, locale) {
|
|
|
|
if (outputFile.exists() && !override) {
|
2013-03-06 03:34:43 -05:00
|
|
|
_log.finest "Banner already exists: $outputFile"
|
2013-02-06 10:12:19 -05:00
|
|
|
return outputFile
|
|
|
|
}
|
|
|
|
|
2012-04-29 01:28:38 -04:00
|
|
|
// select and fetch banner
|
|
|
|
def banner = [locale, null].findResult { TheTVDB.getBanner(series, [BannerType:bannerType, BannerType2:bannerType2, Season:season, Language:it]) }
|
|
|
|
if (banner == null) {
|
2013-03-06 03:34:43 -05:00
|
|
|
_log.finest "Banner not found: $outputFile / $bannerType:$bannerType2"
|
2012-04-29 01:28:38 -04:00
|
|
|
return null
|
|
|
|
}
|
2013-03-06 03:34:43 -05:00
|
|
|
_log.finest "Fetching $outputFile => $banner"
|
2012-04-29 01:28:38 -04:00
|
|
|
return banner.url.saveAs(outputFile)
|
|
|
|
}
|
|
|
|
|
2013-02-06 10:12:19 -05:00
|
|
|
def fetchSeriesFanart(outputFile, series, type, season, override, locale) {
|
|
|
|
if (outputFile.exists() && !override) {
|
2013-03-06 03:34:43 -05:00
|
|
|
_log.finest "Fanart already exists: $outputFile"
|
2013-02-06 10:12:19 -05:00
|
|
|
return outputFile
|
|
|
|
}
|
|
|
|
|
2012-07-28 06:21:30 -04:00
|
|
|
def fanart = [locale, null].findResult{ lang -> FanartTV.getSeriesArtwork(series.seriesId).find{ type == it.type && (season == null || season == it.season) && (lang == null || lang == it.language) }}
|
|
|
|
if (fanart == null) {
|
2013-03-06 03:34:43 -05:00
|
|
|
_log.finest "Fanart not found: $outputFile / $type"
|
2012-07-28 06:21:30 -04:00
|
|
|
return null
|
|
|
|
}
|
2013-03-06 03:34:43 -05:00
|
|
|
_log.finest "Fetching $outputFile => $fanart"
|
2012-07-28 06:21:30 -04:00
|
|
|
return fanart.url.saveAs(outputFile)
|
|
|
|
}
|
|
|
|
|
2013-02-06 10:12:19 -05:00
|
|
|
def fetchSeriesNfo(outputFile, seriesInfo, override, locale) {
|
|
|
|
def i = seriesInfo
|
|
|
|
XML {
|
|
|
|
tvshow {
|
|
|
|
title(i.name)
|
|
|
|
sorttitle([i.name, i.firstAired as String].findAll{ it?.length() > 0 }.join('::'))
|
|
|
|
year(i.firstAired?.year)
|
|
|
|
rating(i.rating)
|
|
|
|
votes(i.ratingCount)
|
|
|
|
plot(i.overview)
|
|
|
|
runtime(i.runtime)
|
|
|
|
mpaa(i.contentRating)
|
|
|
|
id(i.id)
|
|
|
|
episodeguide {
|
|
|
|
url(cache:"${i.id}.xml", "http://www.thetvdb.com/api/1D62F2F90030C444/series/${i.id}/all/${locale.language}.zip")
|
|
|
|
}
|
|
|
|
genre(i.genres?.size() > 0 ? i.genres[0] : null)
|
|
|
|
thumb(i.bannerUrl)
|
|
|
|
premiered(i.firstAired)
|
|
|
|
status(i.status)
|
|
|
|
studio(i.network)
|
|
|
|
i.actors?.each{ n ->
|
|
|
|
actor {
|
|
|
|
name(n)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2012-04-29 01:28:38 -04:00
|
|
|
.saveAs(outputFile)
|
|
|
|
}
|
|
|
|
|
2013-02-06 10:12:19 -05:00
|
|
|
def fetchSeriesArtworkAndNfo(seriesDir, seasonDir, series, season, override = false, locale = _args.locale) {
|
2012-07-30 08:05:18 -04:00
|
|
|
_guarded {
|
2012-04-29 01:28:38 -04:00
|
|
|
// fetch nfo
|
2013-02-06 10:12:19 -05:00
|
|
|
def seriesInfo = TheTVDB.getSeriesInfo(series, locale)
|
|
|
|
fetchSeriesNfo(seriesDir['tvshow.nfo'], seriesInfo, override, locale)
|
2012-04-29 01:28:38 -04:00
|
|
|
|
|
|
|
// fetch series banner, fanart, posters, etc
|
2013-02-06 10:12:19 -05:00
|
|
|
["680x1000", null].findResult{ fetchSeriesBanner(seriesDir['poster.jpg'], series, "poster", it, null, override, locale) }
|
|
|
|
["graphical", null].findResult{ fetchSeriesBanner(seriesDir['banner.jpg'], series, "series", it, null, override, locale) }
|
2012-04-29 01:28:38 -04:00
|
|
|
|
|
|
|
// fetch highest resolution fanart
|
2013-02-06 10:12:19 -05:00
|
|
|
["1920x1080", "1280x720", null].findResult{ fetchSeriesBanner(seriesDir["fanart.jpg"], series, "fanart", it, null, override, locale) }
|
2012-04-29 01:28:38 -04:00
|
|
|
|
|
|
|
// fetch season banners
|
|
|
|
if (seasonDir != seriesDir) {
|
2013-02-06 10:12:19 -05:00
|
|
|
fetchSeriesBanner(seasonDir["poster.jpg"], series, "season", "season", season, override, locale)
|
|
|
|
fetchSeriesBanner(seasonDir["banner.jpg"], series, "season", "seasonwide", season, override, locale)
|
2012-04-29 01:28:38 -04:00
|
|
|
}
|
2012-07-28 06:21:30 -04:00
|
|
|
|
|
|
|
// fetch fanart
|
2013-02-06 10:12:19 -05:00
|
|
|
fetchSeriesFanart(seriesDir['clearart.png'], series, 'clearart', null, override, locale)
|
|
|
|
fetchSeriesFanart(seriesDir['logo.png'], series, 'clearlogo', null, override, locale)
|
|
|
|
fetchSeriesFanart(seriesDir['landscape.jpg'], series, 'tvthumb', null, override, locale)
|
2012-07-28 06:21:30 -04:00
|
|
|
|
|
|
|
// fetch season fanart
|
|
|
|
if (seasonDir != seriesDir) {
|
2013-02-06 10:12:19 -05:00
|
|
|
fetchSeriesFanart(seasonDir['landscape.jpg'], series, 'seasonthumb', season, override, locale)
|
2012-07-28 06:21:30 -04:00
|
|
|
}
|
2012-04-29 01:28:38 -04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
2012-07-28 06:21:30 -04:00
|
|
|
/**
|
|
|
|
* TheMovieDB artwork/nfo helpers
|
|
|
|
*/
|
2013-02-06 10:12:19 -05:00
|
|
|
def fetchMovieArtwork(outputFile, movieInfo, category, override, locale) {
|
|
|
|
if (outputFile.exists() && !override) {
|
2013-03-06 03:34:43 -05:00
|
|
|
_log.finest "Artwork already exists: $outputFile"
|
2013-02-06 10:12:19 -05:00
|
|
|
return outputFile
|
|
|
|
}
|
|
|
|
|
2012-04-29 01:28:38 -04:00
|
|
|
// select and fetch artwork
|
2012-07-24 13:44:54 -04:00
|
|
|
def artwork = TheMovieDB.getArtwork(movieInfo.id as String)
|
2013-02-06 10:12:19 -05:00
|
|
|
def selection = [locale.language, 'en', null].findResult{ l -> artwork.find{ (l == it.language || l == null) && it.category == category } }
|
2012-07-24 13:44:54 -04:00
|
|
|
if (selection == null) {
|
2013-03-06 03:34:43 -05:00
|
|
|
_log.finest "Artwork not found: $outputFile"
|
2012-04-29 01:28:38 -04:00
|
|
|
return null
|
|
|
|
}
|
2013-03-06 03:34:43 -05:00
|
|
|
_log.finest "Fetching $outputFile => $selection"
|
2012-07-24 13:44:54 -04:00
|
|
|
return selection.url.saveAs(outputFile)
|
2012-04-29 01:28:38 -04:00
|
|
|
}
|
|
|
|
|
2013-02-06 10:12:19 -05:00
|
|
|
def fetchAllMovieArtwork(outputFolder, movieInfo, category, override, locale) {
|
2012-12-16 08:26:39 -05:00
|
|
|
// select and fetch artwork
|
|
|
|
def artwork = TheMovieDB.getArtwork(movieInfo.id as String)
|
2013-02-06 10:12:19 -05:00
|
|
|
def selection = [locale.language, 'en', null].findResults{ l -> artwork.findAll{ (l == it.language || l == null) && it.category == category } }.flatten().findAll{ it?.url }.unique()
|
2012-12-16 08:26:39 -05:00
|
|
|
if (selection == null) {
|
2013-03-06 03:34:43 -05:00
|
|
|
_log.finest "Artwork not found: $outputFolder"
|
2012-12-16 08:26:39 -05:00
|
|
|
return null
|
|
|
|
}
|
|
|
|
selection.eachWithIndex{ s, i ->
|
|
|
|
def outputFile = new File(outputFolder, "$category-${(i+1).pad(2)}.jpg")
|
2013-02-06 10:12:19 -05:00
|
|
|
if (outputFile.exists() && !override) {
|
2013-03-06 03:34:43 -05:00
|
|
|
_log.finest "Artwork already exists: $outputFile"
|
2013-02-06 10:12:19 -05:00
|
|
|
} else {
|
2013-03-06 03:34:43 -05:00
|
|
|
_log.finest "Fetching $outputFile => $s"
|
2013-02-06 10:12:19 -05:00
|
|
|
s.url.saveAs(outputFile)
|
|
|
|
}
|
2012-12-16 08:26:39 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-02-06 10:12:19 -05:00
|
|
|
def fetchMovieFanart(outputFile, movieInfo, type, diskType, override, locale) {
|
|
|
|
if (outputFile.exists() && !override) {
|
2013-03-06 03:34:43 -05:00
|
|
|
_log.finest "Fanart already exists: $outputFile"
|
2013-02-06 10:12:19 -05:00
|
|
|
return outputFile
|
|
|
|
}
|
|
|
|
|
2012-07-28 06:21:30 -04:00
|
|
|
def fanart = [locale, null].findResult{ lang -> FanartTV.getMovieArtwork(movieInfo.id).find{ type == it.type && (diskType == null || diskType == it.diskType) && (lang == null || lang == it.language) }}
|
|
|
|
if (fanart == null) {
|
2013-03-06 03:34:43 -05:00
|
|
|
_log.finest "Fanart not found: $outputFile / $type"
|
2012-07-28 06:21:30 -04:00
|
|
|
return null
|
|
|
|
}
|
2013-03-06 03:34:43 -05:00
|
|
|
_log.finest "Fetching $outputFile => $fanart"
|
2012-07-28 06:21:30 -04:00
|
|
|
return fanart.url.saveAs(outputFile)
|
|
|
|
}
|
|
|
|
|
2013-02-06 10:12:19 -05:00
|
|
|
def fetchMovieNfo(outputFile, movieInfo, movieFile, override) {
|
|
|
|
def i = movieInfo
|
|
|
|
def mi = _guarded{ movieFile ? MediaInfo.snapshot(movieFile) : null }
|
|
|
|
XML {
|
|
|
|
movie {
|
|
|
|
title(i.name)
|
|
|
|
originaltitle(i.originalName)
|
|
|
|
sorttitle([i.collection, i.name, i.released as String].findAll{ it?.length() > 0 }.join('::'))
|
|
|
|
set(i.collection)
|
|
|
|
year(i.released?.year)
|
|
|
|
rating(i.rating)
|
|
|
|
votes(i.votes)
|
|
|
|
mpaa(i.certification)
|
|
|
|
id("tt" + (i.imdbId ?: 0).pad(7))
|
|
|
|
plot(i.overview)
|
|
|
|
tagline(i.tagline)
|
|
|
|
runtime(i.runtime)
|
|
|
|
genre(i.genres?.size() > 0 ? i.genres[0] : null)
|
|
|
|
director(i.director)
|
|
|
|
i.cast?.each{ a ->
|
|
|
|
actor {
|
|
|
|
name(a.name)
|
|
|
|
role(a.character)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
fileinfo {
|
|
|
|
streamdetails {
|
|
|
|
mi?.each { kind, streams ->
|
|
|
|
def section = kind.toString().toLowerCase()
|
|
|
|
streams.each { s ->
|
|
|
|
if (section == 'video') {
|
|
|
|
video {
|
|
|
|
codec((s.'Encoded_Library/Name' ?: s.'CodecID/Hint' ?: s.'Format').replaceAll(/[ ].+/, '').trim())
|
|
|
|
aspect(s.'DisplayAspectRatio')
|
|
|
|
width(s.'Width')
|
|
|
|
height(s.'Height')
|
|
|
|
}
|
2012-07-30 08:05:18 -04:00
|
|
|
}
|
2013-02-06 10:12:19 -05:00
|
|
|
if (section == 'audio') {
|
|
|
|
audio {
|
|
|
|
codec((s.'CodecID/Hint' ?: s.'Format').replaceAll(/\p{Punct}/, '').trim())
|
|
|
|
language(s.'Language/String3')
|
|
|
|
channels(s.'Channel(s)')
|
|
|
|
}
|
2012-07-30 08:05:18 -04:00
|
|
|
}
|
2013-02-06 10:12:19 -05:00
|
|
|
if (section == 'text') {
|
|
|
|
subtitle {
|
|
|
|
language(s.'Language/String3')
|
|
|
|
}
|
2012-07-30 08:05:18 -04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2013-02-06 10:12:19 -05:00
|
|
|
imdb(id:"tt" + (i.imdbId ?: 0).pad(7), "http://www.imdb.com/title/tt" + (i.imdbId ?: 0).pad(7))
|
|
|
|
tmdb(id:i.id, "http://www.themoviedb.org/movie/${i.id}")
|
2012-07-30 08:05:18 -04:00
|
|
|
}
|
|
|
|
}
|
2012-04-29 01:28:38 -04:00
|
|
|
.saveAs(outputFile)
|
|
|
|
}
|
|
|
|
|
2013-02-06 10:12:19 -05:00
|
|
|
def fetchMovieArtworkAndNfo(movieDir, movie, movieFile = null, fetchAll = false, override = false, locale = _args.locale) {
|
2012-07-30 08:05:18 -04:00
|
|
|
_guarded {
|
2012-04-29 01:28:38 -04:00
|
|
|
def movieInfo = TheMovieDB.getMovieInfo(movie, locale)
|
2012-07-24 13:44:54 -04:00
|
|
|
|
2012-04-29 01:28:38 -04:00
|
|
|
// fetch nfo
|
2013-02-06 10:12:19 -05:00
|
|
|
fetchMovieNfo(movieDir['movie.nfo'], movieInfo, movieFile, override)
|
|
|
|
|
|
|
|
// generate url files
|
2013-02-13 00:58:13 -05:00
|
|
|
[[db:'imdb', id:movieInfo.imdbId, url:"http://www.imdb.com/title/tt" + (movieInfo.imdbId ?: 0).pad(7)], [db:'tmdb', id:movieInfo.id, url:"http://www.themoviedb.org/movie/${movieInfo.id}"]].each{
|
2013-02-06 10:12:19 -05:00
|
|
|
if (it.id > 0) {
|
|
|
|
def content = "[InternetShortcut]\nURL=${it.url}\n"
|
|
|
|
content.saveAs(new File(movieDir, "${it.db}.url"))
|
|
|
|
}
|
|
|
|
}
|
2012-04-29 01:28:38 -04:00
|
|
|
|
|
|
|
// fetch series banner, fanart, posters, etc
|
2013-02-06 10:12:19 -05:00
|
|
|
fetchMovieArtwork(movieDir['poster.jpg'], movieInfo, 'posters', override, locale)
|
|
|
|
fetchMovieArtwork(movieDir['fanart.jpg'], movieInfo, 'backdrops', override, locale)
|
2012-07-28 06:21:30 -04:00
|
|
|
|
2013-02-06 10:12:19 -05:00
|
|
|
fetchMovieFanart(movieDir['clearart.png'], movieInfo, 'movieart', null, override, locale)
|
|
|
|
fetchMovieFanart(movieDir['logo.png'], movieInfo, 'movielogo', null, override, locale)
|
|
|
|
['bluray', 'dvd', null].findResult { diskType -> fetchMovieFanart(movieDir['disc.png'], movieInfo, 'moviedisc', diskType, override, locale) }
|
2012-12-16 08:26:39 -05:00
|
|
|
|
|
|
|
if (fetchAll) {
|
2013-02-06 10:12:19 -05:00
|
|
|
fetchAllMovieArtwork(movieDir['backdrops'], movieInfo, 'backdrops', override, locale)
|
2012-12-16 08:26:39 -05:00
|
|
|
}
|
2012-04-29 01:28:38 -04:00
|
|
|
}
|
|
|
|
}
|