-- 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