MissingMethodException.. someone mind helping me out?

Support for Windows users
User avatar
rednoah
The Source
Posts: 22923
Joined: 16 Nov 2011, 08:59
Location: Taipei
Contact:

Re: MissingMethodException.. someone mind helping me out?

Post by rednoah »

Try this:

Code: Select all

// TheTVDB ID
def id = id as int

// API Configuration
def url = new URL('http://10.0.0.1:8989')
def header = ['X-Api-Key': '00000000']

def sonarrSeriesId = new JsonSlurper()
                         .parseText(new URL(url, '/api/series')
                         	            .get(header)
                         	            .text)
                         .find{ it.tvdbId == id }.id

println new URL(url, '/api/command').post(
	JsonOutput.toJson(
		[name: 'rescanSeries', seriesId: sonarrSeriesId]
	).getBytes('UTF-8'),
	'application/json',
	header
).text
:idea: Please read the FAQ and How to Request Help.
ZeroByDivide
Posts: 170
Joined: 16 Dec 2014, 01:39

Re: MissingMethodException.. someone mind helping me out?

Post by ZeroByDivide »

rednoah wrote:Try this:

Code: Select all

// TheTVDB ID
def id = id as int

// API Configuration
def url = new URL('http://10.0.0.1:8989')
def header = ['X-Api-Key': '00000000']

def sonarrSeriesId = new JsonSlurper()
                         .parseText(new URL(url, '/api/series')
                         	            .get(header)
                         	            .text)
                         .find{ it.tvdbId == id }.id

println new URL(url, '/api/command').post(
	JsonOutput.toJson(
		[name: 'rescanSeries', seriesId: sonarrSeriesId]
	).getBytes('UTF-8'),
	'application/json',
	header
).text

Looks like that worked correctly! :D

Code: Select all

{
  "name": "RescanSeries",
  "body": {
    "seriesId": 1,
    "sendUpdatesToClient": true,
    "updateScheduledTask": true,
    "completionMessage": "Completed",
    "name": "RescanSeries",
    "trigger": "manual"
  },
  "priority": "normal",
  "status": "queued",
  "queued": "2017-02-21T16:51:09.5670032Z",
  "trigger": "manual",
  "state": "queued",
  "manual": true,
  "startedOn": "2017-02-21T16:51:09.5670032Z",
  "sendUpdatesToClient": true,
  "updateScheduledTask": true,
  "id": 692350
}
Done ?(?????)?
So glad to finally have it only scan the series that has downloaded instead of running a scan through every single series I have on sonarr..

Thanks so much! Next time I get some cash I'll shoot a donation your way.
devster
Posts: 417
Joined: 06 Jun 2017, 22:56

Re: MissingMethodException.. someone mind helping me out?

Post by devster »

Hi, I stumbled on this post and I'd be interested of doing something similar.
I would like to know how you keep your own version of the script in sync with what rednoah has on github.
I'm also missing a crucial step in your refreshSonarrLibrary function.
It seems that you're collecting all episodes of a series or a season before sending the notification via an API call, do I read it right or am I missing something?
I only work in black and sometimes very, very dark grey. (Batman)
ZeroByDivide
Posts: 170
Joined: 16 Dec 2014, 01:39

Re: MissingMethodException.. someone mind helping me out?

Post by ZeroByDivide »

devster wrote: 26 Nov 2017, 17:11 I would like to know how you keep your own version of the script in sync with what rednoah has on github.
There is nothing that you have to keep in sync with, as the sonarr groovy script is not really dependent on anything other than just filebot so you once you get things configured you will more than likely never have to update the script again unless something on sonarrs side changes.
devster wrote: 26 Nov 2017, 17:11 I'm also missing a crucial step in your refreshSonarrLibrary function.
It seems that you're collecting all episodes of a series or a season before sending the notification via an API call, do I read it right or am I missing something?
This script will send off the API call per torrent and tell it to scan the show folder for the ID (it gets the ID from tvdb and matches it to tvdb ID through sonarrs API) that matches the episode that gets processed, the current iteration that is in this thread is just for using with tv shows (sonarr) but I have made some edits of my own to make it work with movies (radarr) as well.

Code: Select all

// The TVDB/TMDB ID
def id = id as int

// Sonarr API Configuration
def url = new URL('http://localhost:8989')
def header = ['X-Api-Key': 'PLACESONARRAPIKEYHERE']

def sonarrSeriesId = new JsonSlurper()
    .parseText(new URL(url, '/api/series')
        .get(header)
        .text)
    .find {
        it.tvdbId == id
    }.id

println new URL(url, '/api/command').post(
    JsonOutput.toJson(
        [name: 'rescanSeries', seriesId: sonarrSeriesId]
    ).getBytes('UTF-8'),
    'application/json',
    header
).text

// Radarr API Configuration
def url2 = new URL('http://localhost:7878')
def header2 = ['X-Api-Key': 'PLACERADARRAPIKEYHERE']

def radarrMovieId = new JsonSlurper()
    .parseText(new URL(url2, '/api/movie')
        .get(header2)
        .text)
    .find {
        it.tmdbId == id
    }.id

