-- function to get the correct extension for a preset
to getPresetExtension(preset)
tell application "EyeTV"
-- if you want to change the extension for a preset, make sure to use the exact same names as in the allowedPresets list below
if preset is in {QuickTime, eMail, Web, HDV720p, HDV1080i} then
return ".mov"
else if preset is in {MPEGPS, «constant EtypTost», «constant EtypVCD », «constant EtypSVCD», «constant EtypDVD », «constant EtypTost», "SymLink"} then
return ".mpg"
else if preset is in {MPEGES, DVDStudioPro} then
return ".mpv"
else if preset is in {AVI, DivX, «constant EtypDvxd»} then
return ".avi"
else if preset is in {ThreeG} then
return ".3gp"
else if preset is in {iPod, AppleTV} then
return ".m4v"
else
-- all other presets default to .mp4
return ".mp4"
end if
end tell
end getPresetExtension
-- main script
on run
tell application "EyeTV" to activate
-- Presets you can use (if you want to modify the extension used with a preset, edit the getPresetExtension function above):
tell application "EyeTV" to set allowedPresets to {QuickTime, «constant EtypVCD », «constant EtypSVCD», «constant EtypDVD », «constant EtypDvxd», «constant EtypTost», eMail, Web, iMovie, iMovieHD, iDVD, DVDStudioPro, «constant EtypTost», MPEGPS, MPEGES, DV, DV169, Movie, AVI, MPEG4, ThreeG, DivX, HDV720p, HDV1080i, iTunes, AppleLossless, PSP, PSPH264, iPod, iPodMP4, AppleTV, iPhone, Turbo, «constant EtypBDMV», iPad, HD720p, HD1080p, "SymLink"}
-- start modifying settings here ---------------------------------------------------------
-- set to false to test folder creation only
set exportingEnabled to true
--set whether error dialogs should be shown
set silentErrors to true
-- set to a path like "Macintosh HD:Exported Movies:"
set defaultOutputFolder to "Macintosh HD:Users:MacMini:Recordings:"
-- set this to true to enable movie detection (very crude, just checks the duration)
-- if a recording is detected as being a movie (see movieDetectionDuration below) is placed in the movieOutputFolder instead of the defaultOutputFolder
set movieDetectionEnabled to true
set movieOutputFolder to "Macintosh HD:Users:MacMini:Movie Recordings:"
-- recordings with a scehduled duration (in seconds 5400 = 90 minutes) greater than this will be considered movies instead of tv shows
set movieDetectionDuration to 5399
-- set this to true to enable tv show detection
-- if a recording is not long enough to be a movie, and has a scrapeable name, it is placed in the televisionOutputFolder instead of the defaultOutputFolder
set televisionDetectionEnabled to true
set televisionOutputFolder to "Macintosh HD:Users:MacMini:AeroFS:Daytime TV:"
-- set to true to only process selected recordings, set to false to process all recordings
set onlyExportSelectedRecordings to false
-- set to true to only export if the file will be scrapeable by Plex, set to false to export all files regardless of scrapeability
set onlyExportScrapeableRecordings to false
-- set this to true to enable fixing of shows that did not export because of onlyExportScrapeableRecordings by going to "Edit Info..." in EyeTV and adding the proper SXXEXX to the begining of the episode title. This will let the file export even if onlyExportScrapeableRecordings is true in that situation.
-- Also if you use the useSeasonFolder setting, as long as the beginning of the renamed episode title is in the form (s|S)[0-9]+(e|E)[0-9]+ (i.e. S01E01 or s1e1 etc.) the season will be parsed out and the folder created. If you plan to rename shows in EyeTV and not use the SXXEXX prefix set this to false, otherwise you may get unexpected results.
set treatRenamedRecordingsAsScrapeable to true
-- add to this list any shows which you want to add the year in the title (usually because the name has been reused by multiple shows)
-- this makes sure Plex scrapes the right show
set duplicateNameShows to {"That Show"}
-- list shows that are known to scrape properly by air date (include year in parentheses "()" if show is also in duplicateNameShows above)
set airDateScrapableShows to {"General Hospital", "The View", "The Bold and the Beautiful", "The Ellen DeGeneres Show", "The Young and the Restless"}
-- set to true to create show and season sub folders, set both to false to place all files in root export folder
-- set useShowFolders to true and useSeasonFolders to false to place all seasons in the root show folder
set useShowFolders to true
-- set this to true to create season sub folders, only works if useShowFolders is set to true
set useSeasonFolders to false
-- set to true if you want movies to be put in a folder (it will have the same name as the movie file)
set useMovieFolders to false
-- set to true use underscores instead of spaces when creating folders
set useUnderscoresInFolderNames to false
-- set to true use underscores instead of spaces when naming exported files
set useUnderscoresInFileNames to false
-- set this to true to add the preset as a suffix to the exported file name
set addPresetSuffix to false
-- set the fallback preset if the type of content cannot be identified
tell application "EyeTV" to set defaultPreset to iPod
-- set this to true to use a different preset for movies
set useMoviePreset to false
-- set the default preset for movies from any of the ones in allowedPresets
tell application "EyeTV" to set moviePreset to iPad
-- set this to true to use the override preset for certain tv shows
set useOverridePreset to false
-- set the override preset from any of the ones in allowedPresets
tell application "EyeTV" to set overridePreset to HD720p
-- list the shows you want to use the override preset (include year in parentheses "()" if the show is also in duplicateNameShows above)
set overridePresetShows to {"Supernatural", "Smallville", "Fringe", "Chuck", "The Cape (2011)", "Castle (2009)", "House"}
-- set to true to clear out all SymLinks when creating new ones
-- make sure this is set to false if you are using SymLinks already in your plex folders so they don't get deleted
set deleteAllSymLinksIfAddingNewSymLink to false
-- end modifying settings here ---------------------------------------------------------
-- validate the presets
tell application "EyeTV"
if defaultPreset is not in allowedPresets or moviePreset is not in allowedPresets or (useOverridePreset is true and overridePreset is not in allowedPresets) then
if not silentErrors then display dialog "exiting: one of your presets is invalid"
return
end if
end tell
-- validate the output directories
if not finderItemExists(defaultOutputFolder) or (movieDetectionEnabled is true and not finderItemExists(movieOutputFolder)) or (televisionDetectionEnabled is true and not finderItemExists(televisionOutputFolder)) then
if not silentErrors then display alert "exiting: one of your output folders does not exist"
return
end if
-- initialize lists for generating output file names
set recordingsToExport to {}
set outputFolderNames to {}
set outputShowFolderNames to {}
set outputSeasonFolderNames to {}
set outputFileNames to {}
set outputPresets to {}
set outputFilePaths to {}
-- get recordingList from EyeTV
tell application "EyeTV"
if onlyExportSelectedRecordings then
set recordingList to (selection of programs window)
else
set recordingList to recordings
end if
if (length of recordingList = 0) then
if not silentErrors then display alert "exiting: no recordings to export"
return
end if
end tell
repeat with currentRecording in recordingList
tell application "EyeTV"
-- check if recording is busy
set recordingIsBusy to busy of currentRecording
end tell
if not recordingIsBusy then
tell application "EyeTV"
-- get the location of the recording
set recordingLocation to location of currentRecording
-- get the recording quality
-- set showRecordingQuality to quality of currentRecording
-- get the episode title in EyeTV in case it was modified by the user
set showEpisodeTitleFromEyeTV to episode of currentRecording
-- get the scheduled duration to try and detect if the recording is a movie
set showScheduledDuration to duration of currentRecording
-- display dialog "showScheduledDuration = " & showScheduledDuration
-- determine if recording is a movie
if movieDetectionEnabled is true and showScheduledDuration is greater than movieDetectionDuration then
set recordingIsMovie to true
else
set recordingIsMovie to false
end if
-- get the air date
set {year:y, month:m, day:d} to (the start time of the currentRecording)
set showAirDate to (m & "-" & d)
end tell
-- locate the .eyetvp file which has the property list data about the episode
tell application "Finder"
set recordingFolder to container of file recordingLocation as alias
set recordingPropertiesFile to item 1 of (every paragraph of (do shell script "ls -1 " & (quoted form of POSIX path of recordingFolder) & "/*.eyetvp" as string))
end tell
-- gather data from .plist file
tell application "System Events"
set showTitle to value of property list item "TITLE" of property list item "epg info" of property list file recordingPropertiesFile
set showYear to value of property list item "YEAR" of property list item "epg info" of property list file recordingPropertiesFile
set showSeasonNumber to value of property list item "SEASONID" of property list item "epg info" of property list file recordingPropertiesFile
set showEpisodeNumber to value of property list item "EPISODENUM" of property list item "epg info" of property list file recordingPropertiesFile
set showEpisodeAbstract to value of property list item "ABSTRACT" of property list item "epg info" of property list file recordingPropertiesFile
end tell
-- add year on movies or shows that have had their name reused so Plex picks the right one
if showTitle is in duplicateNameShows or recordingIsMovie is true then set showTitle to showTitle & " (" & showYear & ")"
-- remove illegal characters from the show title
set showTitleClean to my cleanText(showTitle)
-- initialize nameIsScrapeable
set nameIsScrapeable to false
-- determine the output file name
if recordingIsMovie then
-- if it is a movie just name it with the title
set outputFileName to showTitleClean
set nameIsScrapeable to true
else if showSeasonNumber is not "" and showEpisodeNumber is not "" then
-- determine if we need leading zeroes
set seasonLeadingZero to ""
set episodeLeadingZero to ""
if showSeasonNumber as number is less than 10 then set seasonLeadingZero to "0"
if showEpisodeNumber as number is less than 10 then set episodeLeadingZero to "0"
-- if we have valid season and episode then set the scrapeable name
set outputFileName to showTitleClean & " S" & seasonLeadingZero & showSeasonNumber & "E" & episodeLeadingZero & showEpisodeNumber
set nameIsScrapeable to true
else if showTitle is not in airDateScrapableShows and (showEpisodeTitleFromEyeTV is not "" or showEpisodeAbstract is not "") then
-- If we have an episode title in the Abstract or in EyeTV, use the episode title to help you figure out the episode when renaming later
if showEpisodeTitleFromEyeTV is not equal to showEpisodeAbstract then
-- user has modified the episode title in EyeTV, so we use the EyeTV title. This allows you to put SXXEXX in the beginning of the episode title manually if you know which episode it is
set outputFileName to showTitleClean & " " & my cleanText(showEpisodeTitleFromEyeTV)
ignoring case
-- check if we should treat the renamed recording as scrapeable
if treatRenamedRecordingsAsScrapeable is true and first character of showEpisodeTitleFromEyeTV is "S" then
-- we need to make a season folder, try to extract it from the modified name
-- I am assuming that since you have modified the episode title from the original one and it now starts with an S or s, it is in the SXXEXX format
-- So I will try to extract the season number from that SXXEXX
-- get position of the first "e" or "E"
set ePosition to offset of "E" in showEpisodeTitleFromEyeTV
if ePosition is greater than 2 then
-- there was an "E" or "e" somewhere, so extract the text between the "S" and the "E"
set extractedSeasonText to listToText(text 2 thru (ePosition - 1) of characters of showEpisodeTitleFromEyeTV, "")
-- convert it to a number in case it has leading zeroes
set extractedSeasonNumber to extractedSeasonText as number
-- check if we got a valid number out of it
if extractedSeasonNumber is greater than -1 then
-- we got a good number, so set it as the season number and mark the recording as scrapeable
set showSeasonNumber to extractedSeasonNumber as text
set nameIsScrapeable to true
end if
end if
end if
end ignoring
else
-- just use the original episode title from the abstract, not likely to be scrapeable
set outputFileName to showTitleClean & " - " & my cleanText(showEpisodeAbstract)
end if
else
-- no episode title available or it is an air date scrapeable show so add air date
set outputFileName to showTitleClean & " " & showAirDate
if showTitle is in airDateScrapableShows then
-- show is known to be scrapeable by air date, so set recording as scrapeable
set nameIsScrapeable to true
end if
end if
if outputFileName is in outputFileNames then
-- if we have a duplicate file name, we probably recorded 2 episodes of the same show on the same day and the show does not have guide data
set theTimeStamp to (do shell script "date +%H%M%S")
-- add a timestamp so there is no name conflict
set outputFileName to outputFileName & " " & theTimeStamp
-- wait one second (so any other recordings get a different timestamp suffix
delay 1
end if
-- determine if recording should be exported
set okToExport to (not onlyExportScrapeableRecordings or (onlyExportScrapeableRecordings and nameIsScrapeable)) as boolean
-- if our filename is not empty and recording should be exported, proceed
if outputFileName is not "" and okToExport is true then
tell application "EyeTV"
-- choose correct preset
if useOverridePreset is true and showTitle is in overridePresetShows then
set chosenPreset to overridePreset
else if useMoviePreset is true and recordingIsMovie is true then
set chosenPreset to moviePreset
else
set chosenPreset to defaultPreset
end if
-- get the preset extension
set chosenPresetExtension to my getPresetExtension(chosenPreset)
end tell
-- choose correct output folder
set chosenOutputFolder to defaultOutputFolder
if movieDetectionEnabled is true and recordingIsMovie is true then
set chosenOutputFolder to movieOutputFolder
else if televisionDetectionEnabled is true and nameIsScrapeable is true then
set chosenOutputFolder to televisionOutputFolder
end if
-- initialize subfolder names
set showFolderName to ""
set seasonFolderName to ""
set outputFolderPath to chosenOutputFolder
-- check if we are making show folders
if nameIsScrapeable then
if recordingIsMovie is true then
if useMovieFolders is true then
set showFolderName to showTitleClean
-- add underscores to the folder name, if the feature is enabled
if useUnderscoresInFolderNames is true then set showFolderName to changeSpacesToUnderscores(showFolderName)
-- add folder to output path
set outputFolderPath to outputFolderPath & showFolderName & ":"
end if
else if useShowFolders is true and showTitleClean is not "" then
-- set show sub folder name
set showFolderName to showTitleClean
-- add underscores to the folder name, if the feature is enabled
if useUnderscoresInFolderNames is true then set showFolderName to changeSpacesToUnderscores(showFolderName)
-- add folder to output path
set outputFolderPath to outputFolderPath & showFolderName & ":"
-- check if we are making season folders
if useSeasonFolders is true and showSeasonNumber is not "" then
-- set season sub folder name
set seasonFolderName to "Season " & showSeasonNumber
-- add underscores to the folder name, if the feature is enabled
if useUnderscoresInFolderNames is true then set seasonFolderName to changeSpacesToUnderscores(seasonFolderName)
-- add folder to output path
set outputFolderPath to outputFolderPath & seasonFolderName & ":"
end if
end if
end if
-- add preset suffix if specified
if addPresetSuffix is true then tell application "EyeTV" to set outputFileName to outputFileName & " " & (chosenPreset as text)
-- add underscores to file name if specified
if useUnderscoresInFileNames is true then set outputFileName to changeSpacesToUnderscores(outputFileName)
-- build the output file path
set outputFilePath to outputFolderPath & outputFileName & chosenPresetExtension
copy currentRecording to the end of recordingsToExport
copy chosenOutputFolder to the end of outputFolderNames
copy showFolderName to the end of outputShowFolderNames
copy seasonFolderName to the end of outputSeasonFolderNames
copy outputFileName to the end of outputFileNames
tell application "EyeTV" to copy chosenPreset to the end of outputPresets
copy outputFilePath to the end of outputFilePaths
end if
end if
end repeat
-- use for debugging
-- display dialog my listToText(item 1 of recordingsToExport, return) with title "Recordings To Export"
-- display dialog my listToText(outputFileNames, return) with title "Output File Names"
-- display dialog my listToText(outputFilePaths, return) with title "Output File Paths"
-- display dialog my listToText(outputPresets, return) with title "Output Presets"
-- exit if there are no recordings to export
set recordingsToExportCount to length of recordingsToExport
if recordingsToExportCount = 0 then
if not silentErrors then display alert "exiting: no recordings to export"
return
end if
-- clear out any broken symlinks
if deleteAllSymLinksIfAddingNewSymLink and "SymLink" is in outputPresets then
do shell script "find -L " & (quoted form of POSIX path of defaultOutputFolder) & " -type l -delete"
if movieDetectionEnabled then do shell script "find -L " & (quoted form of POSIX path of movieOutputFolder) & " -type l -delete"
if televisionDetectionEnabled then do shell script "find -L " & (quoted form of POSIX path of televisionOutputFolder) & " -type l -delete"
end if
-- export recordings
repeat with recordingIndex from 1 to recordingsToExportCount
-- get the details of the recording to export from the lists
set theRecording to item recordingIndex of recordingsToExport
set theOutputFolder to item recordingIndex of outputFolderNames
set theShowFolderName to item recordingIndex of outputShowFolderNames
set theSeasonFolderName to item recordingIndex of outputSeasonFolderNames
tell application "EyeTV" to set theChosenPreset to item recordingIndex of outputPresets
set theOutputFilePath to item recordingIndex of outputFilePaths
-- create subfolders if needed
if (useShowFolders is true or useMovieFolders is true) and theShowFolderName is not "" then
tell application "Finder"
set theShowFolderPath to (theOutputFolder & theShowFolderName) as text
if not (exists folder theShowFolderPath) then
make new folder at alias theOutputFolder with properties {name:theShowFolderName}
end if
if useSeasonFolders and theSeasonFolderName is not "" then
set theSeasonFolderPath to (theShowFolderPath & ":" & theSeasonFolderName) as text
if not (exists folder theSeasonFolderPath) then
make new folder at alias theShowFolderPath with properties {name:theSeasonFolderName}
end if
end if
end tell
end if
-- if exporting is enabled, export the recording
if exportingEnabled then
if theChosenPreset is not "SymLink" then
try
tell application "EyeTV" to export from theRecording to theOutputFilePath as theChosenPreset replacing no
on error
if not silentErrors then display alert "error exporting the file " & theOutputFilePath & " as " & (theChosenPreset as text)
end try
else
tell application "EyeTV" to set theRecordingLocation to location of theRecording
tell application "Finder"
set theRecordingFolder to container of file theRecordingLocation as alias
set theRecordingRawFile to item 1 of (every paragraph of (do shell script "ls -1 " & (quoted form of POSIX path of theRecordingFolder) & "/*.mpg" as string))
end tell
do shell script "ln -s " & (quoted form of POSIX path of theRecordingRawFile) & " " & (quoted form of POSIX path of theOutputFilePath)
end if
end if
end repeat
end run
on finderItemExists(thePath)
try
set thePath to thePath as alias
on error
return false
end try
return true
end finderItemExists
to listToText(theList, delimiter)
set astid to AppleScript's text item delimiters
set AppleScript's text item delimiters to delimiter
set textResult to (theList as string)
set AppleScript's text item delimiters to astid
return textResult
end listToText
to textToList(theText, delimiter)
set astid to AppleScript's text item delimiters
set AppleScript's text item delimiters to delimiter
set listResult to text items of theText
set AppleScript's text item delimiters to astid
return listResult
end textToList
to cleanText(theText)
set theCleanTextList to {}
set illegalCharacters to {(ASCII character of 60), (ASCII character of 62), (ASCII character of 58), (ASCII character of 34), (ASCII character of 47), (ASCII character of 92), (ASCII character of 124)}
repeat with currentCharacter in the characters of theText
set theCharacter to currentCharacter as text
if theCharacter is not in illegalCharacters then
set the end of theCleanTextList to theCharacter
end if
end repeat
return my listToText(theCleanTextList, "")
end cleanText
to changeSpacesToUnderscores(theText)
set theNewTextList to {}
repeat with currentCharacter in the characters of theText
set theCharacter to currentCharacter as text
if theCharacter is " " then
set the end of theNewTextList to "_"
else
set the end of theNewTextList to theCharacter
end if
end repeat
return my listToText(theNewTextList, "")
end changeSpacesToUnderscores