println new URL(url2, '/api/command').post(
    JsonOutput.toJson(
        [name: 'rescanMovie', movieId: radarrMovieId]
    ).getBytes('UTF-8'),
    'application/json',
    header2
).text
it could probably be condensed down a slight bit but it works.

to make it work with filebot, make a .groovy file with the above code in it, and then you'd add

Code: Select all

exec="filebot -script path/to/script.groovy --def id={id}"
at the end of your filebot command. like in this for example --

Code: Select all

@ECHO OFF

:: Media file processing script for Filebot
:: CLI https://www.filebot.net/cli.html
:: Format https://www.filebot.net/naming.html
:: Forums https://www.filebot.net/forums

:: Qbittorrent Call ---
:: "C:/Users/JourneyOver/Dropbox/Public/Folders/Filebot/MyStuff/Filebot_Wrapper.bat" "%N" "%F"

:: Set up some logging
set LOGDIR=%userprofile%/Dropbox/Public/Folders/Filebot/logs

:: Groovy Script Location
set UPSR=%userprofile%/Dropbox/Public/Folders/Filebot/MyStuff/update-sonarr.groovy

:: Base destinations to move files, no trailing slash. The subfolder is defined in the format string.
set DESTINATION=D:/Shows

:: Passing Args from Qbittorrent
set TORRENT_NAME=%1
set TORRENT_PATH=%2
::set TORRENT_LABEL=%3

:: Rename action i.e: move | copy | keeplink | symlink | hardlink
set ACTION=move

:: Conflict resolution i.e: override | skip | fail
set CONFLICT=override

:: Paths for format and filter
::set FILTERPATH="@/%userprofile%/Dropbox/Public/Folders/Filebot/MyStuff/Filter.txt"
set FORMATPATH="@/%userprofile%/Dropbox/Public/Folders/Filebot/MyStuff/Formatting.txt"

:: Old Age Filter Format
set FILTERPATH2="any{ age < 170 }{ airdate ? true : false }"

:: Process music files
set MUSIC=false

:: Download subtitles for the given languages i.e: en | de | fr
set SUBTITLES=en

:: Fetch artwork/nfo
set ARTWORK=false

:: Generate *.url files and fetch all available backdrops
set EXTRAS=false

:: Tell the given Kodi/XBMC instance to rescan it's library
::Set KODI=host[:port]

:: Tell the given Plex instance to rescan it's library. Plex Home instances require an authentication token
set PLEX=host:apikey

:: Tell the given Emby instance to rescan it's library
::set EMBY=host:apikey

:: Save reports to local filesystem
set STOREREPORT=false

:: Do not extract archives
set SKIPEXTRACT=false

:: Automatically remove empty folders and clutter files that may be left behind after moving the video files, or temporary extracted files after copying
set CLEAN=true

:: Delete archives after extraction
set DELETEAFTEREXTRACT=true

:: Run filebot script
filebot -script fn:amc ^
  --output "%DESTINATION%" ^
  --log-file "%LOGDIR%/filebot-amc.log" ^
  --action %ACTION% ^
  --conflict %CONFLICT% ^
  -non-strict ^
  -no-xattr ^
  --filter ^
  %FILTERPATH2% ^
  --def ^
  ut_dir=%TORRENT_PATH% ^
  ut_kind=multi ^
  ut_title=%TORRENT_NAME% ^
  excludeList="%LOGDIR%/filebot-history.log" ^
  music=%MUSIC% ^
  subtitles=%SUBTITLES% ^
  artwork=%ARTWORK% ^
  extras=%EXTRAS% ^
  plex="%PLEX%" ^
  storeReport=%STOREREPORT% ^
  skipExtract=%SKIPEXTRACT% ^
  clean=%CLEAN% ^
  deleteAfterExtract=%DELETEAFTEREXTRACT% ^
  %FORMATPATH% ^
  exec="filebot -script %UPSR% --def id={id}"
or if using python you'd do

Code: Select all

'exec=filebot -script path/to/script.groovy --def id={id}'
like example --

Code: Select all

# Media file processing script for Filebot
# CLI https://www.filebot.net/cli.html
# Format https://www.filebot.net/naming.html
# Forums https://www.filebot.net/forums

# Qbittorrent Call ---
# "C:/Users/JourneyOver/Dropbox/Public/Folders/Filebot/MyStuff/Filebot_Wrapper.pyw" "%L" "" "%N" "multi" "" "%F"

import os
import sys
import subprocess

# required args
label, state, title, kind, file, directory = sys.argv[1:7]

# Set up some logging
LOGDIR = os.path.expanduser(os.sep.join(["~", "Dropbox/Public/Folders/Filebot/logs"]))

# Groovy Script Locations
UPSR = os.path.expanduser(os.sep.join(["~", "Dropbox/Public/Folders/Filebot/MyStuff/Update-Sonarr.groovy"]))

# Base destinations to move files, no trailing slash. The subfolder is defined in the format string.
DESTINATION = 'D:/Shows'

# Rename action i.e: move | copy | keeplink | symlink | hardlink | test
ACTION = 'Move'

# Conflict resolution i.e: override | skip | auto | index | fail
CONFLICT = 'Override'

# custom formats
#FILTERPATH = "@/" + os.path.expanduser(os.sep.join(["~", "Dropbox/Public/Folders/Filebot/MyStuff/Filter.txt"]))
FORMATPATH = "@/" + os.path.expanduser(os.sep.join(["~", "Dropbox/Public/Folders/Filebot/MyStuff/Formatting.txt"]))

# Old Age Filter Format
if label == "tv-sonarr":
  FILTERPATH2 = 'any{ age < 7 }{ airdate ? true : false }'
else:
  FILTERPATH2 = 'any{ age < 5000 }{ airdate ? true : false }'

# Process Music Files
MUSIC = 'false'

# Download subtitles for the given languages i.e: en, de, fr, es, ja, zh, ...
SUBTITLES = 'en'

# Fetch Artwork/NFO
ARTWORK = 'false'

# Generate *.url files and fetch all available backdrops
EXTRAS  = 'false'

# Tell the given Kodi/XBMN instance to rescan it's library
#Kodi = 'host[:port]'

# Tell the given Plex instance to rescan it's library. Plex Home instances require an authentication token
PLEX = 'host:apikey'

# Tell the given Emby instance to rescan it's library
#EMBY = 'host:apikey'

# Save reports to local filesystem
STOREREPORT = 'false'

# Skip extracting file
SKIPEXTRACT = 'false'

# Automatically remove empty folders and clutter files that may be left behind after moving the video files, or temporary extracted files after copying
CLEAN = 'true'

# Delete archives after extraction
DELETEAFTEREXTRACT = 'true'

command = [
  'filebot', '-script', 'fn:amc',
  '--output', DESTINATION,
  '--action', ACTION,
  '--conflict', CONFLICT,
  '-non-strict',
  '-no-xattr',
  '--filter',
    FILTERPATH2,
  '--log-file', LOGDIR + '/filebot-amc.log',
  '--def',
     FORMATPATH,
    'excludeList=' + LOGDIR + '/filebot-history.log',
    'music=' + MUSIC,
    'subtitles=' + SUBTITLES,
    'artwork=' + ARTWORK,
    'extras=' + EXTRAS,
    'storeReport=' + STOREREPORT,
    'skipExtract=' + SKIPEXTRACT,
    'clean=' + CLEAN,
    'deleteAfterExtract=' + DELETEAFTEREXTRACT,
    'plex=' + PLEX,
    'ut_label=' + label,
    'ut_state=' + state,
    'ut_title=' + title,
    'ut_kind='  + kind,
    'ut_file='  + file,
    'ut_dir='   + directory,
    'exec=filebot -script ' + UPSR + ' --def id={id}'
]

# execute command (and hide cmd window)
subprocess.run(command, creationflags=0x08000000)
ZeroByDivide
Posts: 170
Joined: 16 Dec 2014, 01:39

Re: MissingMethodException.. someone mind helping me out?

Post by ZeroByDivide »

@Rednoah I never did ask but since you added

Code: Select all

/**
 * Sonarr helpers
 */
def rescanSonarrSeries(server, port, apikey, seriesId) {
	// use HTTPS if hostname is specified, use HTTP if IP is specified
	def protocol = server ==~ /localhost|[0-9.:]+/ ? 'http' : 'https'
	def url = new URL("$protocol://$server:$port")
	def requestHeader = ['X-Api-Key': apikey]

	def series = new JsonSlurper().parseText(new URL(url, '/api/series').get(requestHeader).text)
	def id = series.find{ it.tvdbId == seriesId }?.id

	def command = [name: 'rescanSeries', seriesId: id]
	new URL(url, '/api/command').post(JsonOutput.toJson(command).getBytes('UTF-8'), 'application/json', requestHeader)
}
to the htpc.groovy script do I even need my groovy script that does the the whole rescanseries stuff anymore? If not how would I go about setting up the sonarr stuff?
User avatar
rednoah
The Source
Posts: 22923
Joined: 16 Nov 2011, 08:59
Location: Taipei
Contact:

Re: MissingMethodException.. someone mind helping me out?

Post by rednoah »

I donno. I forgot I implemented sonarr support in the first place.

What have your tried so far? I'm not sure if the amc script actually supports a sonarr option. Maybe the code is just there as a helper for 3rd party scripts.

I'll look at the script code later.
:idea: Please read the FAQ and How to Request Help.
ZeroByDivide
Posts: 170
Joined: 16 Dec 2014, 01:39

Re: MissingMethodException.. someone mind helping me out?

Post by ZeroByDivide »

At the moment I haven't actually tried anything since I've just been running my sonarr update script that you helped me with a long time ago. I did do a check in the AMC script and didn't really see anything with sonarr so I guess it's not fully in other than just in the htpc.groovy script. I've actually been trying to take a crack at trying to implement sonarr (and radarr) into the amc script but I dunno if I'll be able to or not as I still don't fully understand groovy :/ I just think it'd be nice to have the AMC script support sonarr and radarr by default so someone can just throw something like

Code: Select all

 --def sonarr=HOST:KEY|{id} radarr=HOST:KEY|{id}
or something along those lines.

So far I have at least written the radarr helper bit since it's the easiest of actually trying to implement for my knowledge xD

Code: Select all

/**
 * Radarr helpers
 */
def rescanRadarrMovies(server, port, apikey, movieId) {
	// use HTTPS if hostname is specified, use HTTP if IP is specified
	def protocol = server ==~ /localhost|[0-9.:]+/ ? 'http' : 'https'
	def url = new URL("$protocol://$server:$port")
	def requestHeader = ['X-Api-Key': apikey]

	def movies = new JsonSlurper().parseText(new URL(url, '/api/movie').get(requestHeader).text)
	def id = movies.find{ it.tmdbId == movieId }?.id

	def command = [name: 'RescanMovie', movieId: id]
	new URL(url, '/api/command').post(JsonOutput.toJson(command).getBytes('UTF-8'), 'application/json', requestHeader)
}
User avatar
rednoah
The Source
Posts: 22923
Joined: 16 Nov 2011, 08:59
Location: Taipei
Contact:

Re: MissingMethodException.. someone mind helping me out?

Post by rednoah »

So I checked, and the amc script doesn't use these functions at all. I just implemented them once just so others can use them.

e.g.

Code: Select all

include('lib/htpc')
rescanSonarrSeries(...)
I'd write those rescan scripts as separate filebot/groovy scripts, and then have the amc script call them via something like:

Code: Select all

--def exec="filebot -script /path/to/rescan.groovy"
That way you can run and test your rescan script independently of amc script calls.
:idea: Please read the FAQ and How to Request Help.
ZeroByDivide
Posts: 170
Joined: 16 Dec 2014, 01:39

Re: MissingMethodException.. someone mind helping me out?

Post by ZeroByDivide »

rednoah wrote: 10 May 2018, 10:03 So I checked, and the amc script doesn't use these functions at all. I just implemented them once just so others can use them.

e.g.

Code: Select all

include('lib/htpc')
rescanSonarrSeries(...)
I'd write those rescan scripts as separate filebot/groovy scripts, and then have the amc script call them via something like:

Code: Select all

--def exec="filebot -script /path/to/rescan.groovy"
That way you can run and test your rescan script independently of amc script calls.
That's what I've already been doing, I was just hoping to be able to cut out my rescan script if the AMC script was to be able to do it by default >.<

Anyways is there some way to combine these down into one? so like if it's a TMDB ID it does the rescan for radarr, but if it's a TVDB it'll do the rescan for sonarr.

Code: Select all

// The TVDB ID
def id = id as int

// Sonarr API Configuration
def url = new URL('http://localhost:8989')
def header = ['X-Api-Key': 'sadasdasdasda']

def sonarrSeriesId = new JsonSlurper()
    .parseText(new URL(url, '/api/series')
        .get(header)
        .text)
    .find {
        it.tvdbId == id
    }.id

println new URL(url, '/api/command').post(
    JsonOutput.toJson(
        [name: 'rescanSeries', seriesId: sonarrSeriesId]
    ).getBytes('UTF-8'),
    'application/json',
    header
).text


// Radarr API Configuration
def url = new URL('http://localhost:7878')
def header = ['X-Api-Key': 'sdfsdfsdfsdfsdfs']

def radarrMovieId = new JsonSlurper()
    .parseText(new URL(url, '/api/movie')
        .get(header)
        .text)
    .find {
        it.tmdbId == id
    }.id

println new URL(url, '/api/command').post(
    JsonOutput.toJson(
        [name: 'rescanMovie', movieId: radarrMovieId]
    ).getBytes('UTF-8'),
    'application/json',
    header
).text
since as it stands right now I can't get the exec function to work for two separate scripts for some reason (which btw I'm using python so my exec currenty looks like

Code: Select all

'exec=filebot -script ' + SONARR + ' --def id={id}'
) and trying to run the above in one script just produces the error

Code: Select all

startup failed:
Script1.groovy: 26: The current scope already contains a variable of the name url
 @ line 26, column 5.
   def url = new URL('http://localhost:7878')
       ^

Script1.groovy: 27: The current scope already contains a variable of the name header
 @ line 27, column 5.
   def header = ['X-Api-Key': '']
       ^

2 errors

org.codehaus.groovy.control.MultipleCompilationErrorsException: startup failed:
Script1.groovy: 26: The current scope already contains a variable of the name url
 @ line 26, column 5.
   def url = new URL('http://localhost:7878')
       ^

Script1.groovy: 27: The current scope already contains a variable of the name header
 @ line 27, column 5.
   def header = ['X-Api-Key': '']
       ^

2 errors

        at net.filebot.cli.ScriptShell.evaluate(ScriptShell.java:64)
        at net.filebot.cli.ScriptShell.runScript(ScriptShell.java:74)
        at net.filebot.cli.ArgumentProcessor.runScript(ArgumentProcessor.java:127)
        at net.filebot.cli.ArgumentProcessor.run(ArgumentProcessor.java:29)
        at net.filebot.Main.main(Main.java:116)

Failure (°_°)
User avatar
rednoah
The Source
Posts: 22923
Joined: 16 Nov 2011, 08:59
Location: Taipei
Contact:

Re: MissingMethodException.. someone mind helping me out?

Post by rednoah »

Sure, you can pass in all the information you need to your post-processing script and then call Sonarr/Radarr accordingly:

Code: Select all

--def db={info.database} id={id}
or

Code: Select all

--exec "filebot -script /path/to/{type =~ /Movie/ ? 'sonarr' : 'radarr'}.groovy --def id={id}"
:idea: Please read the FAQ and How to Request Help.
ZeroByDivide
Posts: 170
Joined: 16 Dec 2014, 01:39

Re: MissingMethodException.. someone mind helping me out?

Post by ZeroByDivide »

rednoah wrote: 11 May 2018, 05:46 Sure, you can pass in all the information you need to your post-processing script and then call Sonarr/Radarr accordingly:

Code: Select all

--def db={info.database} id={id}
or

Code: Select all

--exec "filebot -script /path/to/{type =~ /Movie/ ? 'sonarr' : 'radarr'}.groovy --def id={id}"
Opted to use the

Code: Select all

--def db={info.database} id={id}
One thing I have noticed though is that the

Code: Select all

info.database
ends up being blank when the database being used is TheMovieDB, doesn't completely matter though as long as TV shows will always produce the info.database correctly as I just have things setup as a if else statement like so

Code: Select all

// TVDB/TMDB ID
def id = id as int

// database
def db = db

if (db.equals('TheTVDB')) {
    // Sonarr API Configuration
    def url = new URL('http://localhost:8989')
    def header = ['X-Api-Key': 'APIKEY']

    def sonarrSeriesId = new JsonSlurper()
        .parseText(new URL(url, '/api/series')
            .get(header)
            .text)
        .find {
            it.tvdbId == id
        }.id

    println new URL(url, '/api/command').post(
        JsonOutput.toJson(
            [name: 'rescanSeries', seriesId: sonarrSeriesId]
        ).getBytes('UTF-8'),
        'application/json',
        header
    ).text
} else {
    // Radarr API Configuration
    def url = new URL('http://localhost:7878')
    def header = ['X-Api-Key': 'APIKEY']

    def radarrMovieId = new JsonSlurper()
        .parseText(new URL(url, '/api/movie')
            .get(header)
            .text)
        .find {
            it.tmdbId == id
        }.id

    println new URL(url, '/api/command').post(
        JsonOutput.toJson(
            [name: 'rescanMovie', movieId: radarrMovieId]
        ).getBytes('UTF-8'),
        'application/json',
        header
    ).text
}
Doing testing everything seems to be passing correctly now along with sonarr doing it's rescan when TheTVDB gets passed and when nothing (or nothing equaling TheTVDB) gets passed radarr does the rescan instead.
ZeroByDivide
Posts: 170
Joined: 16 Dec 2014, 01:39

Re: MissingMethodException.. someone mind helping me out?

Post by ZeroByDivide »

Though it would be nice either way to get the whole
One thing I have noticed though is that the

Code: Select all

info.database
ends up being blank when the database being used is TheMovieDB
thing fixed, as it'd make things a lot better since then I can do a split "if" instead of an "if else" like I have above.

An example of what I'm talking about

Code: Select all

Run script [fn:amc] at [Fri May 11 16:02:58 CDT 2018]
Parameter: minLengthMS = 300000
Parameter: excludeList = C:\Users\JourneyOver\Dropbox/Public/Folders/Filebot/logs/filebot-history.log
Parameter: music = false
Parameter: subtitles = en
Parameter: artwork = true
Parameter: extras = false
Parameter: storeReport = false
Parameter: skipExtract = false
Parameter: clean = true
Parameter: deleteAfterExtract = true
Parameter: plex = *****
Parameter: movieFormat = { import java.math.RoundingMode
  import net.filebot.Language
  def norm = { it.upperInitial()
             .lowerTrail()
             .replaceTrailingBrackets()
             .replaceAll(/[`´‘’ʻ""“”]/, "'")
             .replaceAll(/[:|]/, " - ")
             .replaceAll(/[?]/, "!")
             .replaceAll(/[*\s]+/, " ")
             .replaceAll(/\b[IiVvXx]+\b/, { it.upper() })
             .replaceAll(/\b[0-9](?i:th|nd|rd)\b/, { it.lower() }) }
 allOf
  // Movies directory
  {"Movies"}
  // Folder name
  {n.colon(" - ") + " [$y]"}
  { allOf
    // File name
    { primaryTitle ? primaryTitle.colon(" - ") : primaryTitle.colon(" - ") }
    {" [$y]"}
    // tags + a few more variants
    { specials = { allOf
                     {tags}
                     { def last = n.tokenize(" ").last()
                       fn.after(/(?i:$last)/).findAll(/(?i:alternate[ ._-]cut|limited)/)*.upperInitial()*.lowerTrail()*.replaceAll(/[._-]/, " ") }
                     .flatten().sort() }
      specials().size() > 0 ? specials().join(", ").replaceAll(/^/, " - ") : "" }
    {" PT $pi"}
    {" ["}
    { allOf
      // Video stream
      { allOf{vf}{vc}.join(" ") }
      { def audioClean = { it.replaceAll(/[\p{Pd}\p{Space}]/, ' ').replaceAll(/\p{Space}{2,}/, ' ') }
        // map Codec + Format Profile
        def mCFP = [ "AC3" : "AC3",
                     "AC3+" : "E-AC3",
                     "AAC LC LC" : "AAC-LC",
                     "AAC LC SBR HE AAC LC": "HE-AAC" ]
        audio.collect { au ->
        def channels = any{ au['ChannelPositions/String2'] }{ au['Channel(s)_Original'] }{ au['Channel(s)'] }
        def ch = channels.replaceAll(/Object\sBased\s\/|0.(?=\d.\d)/, '')
                         .tokenize('\\/').take(3)*.toDouble()
                         .inject(0, { a, b -> a + b }).findAll { it > 0 }
                         .max().toBigDecimal().setScale(1, RoundingMode.HALF_UP).toString()
        def codec = audioClean(any{ au['CodecID/String'] }{ au['Codec/String'] }{ au['Codec'] })
        def format = any{ au['CodecID/Hint'] }{ au['Format'] }
        def format_profile = { if ( au['Format_Profile'] != null) audioClean(au['Format_Profile']) else '' }
        def combined = allOf{codec}{format_profile}.join(' ')
        def stream = allOf
                       { ch }
                       { mCFP.get(combined, format) }
                       { Language.findLanguage(au['Language']).ISO3.upperInitial() }
        return stream }*.join(" ").join(", ") }
        // logo-free release source finder
      { def websources = readLines("C:/Users/JourneyOver/Dropbox/Public/Folders/Filebot/websources.txt").join("|")
        def lfr = { fn.match(/($websources)\.(?i)WEB/) }
        return allOf{lfr}{"${self.source ?: 'WEB-DL'}"}.join(" ") }
      .join(" - ") }
    {"]"}
    {subt}
    .join("") }
  .join("/") }
Parameter: seriesFormat = { import java.math.RoundingMode
  import net.filebot.Language
  def norm = { it.replaceAll(/[`´‘’ʻ""“”]/, "'")
             .replaceAll(/[:|]/, " - ")
             .replaceAll(/[?]/, "!")
             .replaceAll(/[*\s]+/, " ")
             .replaceAll(/\b[IiVvXx]+\b/, { it.upper() })
             .replaceAll(/\b[0-9](?i:th|nd|rd)\b/, { it.lower() }) }
allOf
  // TV Shows directory
  {"TV Shows"}
  // Folder name
  { norm(n).replaceAll(/(S.H.I.E.L.D.)/, " S.H.I.E.L.D ") }
  // Season Folder name
  { episode.special ? 'Specials' : 'Season ' + s.pad(2) }
  { allOf
    // File name
    { norm(n).replaceTrailingBrackets() }
    { episode.special ? 'S00E' + special.pad(2) : S00E00 }
    { allOf
      { norm(t).replacePart(' - Part $1') }
      { allOf
        { allOf
          {"["}
          { allOf
            // Video stream
            { allOf{vf}{vc}.join(" ") }
            { def audioClean = { it.replaceAll(/[\p{Pd}\p{Space}]/, ' ').replaceAll(/\p{Space}{2,}/, ' ') }
              // map Codec + Format Profile
              def mCFP = [ "AC3" : "AC3",
                           "AC3+" : "E-AC3",
                           "AAC LC LC" : "AAC-LC",
                           "AAC LC SBR HE AAC LC": "HE-AAC" ]
              audio.collect { au ->
              def channels = any{ au['ChannelPositions/String2'] }{ au['Channel(s)_Original'] }{ au['Channel(s)'] }
              def ch = channels.replaceAll(/Object\sBased\s\/|0.(?=\d.\d)/, '')
                               .tokenize('\\/').take(3)*.toDouble()
                               .inject(0, { a, b -> a + b }).findAll { it > 0 }
                               .max().toBigDecimal().setScale(1, RoundingMode.HALF_UP).toString()
              def codec = audioClean(any{ au['CodecID/String'] }{ au['Codec/String'] }{ au['Codec'] })
              def format = any{ au['CodecID/Hint'] }{ au['Format'] }
              def format_profile = { if ( au['Format_Profile'] != null) audioClean(au['Format_Profile']) else '' }
              def combined = allOf{codec}{format_profile}.join(' ')
              def stream = allOf
                             { ch }
                             { mCFP.get(combined, format) }
                             { Language.findLanguage(au['Language']).ISO3.upperInitial() }
              return stream }*.join(" ").join(", ") }
              // logo-free release source finder
            { def websources = readLines("C:/Users/JourneyOver/Dropbox/Public/Folders/Filebot/websources.txt").join("|")
              def lfr = { fn.match(/($websources)\.(?i)WEB/) }
              return allOf{lfr}{"${self.source ?: 'WEB-DL'}"}.join(" ") }
            .join(" - ") }
          {"]"}
          .join("") }
          {subt}
        .join("") }
      .join(" ") }
    .join(" - ") }
  .join("/") }
Parameter: ut_label = 
Parameter: ut_state = 
Parameter: ut_title = Independence.Day.Resurgence (2016)1080p.BluRay.x264.mp4
Parameter: ut_kind = multi
Parameter: ut_file = 
Parameter: ut_dir = C:\Users\JourneyOver\Desktop\QBT\Independence.Day.Resurgence (2016)1080p.BluRay.x264.mp4
Parameter: exec = filebot -script C:\Users\JourneyOver\Dropbox/Public/Folders/Filebot/Update_Sonarr.groovy --def db={info.database} id={id}
Use excludes: C:\Users\JourneyOver\Dropbox\Public\Folders\Filebot\logs\filebot-history.log
Input: C:\Users\JourneyOver\Desktop\QBT\Independence.Day.Resurgence (2016)1080p.BluRay.x264.mp4
Group: [mov:independence day resurgence 2016] => [Independence.Day.Resurgence (2016)1080p.BluRay.x264.mp4]
Get [English] subtitles for 1 files
Looking up subtitles by hash via OpenSubtitles
Fetching [English] subtitles [Independence.Day.Resurgence.2016.720p.BluRay.x264-GECKOS.srt] from [OpenSubtitles]
Export [Independence.Day.Resurgence.2016.720p.BluRay.x264-GECKOS.srt] as [SubRip / UTF-8]
Writing [Independence.Day.Resurgence.2016.720p.BluRay.x264-GECKOS.srt] to [Independence.Day.Resurgence (2016)1080p.BluRay.x264.eng.srt]
Rename movies using [TheMovieDB]
Auto-detect movie from context: [C:\Users\JourneyOver\Desktop\QBT\Independence.Day.Resurgence (2016)1080p.BluRay.x264.mp4]
Apply filter [any{ age < 80000 }{ airdate ? true : false }] on [1] items
Include [Independence Day: Resurgence (2016)]
[MOVE] from [C:\Users\JourneyOver\Desktop\QBT\Independence.Day.Resurgence (2016)1080p.BluRay.x264.mp4] to [D:\Media\Movies\Independence Day - Resurgence [2016]\Independence Day - Resurgence [2016] [1080p x264 - 2.0 AAC-LC - BluRay].mp4]
[MOVE] from [C:\Users\JourneyOver\Desktop\QBT\Independence.Day.Resurgence (2016)1080p.BluRay.x264.eng.srt] to [D:\Media\Movies\Independence Day - Resurgence [2016]\Independence Day - Resurgence [2016] [1080p x264 - 2.0 AAC-LC - BluRay].eng.srt]
Processed 2 files
Fetching movie artwork for [Independence Day: Resurgence (2016)] to [D:\Media\Movies\Independence Day - Resurgence [2016]]
Generate Movie NFO: Independence Day: Resurgence [47933]
Fetching D:\Media\Movies\Independence Day - Resurgence [2016]\poster.jpg => [posters/2000x3000, en, 5.572, https://image.tmdb.org/t/p/original/5CHJs479xWnm3zMDOl94VkKS7MZ.jpg]
Fetching D:\Media\Movies\Independence Day - Resurgence [2016]\fanart.jpg => [backdrops/1920x1080, en, 5.245421245421245, https://image.tmdb.org/t/p/original/jlabReqTKDttdAUOGLq7VMNyv1u.jpg]
Fetching D:\Media\Movies\Independence Day - Resurgence [2016]\clearart.png => [hdmovieclearart, en, 7.0, https://assets.fanart.tv/fanart/movies/47933/hdmovieclearart/independence-day-resurgence-577035e00909b.png]
Fetching D:\Media\Movies\Independence Day - Resurgence [2016]\logo.png => [hdmovielogo, en, 10.0, https://assets.fanart.tv/fanart/movies/47933/hdmovielogo/independence-day-resurgence-56cd3a5854b98.png]
Fetching D:\Media\Movies\Independence Day - Resurgence [2016]\disc.png => [moviedisc/bluray, en, 8.0, https://assets.fanart.tv/fanart/movies/47933/moviedisc/independence-day-resurgence-57703e6cd6f1d.png]
Execute: filebot -script C:\Users\JourneyOver\Dropbox/Public/Folders/Filebot/Update_Sonarr.groovy --def db= id=47933
Notify Plex: [host:localhost, token:]
GET: http://localhost:32400/library/sections/all/refresh?X-Plex-Token=
Done ヾ(@⌒ー⌒@)ノ
As you can see the db just comes back empty when it should come back as TheMovieDB
User avatar
rednoah
The Source
Posts: 22923
Joined: 16 Nov 2011, 08:59
Location: Taipei
Contact:

Re: MissingMethodException.. someone mind helping me out?

Post by rednoah »

{info.database} indeed only works for Episode type objects. I guess that's because for movies there really isn't anything but TheMovieDB. I recommend using {type} and that'll give you either "Movie" or "Episode" based on which you can decide what to do.
:idea: Please read the FAQ and How to Request Help.
ZeroByDivide
Posts: 170
Joined: 16 Dec 2014, 01:39

Re: MissingMethodException.. someone mind helping me out?

Post by ZeroByDivide »

rednoah wrote: 12 May 2018, 04:34 {info.database} indeed only works for Episode type objects. I guess that's because for movies there really isn't anything but TheMovieDB. I recommend using {type} and that'll give you either "Movie" or "Episode" based on which you can decide what to do.


Great that works perfectly! New sonarr/radarr series/movie refresh script below (replace APIKEY with your API Keys from Sonarr & Radarr)

Code: Select all

// TVDB/TMDB ID
def id = id as int

// Video Type
def type = type

// Sonarr API Configuration
if (type.equals('Episode')) {
    def url = new URL('http://localhost:8989')
    def header = ['X-Api-Key': 'APIKEY']

    def sonarrSeriesId = new JsonSlurper()
        .parseText(new URL(url, '/api/series')
            .get(header)
            .text)
        .find {
            it.tvdbId == id
        }.id

    println new URL(url, '/api/command').post(
        JsonOutput.toJson(
            [name: 'rescanSeries', seriesId: sonarrSeriesId]
        ).getBytes('UTF-8'),
        'application/json',
        header
    ).text
}

// Radarr API Configuration
if (type.equals('Movie')) {
    def url = new URL('http://localhost:7878')
    def header = ['X-Api-Key': 'APIKEY']

    def radarrMovieId = new JsonSlurper()
        .parseText(new URL(url, '/api/movie')
            .get(header)
            .text)
        .find {
            it.tmdbId == id
        }.id

    println new URL(url, '/api/command').post(
        JsonOutput.toJson(
            [name: 'rescanMovie', movieId: radarrMovieId]
        ).getBytes('UTF-8'),
        'application/json',
        header
    ).text
}
and add

Code: Select all

--def exec="filebot -script /path/to/rescan.groovy --def type={type} id={id}"
to your filebot call.
User avatar
rednoah
The Source
Posts: 22923
Joined: 16 Nov 2011, 08:59
Location: Taipei
Contact:

Re: MissingMethodException.. someone mind helping me out?

Post by rednoah »

I'd do checks with the regex find operator:

Code: Select all

type =~ /Movie/

Code: Select all

type =~ /Episode/
That's because {type} can also yield values such as MoviePart and MultiEpisode.
:idea: Please read the FAQ and How to Request Help.
ZeroByDivide
Posts: 170
Joined: 16 Dec 2014, 01:39

Re: MissingMethodException.. someone mind helping me out?

Post by ZeroByDivide »

rednoah wrote: 12 May 2018, 06:47 I'd do checks with the regex find operator:

Code: Select all

type =~ /Movie/

Code: Select all

type =~ /Episode/
That's because {type} can also yield values such as MoviePart and MultiEpisode.
so it would be better to do the .groovy script like so then?

Code: Select all

// TVDB/TMDB ID
def id = id as int

// Video Type
def type = type

// Sonarr API Configuration
if (type =~ /Episode/) {
    def url = new URL('http://localhost:8989')
    def header = ['X-Api-Key': 'APIKEY']

    def sonarrSeriesId = new JsonSlurper()
        .parseText(new URL(url, '/api/series')
            .get(header)
            .text)
        .find {
            it.tvdbId == id
        }.id

    println new URL(url, '/api/command').post(
        JsonOutput.toJson(
            [name: 'rescanSeries', seriesId: sonarrSeriesId]
        ).getBytes('UTF-8'),
        'application/json',
        header
    ).text
}

// Radarr API Configuration
if (type =~ /Movie/) {
    def url = new URL('http://localhost:7878')
    def header = ['X-Api-Key': 'APIKEY']

    def radarrMovieId = new JsonSlurper()
        .parseText(new URL(url, '/api/movie')
            .get(header)
            .text)
        .find {
            it.tmdbId == id
        }.id

    println new URL(url, '/api/command').post(
        JsonOutput.toJson(
            [name: 'rescanMovie', movieId: radarrMovieId]
        ).getBytes('UTF-8'),
        'application/json',
        header
    ).text
}
Last edited by ZeroByDivide on 12 May 2018, 07:12, edited 1 time in total.
User avatar
rednoah
The Source
Posts: 22923
Joined: 16 Nov 2011, 08:59
Location: Taipei
Contact:

Re: MissingMethodException.. someone mind helping me out?

Post by rednoah »

Yep, that should work in all corner cases as well.
:idea: Please read the FAQ and How to Request Help.
ZeroByDivide
Posts: 170
Joined: 16 Dec 2014, 01:39

Re: MissingMethodException.. someone mind helping me out?

Post by ZeroByDivide »

rednoah wrote: 12 May 2018, 06:56 Yep, that should work in all corner cases as well.
Great, Thanks a bunch for all the help as usual! :D
Post Reply