Jump to content

Sky Slate Blueberry Blackcurrant Watermelon Strawberry Orange Banana Apple Emerald Chocolate
Photo

SceneRenamer - Renames "Scene" releases of TV Show


  • Please log in to reply
56 replies to this topic
strictlyfocused02
  • Members
  • 64 posts
  • Last active: Jul 27 2014 03:43 PM
  • Joined: 21 Jan 2009

f2QcE.png

Description
The naming convention for "Scene" releases of TV Shows dictates that each file will have somewhat cryptic and long file name and usually doesn't contain the episode title. This bothered me ... so here is my solution.
Features
- Parses show name from filename
- Parses season and episode numbers from filename
- Uses show name along with season number and episode number to connect to TheTVDB.com's extensive database
- Renames the file based on info obtained from TheTVDB.com
- Add an entire folder (great for seasons!)
- Add an individual file(s) (now with multi-select!)
- Right-Click context menu with useful entries (Open Item, Open Folder, Remove Item, Item Properties)
- 4 different output naming formats (Shown in screenshot)
- Ability to pad single digit episode and season numbers with a zero
- Open Folder dialog box has an edit field so you can just paste a directory instead of using the clunky tree navigation pane
- settings.ini file to set the approved filetypes and also set the directory Add Folder/File starts in (NEW!)
- Drag and Drop file support (NEW!)
- A full changelog can be found at the bottom of the script source code
Instructions
1 - Add a file or folder using the appropriate button at the top of the window
2 - If needed, remove any items you do not wish to scan against TheTVDB.com's database via the right-click menu
3 - Press "Get TVDB Info" and wait for each row to have its "Preview" column filled
4 - Remove any items that you do not wish to be renamed
5 - Press "Rename Files"
Notes
- Supports many "Scene" naming conventions (along with minor variations)
- Show.Name.s01e01.avi
- Show.Name.01x06.avi
- Show.Name.104.avi- Show title is determined by looking behind the season and episode information
- If the Naming scheme is changed you have to re-fetch the TVDB info again to apply the change
- Titans "XPath" function was used so major thanks to Titan for that!
- This is a complete re-write, but same concept, of my previous script located here
- If the script is unable to get the episode info from TheTVDB it will rename the file as close as possible to the selected naming format (i.e. "Greek - 03x01.avi" if no episode title is present)
- Due to some of recent changes made to the script Ive chosen to upload a nice little zip file to autohotkey.net which includes a compiled version (source included ofc!) of the script. More specifically, having moved xpath to its own subdir and the addition of an ini settings file the script has become more difficult to just "copypasta" and have everything work.
[/list]As always, any tips, suggestions, or any constructive criticism is not only welcomed, but encouraged!

Download
SceneRenamer 1.71
Last updated: 2014-Jul-27



madrano
  • Members
  • 2 posts
  • Last active: Dec 19 2009 12:51 PM
  • Joined: 23 Aug 2008
fantastic script thx

Thrawn
  • Members
  • 30 posts
  • Last active: Apr 05 2011 06:07 PM
  • Joined: 12 May 2008
i'm coding something similar using thetvdb.com's api. currently in development, the configuration / update part are not fully implemented - mainly gui stuff. but what you can see in the screenshots works - in a perfectly usable speed. you won't see any filenames anymore, so it doesnt really matter how unreadable they are. currently its using xpath, gdip and some hacks for multiple scrollable areas (i am planning to implement majkinetors [module] Scroller 1.0 as soon as its able to handle scrollable panels).

Posted Image


Posted Image



ashius
  • Members
  • 3 posts
  • Last active: Mar 27 2011 12:09 PM
  • Joined: 20 Oct 2009
This is an awesome script! Thanks for sharing it.

I have modified it so on launch it automatically scans my 'new shows folder'. I also took off the preceding 0 on the season number too.

The only thing I find a bit clunky is when a show has more than one search result. I have been trying to think of a way to make it easier, I have a couple of ideas but no idea how to implement them.

1. After a match has been confirmed, in the context menu would be an item to store that ShowName with its corresponding SeriesName and SeriesIDNum for future matches. I guess this would be stored in a separate ini file, that the script checks first before hitting TheTVDB.

2. Instead of a series of yes/no dialog's the result could be presented in a list box format.

Do you think either of them would be possible?

ashius
  • Members
  • 3 posts
  • Last active: Mar 27 2011 12:09 PM
  • Joined: 20 Oct 2009
Well I gave the my number 1 option a shot myself and came up with the below. It seems to work well enough, tho I'm sure it hasn't been done the best way possible.

I'm pretty sure i commented on any changes I made to the code

; SceneRenamer by strictlyfocused02
;
; AutoHotkey Version: 1.0.48+
;
; Script Function:
;   Extracts season and episode info from the filename
;   and uses that to retreive info from TheTVDB.com to rename
;   the file to a user-specified format

;   Special thanks to TheTVDB.com
;   This project would not have been possible without their top-notch API

#Include xpath.ahk

#NoEnv
SendMode, Input
SetWorkingDir, %A_ScriptDir%

Gui, Add, Button, Default gButtonAddFolder, &Add folder
Gui, Add, Button, x+20 gButtonAddFile, &Add file
Gui, Add, Button, x+20 gButtonClear, &Clear list
Gui, Add, Button, x+20 TVRenameFolder, &TV Rename Folder ;Addtional button for scaning my default folder
Gui, Add, Button, x+20 ButtonAddRule, &Add Rule ; Add rule button


Gui, Add, ListView, xm r25 w800 vMyListView, Name|Preview|Directory|Extension|TVDB Series ID No|Show Name ;Added collum for getting the selected Show Name

Gui, Add, DropDownList, y+7 w250 AltSubmit vNameScheme, (Show Title) - (SS)x(EE) - (Episode Title)||(Show Title) - S(SS)E(EE) - (Episode Title)|(SS)x(EE) - Episode Title|S(SS)E(EE) - (Episode Title)
Gui, Add, Checkbox, x+30 Checked vZero, Pad with zero?
Gui, Add, Button, x+200 gButtonGetTVDBInfo, &Get TVDB Info
Gui, Add, Button, x+60 gButtonRename, &Rename files

Menu, MyContextMenu, Add, Open, ContextOpenFile
Menu, MyContextMenu, Add, Properties, ContextProperties
Menu, MyContextMenu, Add, Remove item, ContextRemoveItem

Gui, Show
Gosub, ButtonTVRenameFolder ;This is so it starts scaning once opened
Return



GuiClose:
   ExitApp

GuiContextMenu:
   If A_GuiControl <> MyListView
       Return
   Menu, MyContextMenu, Show, %A_GuiX%, %A_GuiY%
   Return

;Add new rule to the rules.ini
ButtonAddRule:
	FocusedRowNumber := LV_GetNext(0, "F")
	LV_GetText(SeriesIDNum, FocusedRowNumber, 5)
	LV_GetText(ShowName, FocusedRowNumber, 6) 
	
	;check for rules.ini and create if it doesnt exist
	IfNotExist, rules.ini
		IniWrite, AllRuleNames, rules.ini, Rules, AllRuleNames 
	Else
	IniRead, AllRuleNames, rules.ini, Rules, AllRuleNames
	;Check the rule doesnt already exist
	Loop, Parse, AllRuleNames, |
		{
			thisRule = %A_LoopField%
			if thisRule = %ShowName%
			{
				Msgbox %ShowName% already has a rule
				Return
			}
		}
	IniWrite, %AllRuleNames%%ShowName%|, rules.ini, Rules, AllRuleNames 
	IniWrite, %ShowName%, rules.ini, %ShowName%, SeriesName
	IniWrite, %SeriesIDNum%, rules.ini, %ShowName%, SeriesIDNum
   Return
   
   
ContextOpenFile:
ContextProperties:
   FocusedRowNumber := LV_GetNext(0, "F")
   If not FocusedRowNumber
      return
   LV_GetText(FileName, FocusedRowNumber, 1)
   LV_GetText(FileDir, FocusedRowNumber, 3)
   IfInString A_ThisMenuItem, Open
      Run %FileDir%\%FileName%,, UseErrorLevel
   Else
      Run Properties "%FileDir%\%FileName%",, UseErrorLevel
   If ErrorLevel
      MsgBox Could not perform requested action on "%FileDir%\%FileName%".
   return
   
ContextRemoveItem:
   RowNumber = 0
   Loop
   {
      RowNumber := LV_GetNext(RowNumber - 1)
      If not RowNumber
           Break
      LV_Delete(RowNumber)
   }
   Return

ButtonAddFolder:
   Gui +OwnDialogs
   FileSelectFolder, TargetFolder,, 3, Select a folder:
   If not TargetFolder  ; The user pressed cancel
       Return
   StringRight, LastChar, TargetFolder, 1
   If LastChar = \
      StringTrimRight, TargetFolder, TargetFolder, 1
   GuiControl, -Redraw, MyListView ; Improves performance by disabling redrawing
   Loop %TargetFolder%\*.*
   {
      FileName := A_LoopFileFullPath
      SplitPath, FileName,,, FileExt  ; Get the file extension
      If FileExt in avi,mkv,mp4
         LV_Add(Row, A_LoopFileName, "", A_LoopFileDir, FileExt)
   }
   GuiControl, +Redraw, MyListView  ; Turn redrawing back on
   LV_ModifyCol()  ; Resize each column to fit
   LV_ModifyCol(2, 60)  ; Expand "Preview" to keep the header visible
   LV_ModifyCol(4, 60)  ; Expand "Extension" to keep the header visible
   LV_ModifyCol(5, 110)  ; Expand "TVDB Series ID No" to keep the header visible
   Return

   ;Auto load a default folder and scan it
 ButtonTVRenameFolder:  
   TargetFolder := "\\SPOON\Downloads\TV Rename\"
   Loop %TargetFolder%\*.*
   {
      FileName := A_LoopFileFullPath
      SplitPath, FileName,,, FileExt  ; Get the file extension
      If FileExt in avi,mkv,mp4
         LV_Add(Row, A_LoopFileName, "", A_LoopFileDir, FileExt)
   }
   GuiControl, +Redraw, MyListView  ; Turn redrawing back on
   LV_ModifyCol()  ; Resize each column to fit
   LV_ModifyCol(2, 60)  ; Expand "Preview" to keep the header visible
   LV_ModifyCol(4, 60)  ; Expand "Extension" to keep the header visible
   LV_ModifyCol(5, 110)  ; Expand "TVDB Series ID No" to keep the header visible
   Gosub, ButtonGetTVDBInfo
   Return
   
   
   
ButtonAddFile:
   Gui +OwnDialogs
   FileSelectFile, TargetFile
   If not TargetFile
      Return
   SplitPath, TargetFile,,, FileExt  ; Get the file extension
   If FileExt in avi,mkv,mp4
   {
      SplitPath, TargetFile, FileName, TargetFolder
      LV_Add(Row, FileName, "", TargetFolder, FileExt)
      LV_ModifyCol()  ; Resize each column to fit
      LV_ModifyCol(2, 60)  ; Expand "Preview" to keep the header visible
      LV_ModifyCol(4, 60)  ; Expand "Extension" to keep the header visible
      LV_ModifyCol(5, 110)  ; Expand "TVDB Series ID No" to keep the header visible
   }
   Return

ButtonClear:
   TargetFolder =
   LV_Delete()
   Return

ButtonGetTVDBInfo:
   LV_GetText(LVFileName, 1, 1)  ; Get the filename
   If not LVFileName
   {
      MsgBox, 0,Fatal Error!, You must select a file or folder before connecting to TheTVDB.com!
      Return
   }
   Loop
   {
      RowNumber = %A_Index%
      LV_GetText(LVFileName, RowNumber, 1)  ; Get the filename
      If not LVFileName  ; Break the loop at the end of the list
         Break
      LV_GetText(LVFileDir, RowNumber, 3)  ; Get the file directory
      LV_GetText(LVFileExt, RowNumber, 4)  ; Get the file extension
      ShowInfo := GetTVDBShows(GetShowName(LVFileName))
      StringSplit, OutputArray, ShowInfo, `,
      ShowName = %OutputArray1%
      SeriesIDNo = %OutputArray2%
      SeasonNumber := GetSeasonNumber(LVFileName)
      EpisodeNumber := GetEpisodeNumber(LVFileName)
      If SeriesIDNo
      {
         EpisodeInfo := GetTVDBEpisodes(SeriesIDNo, SeasonNumber, EpisodeNumber)
         StringSplit, OutputArray, EpisodeInfo, `,
         SeasonNumber = %OutputArray1%
         EpisodeNumber = %OutputArray2%
         EpisodeTitle = %OutputArray3%
      }
      GuiControlGet, NamingScheme,, NameScheme
      If NamingScheme = 1
      {
         If EpisodeTitle
            NewFileName = %ShowName% - %SeasonNumber%x%EpisodeNumber% - %EpisodeTitle%.%LVFileExt%
         Else
            NewFileName = %ShowName% - %SeasonNumber%x%EpisodeNumber%.%LVFileExt%
      }
      Else if NamingScheme = 2
      {
         If EpisodeTitle
            NewFileName = %ShowName% - S%SeasonNumber%E%EpisodeNumber% - %EpisodeTitle%.%LVFileExt%
         Else
            NewFileName = %ShowName% - S%SeasonNumber%E%EpisodeNumber%.%LVFileExt%
      }
      Else If NamingScheme = 3
      {
         If EpisodeTitle
            NewFileName = %SeasonNumber%x%EpisodeNumber% - %EpisodeTitle%.%LVFileExt%
         Else
            NewFileName = %SeasonNumber%x%EpisodeNumber%.%LVFileExt%
      }
      Else If NamingScheme = 4
      {
         If EpisodeTitle
            NewFileName = S%SeasonNumber%E%EpisodeNumber% - %EpisodeTitle%.%LVFileExt%
         Else
            NewFileName = S%SeasonNumber%E%EpisodeNumber%.%LVFileExt%
      }

      LV_Modify(RowNumber, Col1, LVFileName, NewFileName, LVFileDir, LVFileExt, SeriesIDNo, ShowName)
      LV_ModifyCol()
      LV_ModifyCol(4, 60)
      LV_ModifyCol(5, 110)  ; Expand "TVDB Series ID No" to keep the header visible
   }
   Return

ButtonRename:
   Loop
   {
      RowNumber = %A_Index%
      LV_GetText(LVFileName, RowNumber, 1)  ; Get the original filename
      If not LVFileName  ; Break the loop at the end of the list
         Break
      LV_GetText(LVNewFileName, RowNumber, 2)  ; Get the new filename
      FileMove, %TargetFolder%\%LVFileName%, %TargetFolder%\%LVNewFileName%
   }
   RenameCount := RowNumber - 1
   MsgBox, 0, Success!, %RenameCount% files have been renamed!`n`nRefreshing file list...
   LV_Delete()
   Loop %TargetFolder%\*.*
   {
      FileName := A_LoopFileFullPath
      If not FileName
         Break
      SplitPath, FileName,,, FileExt  ; Get the file extension
      If FileExt in avi,mkv,mp4
         LV_Add(Row, A_LoopFileName, "", A_LoopFileDir, FileExt)
   }
   GuiControl, +Redraw, MyListView  ; Turn redrawing back on
   LV_ModifyCol()  ; Resize each column to fit
   LV_ModifyCol(2, 60)  ; Expand "Preview" to keep the header visible
   LV_ModifyCol(4, 60)  ; Expand "Extension" to keep the header visible
   LV_ModifyCol(5, 110)  ; Expand "TVDB Series ID No" to keep the header visible
   Return

;Provide a filename (greek.s01e01.avi) and this will hopefully detect and return the show name
GetShowName(FileName)
{
   IfInString, FileName, .
      StringReplace, NormalName, FileName, ., %A_Space%, All
   IfInString, NormalName, _
      StringReplace, NormalName, NormalName, _, %A_Space%, All
   If RegExMatch(NormalName, "i)s[0-9][0-9]? ?e[0-9][0-9]?", SeasonAndEpisode)
   {
      StringGetPos, SeasonAndEpisodePos, NormalName, %SeasonAndEpisode%
      StringLeft, ShowName, NormalName, (SeasonAndEpisodePos - 1)
   }
   Else If RegExMatch(NormalName, "i)[0-9][0-9]?x[0-9][0-9]?", SeasonAndEpisode)
   {
      StringGetPos, SeasonAndEpisodePos, NormalName, %SeasonAndEpisode%
      StringLeft, ShowName, NormalName, (SeasonAndEpisodePos - 1)
   }
   Else If RegExMatch(NormalName, "[0-9][0-9][0-9][0-9]?", SeasonAndEpisode)
   {
      StringGetPos, SeasonAndEpisodePos, NormalName, %SeasonAndEpisode%
      StringLeft, ShowName, NormalName, (SeasonAndEpisodePos - 1)
   }
   Loop
   {
      StringRight, LastChar, ShowName, 1
      If (LastChar = "-" or LastChar = " ")
         StringTrimRight, ShowName, ShowName, 1
      Else
         Break
   }
   Return ShowName
}

;Provide a filename (greek.s01e01.avi) and this will hopefully detect and return the season number
GetSeasonNumber(FileName)
{
   If RegExMatch(FileName, "i)s\K[0-9][0-9]?.?e[0-9][0-9]?", SeasonAndEpisode)
   {
      StringGetPos, EPos, SeasonAndEpisode, e
      StringLeft, SeasonNumber, SeasonAndEpisode, %EPos%
      IfInString, SeasonNumber, .
         StringTrimRight, SeasonNumber, SeasonNumber, 1
      IfInString, SeasonNumber, 0
      {
         StringGetPos, ZeroLoc, SeasonNumber, 0
         If ZeroLoc = 0
            StringTrimLeft, SeasonNumber, SeasonNumber, 1
      }
         
   }
   Else If RegExMatch(FileName, "i)[0-9][0-9]?x[0-9][0-9]?", SeasonAndEpisode)
   {
      StringGetPos, XPos, SeasonAndEpisode, x
      StringLeft, SeasonNumber, SeasonAndEpisode, %XPos%
      IfInString, SeasonNumber, 0
      {
        StringGetPos, ZeroLoc, SeasonNumber, 0
         If ZeroLoc = 0
            StringTrimLeft, SeasonNumber, SeasonNumber, 1
      }
   }
   Else If RegExMatch(FileName, "[0-9][0-9][0-9][0-9]?", SeasonAndEpisode)
   {
      StringTrimRight, SeasonNumber, SeasonAndEpisode, 2
      IfInString, SeasonNumber, 0
      {
         StringGetPos, ZeroLoc, SeasonNumber, 0
         If ZeroLoc = 0
            StringTrimLeft, SeasonNumber, SeasonNumber, 1
      }
   }
   Return SeasonNumber
}

;Provide a filename (greek.s01e01.avi) and this will hopefully detect and return the episode number
GetEpisodeNumber(FileName)
{
   If RegExMatch(FileName, "i)s\K[0-9][0-9]?.?e[0-9][0-9]?", SeasonAndEpisode)
   {
      StringGetPos, EPos, SeasonAndEpisode, e
      StringRight, EpisodeNumber, SeasonAndEpisode, %EPos%
      IfInString, EpisodeNumber, e
         StringTrimLeft, EpisodeNumber, EpisodeNumber, 1
      IfInString, EpisodeNumber, 0
      {
         StringGetPos, ZeroLoc, EpisodeNumber, 0
         If ZeroLoc = 0
            StringTrimLeft, EpisodeNumber, EpisodeNumber, 1
      }
   }
   Else If RegExMatch(FileName, "i)[0-9][0-9]?x[0-9][0-9]?", SeasonAndEpisode)
   {
      StringGetPos, XPos, SeasonAndEpisode, x
      StringRight, EpisodeNumber, SeasonAndEpisode, %XPos%
      IfInString, EpisodeNumber, 0
      {
         StringGetPos, ZeroLoc, EpisodeNumber, 0
         If ZeroLoc = 0
            StringTrimLeft, EpisodeNumber, EpisodeNumber, 1
      }
   }
   Else If RegExMatch(FileName, "[0-9][0-9][0-9][0-9]?", SeasonAndEpisode)
   {
      StringRight, EpisodeNumber, SeasonAndEpisode, 2
      IfInString, EpisodeNumber, 0
      {
         StringGetPos, ZeroLoc, EpisodeNumber, 0
         If ZeroLoc = 0
            StringTrimLeft, EpisodeNumber, EpisodeNumber, 1
      }
   }
   Return EpisodeNumber
}


;Provide a show name (greek) and it will return the TVDB data for the show name (Greek) and series ID (80301) as a CSV (Greek,80301)
GetTVDBShows(ShowName)
{
;Check the rules.ini for a match
		IniRead, AllRuleNames, rules.ini, Rules, AllRuleNames
		Loop, Parse, AllRuleNames, |
		{
			thisRule = %A_LoopField%
			;Continue on if there is no rule
			if (thisRule = "ERROR") or (thisRule = "")
			{
				Continue
			}
			if (thisRule = ShowName)
			{
			IniRead, SeriesName, rules.ini, %thisRule%, SeriesName
			IniRead, SeriesIDNum, rules.ini, %thisRule%, SeriesIDNum
			;Jump to the end of GetTVDBShows if match ins found in rules.
			goto finish
			}
		}
   IfExist, Series_ID.xml
      FileDelete, Series_ID.xml
   UrlDownloadToFile, http://www.thetvdb.com/api/GetSeries.php?seriesname="%ShowName%", Series_ID.xml
   XPath_Load(xml, "Series_ID.xml")
   SeriesNameNodeCount := XPath(xml, "/Data/Series/SeriesName/Count()")
   If SeriesNameNodeCount = 1
   {
      SeriesIDNum := XPath(xml, "/Data/Series/seriesid/text()")
      SeriesName := XPath(xml, "/Data/Series/SeriesName/text()")
   }
   Else If SeriesNameNodeCount >= 2
   {
      SeriesIDNum := XPath(xml, "/Data/Series/seriesid/text()")
      SeriesName := XPath(xml, "/Data/Series/SeriesName/text()")
      SeriesOverview := XPath(xml, "/Data/Series/Overview/text()")
      StringSplit, OutputArraySID, SeriesIDNum, `,
      StringSplit, OutputArraySN, SeriesName, `,
      StringSplit, OutputArraySO, SeriesOverview, `,
	  Loop, %SeriesNameNodeCount%
      {
         SeriesIDNum := OutputArraySID%A_Index%
         SeriesName := OutputArraySN%A_Index%
         SeriesOverview := OutputArraySO%A_Index%
         IfInString, SeriesOverview, ,`;
            StringReplace, SeriesOverview, SeriesOverview, ,`;, `,, All
         If not SeriesOverview
            SeriesOverview = (No show description provided)
         MsgBox, 3, Which show do you want?, %SeriesName%`n`n%SeriesOverview%
         IfMsgBox, Yes
            Break
         IfMsgBox, No
         {
            NoCount = %A_Index%
            If NoCount = %SeriesNameNodeCount%
            {
               SeriesName =
               SeriesIDNum =
               MsgBox, 0, Fatal Error!, No more show name suggestions provided!`n`nI will use the show name parsed from the filename and move on to the next row...
            }
         }
         IfMsgBox, Cancel
            Return
      }
   }
   finish:
   If not SeriesName
      SeriesName = %ShowName%
   FileDelete, Series_ID.xml
   Data = %SeriesName%,%SeriesIDNum%
   Return Data
}

;Provide the "TVDB series ID", "season number" and "episode number" and this will return the matching TVDB season number,episode number, and episode title as a CSV (3,1,The Day After)
GetTVDBEpisodes(SeriesIDNum, SeasonNum, EpisodeNum)
{
   IfExist, Episode_Info.xml
      FileDelete, Episode_Info.xml
   UrlDownloadToFile, http://www.thetvdb.com/api/563E39CDC7F666DF/series/%SeriesIDNum%/default/%SeasonNum%/%EpisodeNum%/en.xml, Episode_Info.xml
   XPath_Load(xml, "Episode_Info.xml")
   SeasonNumber := XPath(xml, "/Data/Episode/SeasonNumber/text()")
   EpisodeNumber := XPath(xml, "/Data/Episode/EpisodeNumber/text()")
   EpisodeTitle := XPath(xml, "/Data/Episode/EpisodeName/text()")
   FileDelete, Episode_Info.xml
   If not SeasonNumber
      SeasonNumber = %SeasonNum%
   If not EpisodeNumber
      EpisodeNumber = %EpisodeNum%
   IfInString, EpisodeTitle, ?
      StringReplace, EpisodeTitle, EpisodeTitle, ?,, All
   GuiControlGet, PadZero, , Zero
   If PadZero = 1
   {
      SeasonLen := StrLen(SeasonNumber)
      EpisodeLen := StrLen(EpisodeNumber)
      ;If SeasonLen = 1
       ;  SeasonNumber = 0%SeasonNumber%
      If EpisodeLen = 1
         EpisodeNumber = 0%EpisodeNumber%
   }
   K = %SeasonNumber%,%EpisodeNumber%,%EpisodeTitle%
   Return K
}

Any feedback would be great, I haven't really done anything like this before, and I'm sure I have made some mistakes

strictlyfocused02
  • Members
  • 64 posts
  • Last active: Jul 27 2014 03:43 PM
  • Joined: 21 Jan 2009

Well I gave the my number 1 option a shot myself and came up with the below. It seems to work well enough, tho I'm sure it hasn't been done the best way possible.

I'm pretty sure i commented on any changes I made to the code

; SceneRenamer by strictlyfocused02
;
; AutoHotkey Version: 1.0.48+
;
; Script Function:
;   Extracts season and episode info from the filename
;   and uses that to retreive info from TheTVDB.com to rename
;   the file to a user-specified format

;   Special thanks to TheTVDB.com
;   This project would not have been possible without their top-notch API

#Include xpath.ahk

#NoEnv
SendMode, Input
SetWorkingDir, %A_ScriptDir%

Gui, Add, Button, Default gButtonAddFolder, &Add folder
Gui, Add, Button, x+20 gButtonAddFile, &Add file
Gui, Add, Button, x+20 gButtonClear, &Clear list
Gui, Add, Button, x+20 TVRenameFolder, &TV Rename Folder ;Addtional button for scaning my default folder
Gui, Add, Button, x+20 ButtonAddRule, &Add Rule ; Add rule button


Gui, Add, ListView, xm r25 w800 vMyListView, Name|Preview|Directory|Extension|TVDB Series ID No|Show Name ;Added collum for getting the selected Show Name

Gui, Add, DropDownList, y+7 w250 AltSubmit vNameScheme, (Show Title) - (SS)x(EE) - (Episode Title)||(Show Title) - S(SS)E(EE) - (Episode Title)|(SS)x(EE) - Episode Title|S(SS)E(EE) - (Episode Title)
Gui, Add, Checkbox, x+30 Checked vZero, Pad with zero?
Gui, Add, Button, x+200 gButtonGetTVDBInfo, &Get TVDB Info
Gui, Add, Button, x+60 gButtonRename, &Rename files

Menu, MyContextMenu, Add, Open, ContextOpenFile
Menu, MyContextMenu, Add, Properties, ContextProperties
Menu, MyContextMenu, Add, Remove item, ContextRemoveItem

Gui, Show
Gosub, ButtonTVRenameFolder ;This is so it starts scaning once opened
Return



GuiClose:
   ExitApp

GuiContextMenu:
   If A_GuiControl <> MyListView
       Return
   Menu, MyContextMenu, Show, %A_GuiX%, %A_GuiY%
   Return

;Add new rule to the rules.ini
ButtonAddRule:
	FocusedRowNumber := LV_GetNext(0, "F")
	LV_GetText(SeriesIDNum, FocusedRowNumber, 5)
	LV_GetText(ShowName, FocusedRowNumber, 6) 
	
	;check for rules.ini and create if it doesnt exist
	IfNotExist, rules.ini
		IniWrite, AllRuleNames, rules.ini, Rules, AllRuleNames 
	Else
	IniRead, AllRuleNames, rules.ini, Rules, AllRuleNames
	;Check the rule doesnt already exist
	Loop, Parse, AllRuleNames, |
		{
			thisRule = %A_LoopField%
			if thisRule = %ShowName%
			{
				Msgbox %ShowName% already has a rule
				Return
			}
		}
	IniWrite, %AllRuleNames%%ShowName%|, rules.ini, Rules, AllRuleNames 
	IniWrite, %ShowName%, rules.ini, %ShowName%, SeriesName
	IniWrite, %SeriesIDNum%, rules.ini, %ShowName%, SeriesIDNum
   Return
   
   
ContextOpenFile:
ContextProperties:
   FocusedRowNumber := LV_GetNext(0, "F")
   If not FocusedRowNumber
      return
   LV_GetText(FileName, FocusedRowNumber, 1)
   LV_GetText(FileDir, FocusedRowNumber, 3)
   IfInString A_ThisMenuItem, Open
      Run %FileDir%\%FileName%,, UseErrorLevel
   Else
      Run Properties "%FileDir%\%FileName%",, UseErrorLevel
   If ErrorLevel
      MsgBox Could not perform requested action on "%FileDir%\%FileName%".
   return
   
ContextRemoveItem:
   RowNumber = 0
   Loop
   {
      RowNumber := LV_GetNext(RowNumber - 1)
      If not RowNumber
           Break
      LV_Delete(RowNumber)
   }
   Return

ButtonAddFolder:
   Gui +OwnDialogs
   FileSelectFolder, TargetFolder,, 3, Select a folder:
   If not TargetFolder  ; The user pressed cancel
       Return
   StringRight, LastChar, TargetFolder, 1
   If LastChar = \
      StringTrimRight, TargetFolder, TargetFolder, 1
   GuiControl, -Redraw, MyListView ; Improves performance by disabling redrawing
   Loop %TargetFolder%\*.*
   {
      FileName := A_LoopFileFullPath
      SplitPath, FileName,,, FileExt  ; Get the file extension
      If FileExt in avi,mkv,mp4
         LV_Add(Row, A_LoopFileName, "", A_LoopFileDir, FileExt)
   }
   GuiControl, +Redraw, MyListView  ; Turn redrawing back on
   LV_ModifyCol()  ; Resize each column to fit
   LV_ModifyCol(2, 60)  ; Expand "Preview" to keep the header visible
   LV_ModifyCol(4, 60)  ; Expand "Extension" to keep the header visible
   LV_ModifyCol(5, 110)  ; Expand "TVDB Series ID No" to keep the header visible
   Return

   ;Auto load a default folder and scan it
 ButtonTVRenameFolder:  
   TargetFolder := "\\SPOON\Downloads\TV Rename"
   Loop %TargetFolder%\*.*
   {
      FileName := A_LoopFileFullPath
      SplitPath, FileName,,, FileExt  ; Get the file extension
      If FileExt in avi,mkv,mp4
         LV_Add(Row, A_LoopFileName, "", A_LoopFileDir, FileExt)
   }
   GuiControl, +Redraw, MyListView  ; Turn redrawing back on
   LV_ModifyCol()  ; Resize each column to fit
   LV_ModifyCol(2, 60)  ; Expand "Preview" to keep the header visible
   LV_ModifyCol(4, 60)  ; Expand "Extension" to keep the header visible
   LV_ModifyCol(5, 110)  ; Expand "TVDB Series ID No" to keep the header visible
   Gosub, ButtonGetTVDBInfo
   Return
   
   
   
ButtonAddFile:
   Gui +OwnDialogs
   FileSelectFile, TargetFile
   If not TargetFile
      Return
   SplitPath, TargetFile,,, FileExt  ; Get the file extension
   If FileExt in avi,mkv,mp4
   {
      SplitPath, TargetFile, FileName, TargetFolder
      LV_Add(Row, FileName, "", TargetFolder, FileExt)
      LV_ModifyCol()  ; Resize each column to fit
      LV_ModifyCol(2, 60)  ; Expand "Preview" to keep the header visible
      LV_ModifyCol(4, 60)  ; Expand "Extension" to keep the header visible
      LV_ModifyCol(5, 110)  ; Expand "TVDB Series ID No" to keep the header visible
   }
   Return

ButtonClear:
   TargetFolder =
   LV_Delete()
   Return

ButtonGetTVDBInfo:
   LV_GetText(LVFileName, 1, 1)  ; Get the filename
   If not LVFileName
   {
      MsgBox, 0,Fatal Error!, You must select a file or folder before connecting to TheTVDB.com!
      Return
   }
   Loop
   {
      RowNumber = %A_Index%
      LV_GetText(LVFileName, RowNumber, 1)  ; Get the filename
      If not LVFileName  ; Break the loop at the end of the list
         Break
      LV_GetText(LVFileDir, RowNumber, 3)  ; Get the file directory
      LV_GetText(LVFileExt, RowNumber, 4)  ; Get the file extension
      ShowInfo := GetTVDBShows(GetShowName(LVFileName))
      StringSplit, OutputArray, ShowInfo, `,
      ShowName = %OutputArray1%
      SeriesIDNo = %OutputArray2%
      SeasonNumber := GetSeasonNumber(LVFileName)
      EpisodeNumber := GetEpisodeNumber(LVFileName)
      If SeriesIDNo
      {
         EpisodeInfo := GetTVDBEpisodes(SeriesIDNo, SeasonNumber, EpisodeNumber)
         StringSplit, OutputArray, EpisodeInfo, `,
         SeasonNumber = %OutputArray1%
         EpisodeNumber = %OutputArray2%
         EpisodeTitle = %OutputArray3%
      }
      GuiControlGet, NamingScheme,, NameScheme
      If NamingScheme = 1
      {
         If EpisodeTitle
            NewFileName = %ShowName% - %SeasonNumber%x%EpisodeNumber% - %EpisodeTitle%.%LVFileExt%
         Else
            NewFileName = %ShowName% - %SeasonNumber%x%EpisodeNumber%.%LVFileExt%
      }
      Else if NamingScheme = 2
      {
         If EpisodeTitle
            NewFileName = %ShowName% - S%SeasonNumber%E%EpisodeNumber% - %EpisodeTitle%.%LVFileExt%
         Else
            NewFileName = %ShowName% - S%SeasonNumber%E%EpisodeNumber%.%LVFileExt%
      }
      Else If NamingScheme = 3
      {
         If EpisodeTitle
            NewFileName = %SeasonNumber%x%EpisodeNumber% - %EpisodeTitle%.%LVFileExt%
         Else
            NewFileName = %SeasonNumber%x%EpisodeNumber%.%LVFileExt%
      }
      Else If NamingScheme = 4
      {
         If EpisodeTitle
            NewFileName = S%SeasonNumber%E%EpisodeNumber% - %EpisodeTitle%.%LVFileExt%
         Else
            NewFileName = S%SeasonNumber%E%EpisodeNumber%.%LVFileExt%
      }

      LV_Modify(RowNumber, Col1, LVFileName, NewFileName, LVFileDir, LVFileExt, SeriesIDNo, ShowName)
      LV_ModifyCol()
      LV_ModifyCol(4, 60)
      LV_ModifyCol(5, 110)  ; Expand "TVDB Series ID No" to keep the header visible
   }
   Return

ButtonRename:
   Loop
   {
      RowNumber = %A_Index%
      LV_GetText(LVFileName, RowNumber, 1)  ; Get the original filename
      If not LVFileName  ; Break the loop at the end of the list
         Break
      LV_GetText(LVNewFileName, RowNumber, 2)  ; Get the new filename
      FileMove, %TargetFolder%\%LVFileName%, %TargetFolder%\%LVNewFileName%
   }
   RenameCount := RowNumber - 1
   MsgBox, 0, Success!, %RenameCount% files have been renamed!`n`nRefreshing file list...
   LV_Delete()
   Loop %TargetFolder%\*.*
   {
      FileName := A_LoopFileFullPath
      If not FileName
         Break
      SplitPath, FileName,,, FileExt  ; Get the file extension
      If FileExt in avi,mkv,mp4
         LV_Add(Row, A_LoopFileName, "", A_LoopFileDir, FileExt)
   }
   GuiControl, +Redraw, MyListView  ; Turn redrawing back on
   LV_ModifyCol()  ; Resize each column to fit
   LV_ModifyCol(2, 60)  ; Expand "Preview" to keep the header visible
   LV_ModifyCol(4, 60)  ; Expand "Extension" to keep the header visible
   LV_ModifyCol(5, 110)  ; Expand "TVDB Series ID No" to keep the header visible
   Return

;Provide a filename (greek.s01e01.avi) and this will hopefully detect and return the show name
GetShowName(FileName)
{
   IfInString, FileName, .
      StringReplace, NormalName, FileName, ., %A_Space%, All
   IfInString, NormalName, _
      StringReplace, NormalName, NormalName, _, %A_Space%, All
   If RegExMatch(NormalName, "i)s[0-9][0-9]? ?e[0-9][0-9]?", SeasonAndEpisode)
   {
      StringGetPos, SeasonAndEpisodePos, NormalName, %SeasonAndEpisode%
      StringLeft, ShowName, NormalName, (SeasonAndEpisodePos - 1)
   }
   Else If RegExMatch(NormalName, "i)[0-9][0-9]?x[0-9][0-9]?", SeasonAndEpisode)
   {
      StringGetPos, SeasonAndEpisodePos, NormalName, %SeasonAndEpisode%
      StringLeft, ShowName, NormalName, (SeasonAndEpisodePos - 1)
   }
   Else If RegExMatch(NormalName, "[0-9][0-9][0-9][0-9]?", SeasonAndEpisode)
   {
      StringGetPos, SeasonAndEpisodePos, NormalName, %SeasonAndEpisode%
      StringLeft, ShowName, NormalName, (SeasonAndEpisodePos - 1)
   }
   Loop
   {
      StringRight, LastChar, ShowName, 1
      If (LastChar = "-" or LastChar = " ")
         StringTrimRight, ShowName, ShowName, 1
      Else
         Break
   }
   Return ShowName
}

;Provide a filename (greek.s01e01.avi) and this will hopefully detect and return the season number
GetSeasonNumber(FileName)
{
   If RegExMatch(FileName, "i)s\K[0-9][0-9]?.?e[0-9][0-9]?", SeasonAndEpisode)
   {
      StringGetPos, EPos, SeasonAndEpisode, e
      StringLeft, SeasonNumber, SeasonAndEpisode, %EPos%
      IfInString, SeasonNumber, .
         StringTrimRight, SeasonNumber, SeasonNumber, 1
      IfInString, SeasonNumber, 0
      {
         StringGetPos, ZeroLoc, SeasonNumber, 0
         If ZeroLoc = 0
            StringTrimLeft, SeasonNumber, SeasonNumber, 1
      }
         
   }
   Else If RegExMatch(FileName, "i)[0-9][0-9]?x[0-9][0-9]?", SeasonAndEpisode)
   {
      StringGetPos, XPos, SeasonAndEpisode, x
      StringLeft, SeasonNumber, SeasonAndEpisode, %XPos%
      IfInString, SeasonNumber, 0
      {
        StringGetPos, ZeroLoc, SeasonNumber, 0
         If ZeroLoc = 0
            StringTrimLeft, SeasonNumber, SeasonNumber, 1
      }
   }
   Else If RegExMatch(FileName, "[0-9][0-9][0-9][0-9]?", SeasonAndEpisode)
   {
      StringTrimRight, SeasonNumber, SeasonAndEpisode, 2
      IfInString, SeasonNumber, 0
      {
         StringGetPos, ZeroLoc, SeasonNumber, 0
         If ZeroLoc = 0
            StringTrimLeft, SeasonNumber, SeasonNumber, 1
      }
   }
   Return SeasonNumber
}

;Provide a filename (greek.s01e01.avi) and this will hopefully detect and return the episode number
GetEpisodeNumber(FileName)
{
   If RegExMatch(FileName, "i)s\K[0-9][0-9]?.?e[0-9][0-9]?", SeasonAndEpisode)
   {
      StringGetPos, EPos, SeasonAndEpisode, e
      StringRight, EpisodeNumber, SeasonAndEpisode, %EPos%
      IfInString, EpisodeNumber, e
         StringTrimLeft, EpisodeNumber, EpisodeNumber, 1
      IfInString, EpisodeNumber, 0
      {
         StringGetPos, ZeroLoc, EpisodeNumber, 0
         If ZeroLoc = 0
            StringTrimLeft, EpisodeNumber, EpisodeNumber, 1
      }
   }
   Else If RegExMatch(FileName, "i)[0-9][0-9]?x[0-9][0-9]?", SeasonAndEpisode)
   {
      StringGetPos, XPos, SeasonAndEpisode, x
      StringRight, EpisodeNumber, SeasonAndEpisode, %XPos%
      IfInString, EpisodeNumber, 0
      {
         StringGetPos, ZeroLoc, EpisodeNumber, 0
         If ZeroLoc = 0
            StringTrimLeft, EpisodeNumber, EpisodeNumber, 1
      }
   }
   Else If RegExMatch(FileName, "[0-9][0-9][0-9][0-9]?", SeasonAndEpisode)
   {
      StringRight, EpisodeNumber, SeasonAndEpisode, 2
      IfInString, EpisodeNumber, 0
      {
         StringGetPos, ZeroLoc, EpisodeNumber, 0
         If ZeroLoc = 0
            StringTrimLeft, EpisodeNumber, EpisodeNumber, 1
      }
   }
   Return EpisodeNumber
}


;Provide a show name (greek) and it will return the TVDB data for the show name (Greek) and series ID (80301) as a CSV (Greek,80301)
GetTVDBShows(ShowName)
{
;Check the rules.ini for a match
		IniRead, AllRuleNames, rules.ini, Rules, AllRuleNames
		Loop, Parse, AllRuleNames, |
		{
			thisRule = %A_LoopField%
			;Continue on if there is no rule
			if (thisRule = "ERROR") or (thisRule = "")
			{
				Continue
			}
			if (thisRule = ShowName)
			{
			IniRead, SeriesName, rules.ini, %thisRule%, SeriesName
			IniRead, SeriesIDNum, rules.ini, %thisRule%, SeriesIDNum
			;Jump to the end of GetTVDBShows if match ins found in rules.
			goto finish
			}
		}
   IfExist, Series_ID.xml
      FileDelete, Series_ID.xml
   UrlDownloadToFile, http://www.thetvdb.com/api/GetSeries.php?seriesname="%ShowName%", Series_ID.xml
   XPath_Load(xml, "Series_ID.xml")
   SeriesNameNodeCount := XPath(xml, "/Data/Series/SeriesName/Count()")
   If SeriesNameNodeCount = 1
   {
      SeriesIDNum := XPath(xml, "/Data/Series/seriesid/text()")
      SeriesName := XPath(xml, "/Data/Series/SeriesName/text()")
   }
   Else If SeriesNameNodeCount >= 2
   {
      SeriesIDNum := XPath(xml, "/Data/Series/seriesid/text()")
      SeriesName := XPath(xml, "/Data/Series/SeriesName/text()")
      SeriesOverview := XPath(xml, "/Data/Series/Overview/text()")
      StringSplit, OutputArraySID, SeriesIDNum, `,
      StringSplit, OutputArraySN, SeriesName, `,
      StringSplit, OutputArraySO, SeriesOverview, `,
	  Loop, %SeriesNameNodeCount%
      {
         SeriesIDNum := OutputArraySID%A_Index%
         SeriesName := OutputArraySN%A_Index%
         SeriesOverview := OutputArraySO%A_Index%
         IfInString, SeriesOverview, ,`;
            StringReplace, SeriesOverview, SeriesOverview, ,`;, `,, All
         If not SeriesOverview
            SeriesOverview = (No show description provided)
         MsgBox, 3, Which show do you want?, %SeriesName%`n`n%SeriesOverview%
         IfMsgBox, Yes
            Break
         IfMsgBox, No
         {
            NoCount = %A_Index%
            If NoCount = %SeriesNameNodeCount%
            {
               SeriesName =
               SeriesIDNum =
               MsgBox, 0, Fatal Error!, No more show name suggestions provided!`n`nI will use the show name parsed from the filename and move on to the next row...
            }
         }
         IfMsgBox, Cancel
            Return
      }
   }
   finish:
   If not SeriesName
      SeriesName = %ShowName%
   FileDelete, Series_ID.xml
   Data = %SeriesName%,%SeriesIDNum%
   Return Data
}

;Provide the "TVDB series ID", "season number" and "episode number" and this will return the matching TVDB season number,episode number, and episode title as a CSV (3,1,The Day After)
GetTVDBEpisodes(SeriesIDNum, SeasonNum, EpisodeNum)
{
   IfExist, Episode_Info.xml
      FileDelete, Episode_Info.xml
   UrlDownloadToFile, http://www.thetvdb.com/api/563E39CDC7F666DF/series/%SeriesIDNum%/default/%SeasonNum%/%EpisodeNum%/en.xml, Episode_Info.xml
   XPath_Load(xml, "Episode_Info.xml")
   SeasonNumber := XPath(xml, "/Data/Episode/SeasonNumber/text()")
   EpisodeNumber := XPath(xml, "/Data/Episode/EpisodeNumber/text()")
   EpisodeTitle := XPath(xml, "/Data/Episode/EpisodeName/text()")
   FileDelete, Episode_Info.xml
   If not SeasonNumber
      SeasonNumber = %SeasonNum%
   If not EpisodeNumber
      EpisodeNumber = %EpisodeNum%
   IfInString, EpisodeTitle, ?
      StringReplace, EpisodeTitle, EpisodeTitle, ?,, All
   GuiControlGet, PadZero, , Zero
   If PadZero = 1
   {
      SeasonLen := StrLen(SeasonNumber)
      EpisodeLen := StrLen(EpisodeNumber)
      ;If SeasonLen = 1
       ;  SeasonNumber = 0%SeasonNumber%
      If EpisodeLen = 1
         EpisodeNumber = 0%EpisodeNumber%
   }
   K = %SeasonNumber%,%EpisodeNumber%,%EpisodeTitle%
   Return K
}

Any feedback would be great, I haven't really done anything like this before, and I'm sure I have made some mistakes


I think it looks fine :) ... as long as it works who cares how pretty it is. Like my father always told me, theres more than one way to skin a cat.

On topic, Im working on optimizing how show names are retreived in an effort to speed things up and to (potentially) reduce the number of queries against TheTVDB. This is going to involve a nicer show selection method when multiple shows are returned. Thanks for the ideas and kind words, ashius!

ashius
  • Members
  • 3 posts
  • Last active: Mar 27 2011 12:09 PM
  • Joined: 20 Oct 2009
Nice, I am looking forward to checking out the new changes. I don't how how you plan on speeding the process the up, it will be interesting to see.

I have been plugging away at the Rules idea. I have fleshed it out further:
-GUI for editing rules
-Rule removal
-Added a Button for setting a Default scanning folder.

Wow doesn't really seem a lot when it is put in bullet points :p

Anyway here is the code:

; SceneRenamer by strictlyfocused02
;
; AutoHotkey Version: 1.0.48+
;
; Script Function:
;   Extracts season and episode info from the filename
;   and uses that to retreive info from TheTVDB.com to rename
;   the file to a user-specified format

;   Special thanks to TheTVDB.com
;   This project would not have been possible without their top-notch API

#Include xpath.ahk

#NoEnv
SendMode, Input
SetWorkingDir, %A_ScriptDir%
;check for rules.ini and create if it doesnt exist
IfNotExist, rules.ini
	Blank = 
	IniWrite,%Blank%, rules.ini, Rules, AllRuleNames 
;Get the default folder
IniRead,DefaultTargetFolder, rules.ini, DefaultFolder, Folder

MainGUI:
Gui, Destroy
Gui, Add, Button, Default gButtonAddFolder, &Add folder
Gui, Add, Button, x+20 gButtonAddFile, Add &file
Gui, Add, Button, x+20 gButtonClear, &Clear list
Gui, Add, Button, x+20 gButtonDefaultRenameFolder, &Default Rename Folder ;Addtional button for scaning the default folder
Gui, Add, Button, x+20 ButtonAddRule, Add &Rule ; Add rule button
Gui, Add, Button, x+20 ButtonEditRules, &Edit Rules ; Edit rule button
Gui, Add, Button, x+60 gButtonSetDefaultFolder, &Set Default Folder ; Edit rule button



Gui, Add, ListView, xm r25 w800 vMyListView, Name|Preview|Directory|Extension|TVDB Series ID No|Show Name|FileName ;Added collum for getting the selected Show Name

Gui, Add, DropDownList, y+7 w250 AltSubmit vNameScheme, (Show Title) - (SS)x(EE) - (Episode Title)||(Show Title) - S(SS)E(EE) - (Episode Title)|(SS)x(EE) - Episode Title|S(SS)E(EE) - (Episode Title)
Gui, Add, Checkbox, x+30 Checked vZero, Pad with zero?
Gui, Add, Button, x+200 gButtonGetTVDBInfo, &Get TVDB Info
Gui, Add, Button, x+60 gButtonRename, &Rename files

Menu, MyContextMenu, Add, Open, ContextOpenFile
Menu, MyContextMenu, Add, Properties, ContextProperties
Menu, MyContextMenu, Add, Remove item, ContextRemoveItem

Gui, Show
Gosub, ButtonDefaultRenameFolder ;This is so it starts scaning once opened
Return



GuiClose:
   ExitApp

GuiContextMenu:
   If A_GuiControl <> MyListView
       Return
   Menu, MyContextMenu, Show, %A_GuiX%, %A_GuiY%
   Return

ButtonSetDefaultFolder:
	FocusedRowNumber := LV_GetNext(0, "F")
	LV_GetText(LVFileDir, FocusedRowNumber, 3)
	msgbox, 4, Set Default Directory, Set %LVFileDir% as the default directory for scanning? `nThis will make SceneRenamer scan this folder on start.
	Ifmsgbox yes
		IniWrite,%LVFileDir%, rules.ini, DefaultFolder, Folder
Return
   
;Add new rule to the rules.ini
ButtonAddRule:
	;Get information on the Selected show
	FocusedRowNumber := LV_GetNext(0, "F")
	LV_GetText(PatternShowName, FocusedRowNumber, 7)
	LV_GetText(ShowName, FocusedRowNumber, 6)
	LV_GetText(SeriesIDNum, FocusedRowNumber, 5)

	IniRead, AllRuleNames, rules.ini, Rules, AllRuleNames
	;Check the rule doesnt already exist
	Loop, Parse, AllRuleNames, |
		{
			thisRule = %A_LoopField%
			if thisRule = %PatternShowName%
			{
				Msgbox %PatternShowName% already has a rule
				Return
			}
		}
	IniWrite, %AllRuleNames%%PatternShowName%|, rules.ini, Rules, AllRuleNames 
	IniWrite, %ShowName%, rules.ini, %PatternShowName%, SeriesName
	IniWrite, %SeriesIDNum%, rules.ini, %PatternShowName%, SeriesIDNum
	Return
   
   
ContextOpenFile:
ContextProperties:
   FocusedRowNumber := LV_GetNext(0, "F")
   If not FocusedRowNumber
      return
   LV_GetText(FileName, FocusedRowNumber, 1)
   LV_GetText(FileDir, FocusedRowNumber, 3)
   IfInString A_ThisMenuItem, Open
      Run %FileDir%\%FileName%,, UseErrorLevel
   Else
      Run Properties "%FileDir%\%FileName%",, UseErrorLevel
   If ErrorLevel
      MsgBox Could not perform requested action on "%FileDir%\%FileName%".
   return
   
ContextRemoveItem:
   RowNumber = 0
   Loop
   {
      RowNumber := LV_GetNext(RowNumber - 1)
      If not RowNumber
           Break
      LV_Delete(RowNumber)
   }
   Return

ButtonAddFolder:
   Gui +OwnDialogs
   FileSelectFolder, TargetFolder,, 3, Select a folder:
   If not TargetFolder  ; The user pressed cancel
       Return
   StringRight, LastChar, TargetFolder, 1
   If LastChar = \
      StringTrimRight, TargetFolder, TargetFolder, 1
   GuiControl, -Redraw, MyListView ; Improves performance by disabling redrawing
   Loop %TargetFolder%\*.*
   {
      FileName := A_LoopFileFullPath
      SplitPath, FileName,,, FileExt  ; Get the file extension
      If FileExt in avi,mkv,mp4
         LV_Add(Row, A_LoopFileName, "", A_LoopFileDir, FileExt)
   }
   GuiControl, +Redraw, MyListView  ; Turn redrawing back on
   LV_ModifyCol()  ; Resize each column to fit
   LV_ModifyCol(2, 60)  ; Expand "Preview" to keep the header visible
   LV_ModifyCol(4, 60)  ; Expand "Extension" to keep the header visible
   LV_ModifyCol(5, 110)  ; Expand "TVDB Series ID No" to keep the header visible
   Return

   ;Auto load a default folder and scan it
ButtonDefaultRenameFolder: 
	If DefaultTargetFolder = ERROR
		Return
	Else
	;Check a file exists before running Default scan
	IfExist, %DefaultTargetFolder%*.avi
		avi = 1
	IfExist, %DefaultTargetFolder%*.mkv
		mkv = 1
	IfExist, %DefaultTargetFolder%*.mp4
		mp4 = 1
	If (mkv = "" AND avi = "" AND mp4 = "")
		Return
   TargetFolder :=  DefaultTargetFolder
   ;TargetFolder = "\\SPOON\Downloads\TV Rename"
   Loop %TargetFolder%\*.*
   {
      FileName := A_LoopFileFullPath
      SplitPath, FileName,,, FileExt  ; Get the file extension
      If FileExt in avi,mkv,mp4
         LV_Add(Row, A_LoopFileName, "", A_LoopFileDir, FileExt)
   }
   GuiControl, +Redraw, MyListView  ; Turn redrawing back on
   LV_ModifyCol()  ; Resize each column to fit
   LV_ModifyCol(2, 60)  ; Expand "Preview" to keep the header visible
   LV_ModifyCol(4, 60)  ; Expand "Extension" to keep the header visible
   LV_ModifyCol(5, 110)  ; Expand "TVDB Series ID No" to keep the header visible
   Gosub, ButtonGetTVDBInfo
   Return
   
   
   
ButtonAddFile:
   Gui +OwnDialogs
   FileSelectFile, TargetFile
   If not TargetFile
      Return
   SplitPath, TargetFile,,, FileExt  ; Get the file extension
   If FileExt in avi,mkv,mp4
   {
      SplitPath, TargetFile, FileName, TargetFolder
      LV_Add(Row, FileName, "", TargetFolder, FileExt)
      LV_ModifyCol()  ; Resize each column to fit
      LV_ModifyCol(2, 60)  ; Expand "Preview" to keep the header visible
      LV_ModifyCol(4, 60)  ; Expand "Extension" to keep the header visible
      LV_ModifyCol(5, 110)  ; Expand "TVDB Series ID No" to keep the header visible
   }
   Return

ButtonClear:
   TargetFolder =
   LV_Delete()
   Return

ButtonGetTVDBInfo:
   LV_GetText(LVFileName, 1, 1)  ; Get the filename
   If not LVFileName
   {
      MsgBox, 0,Fatal Error!, You must select a file or folder before connecting to TheTVDB.com!
      Return
   }
   Loop
   {
      RowNumber = %A_Index%
      LV_GetText(LVFileName, RowNumber, 1)  ; Get the filename
      If not LVFileName  ; Break the loop at the end of the list
         Break
      LV_GetText(LVFileDir, RowNumber, 3)  ; Get the file directory
      LV_GetText(LVFileExt, RowNumber, 4)  ; Get the file extension
      ShowInfo := GetTVDBShows(GetShowName(LVFileName))
      StringSplit, OutputArray, ShowInfo, `,
      ShowName = %OutputArray1%
      SeriesIDNo = %OutputArray2%
      SeasonNumber := GetSeasonNumber(LVFileName)
      EpisodeNumber := GetEpisodeNumber(LVFileName)
      If SeriesIDNo
      {
         EpisodeInfo := GetTVDBEpisodes(SeriesIDNo, SeasonNumber, EpisodeNumber)
         StringSplit, OutputArray, EpisodeInfo, `,
         SeasonNumber = %OutputArray1%
         EpisodeNumber = %OutputArray2%
         EpisodeTitle = %OutputArray3%
      }
      GuiControlGet, NamingScheme,, NameScheme
      If NamingScheme = 1
      {
         If EpisodeTitle
            NewFileName = %ShowName% - %SeasonNumber%x%EpisodeNumber% - %EpisodeTitle%.%LVFileExt%
         Else
            NewFileName = %ShowName% - %SeasonNumber%x%EpisodeNumber%.%LVFileExt%
      }
      Else if NamingScheme = 2
      {
         If EpisodeTitle
            NewFileName = %ShowName% - S%SeasonNumber%E%EpisodeNumber% - %EpisodeTitle%.%LVFileExt%
         Else
            NewFileName = %ShowName% - S%SeasonNumber%E%EpisodeNumber%.%LVFileExt%
      }
      Else If NamingScheme = 3
      {
         If EpisodeTitle
            NewFileName = %SeasonNumber%x%EpisodeNumber% - %EpisodeTitle%.%LVFileExt%
         Else
            NewFileName = %SeasonNumber%x%EpisodeNumber%.%LVFileExt%
      }
      Else If NamingScheme = 4
      {
         If EpisodeTitle
            NewFileName = S%SeasonNumber%E%EpisodeNumber% - %EpisodeTitle%.%LVFileExt%
         Else
            NewFileName = S%SeasonNumber%E%EpisodeNumber%.%LVFileExt%
      }
      LV_Modify(RowNumber, Col1, LVFileName, NewFileName, LVFileDir, LVFileExt, SeriesIDNo, ShowName, PatternShowName)
      LV_ModifyCol()
      LV_ModifyCol(4, 60)
      LV_ModifyCol(5, 110)  ; Expand "TVDB Series ID No" to keep the header visible
   }
   Return

ButtonRename:
   Loop
   {
      RowNumber = %A_Index%
      LV_GetText(LVFileName, RowNumber, 1)  ; Get the original filename
      If not LVFileName  ; Break the loop at the end of the list
         Break
      LV_GetText(LVNewFileName, RowNumber, 2)  ; Get the new filename
      FileMove, %TargetFolder%\%LVFileName%, %TargetFolder%\%LVNewFileName%
   }
   RenameCount := RowNumber - 1
   MsgBox, 0, Success!, %RenameCount% files have been renamed!`n`nRefreshing file list...
   LV_Delete()
   Loop %TargetFolder%\*.*
   {
      FileName := A_LoopFileFullPath
      If not FileName
         Break
      SplitPath, FileName,,, FileExt  ; Get the file extension
      If FileExt in avi,mkv,mp4
         LV_Add(Row, A_LoopFileName, "", A_LoopFileDir, FileExt)
   }
   GuiControl, +Redraw, MyListView  ; Turn redrawing back on
   LV_ModifyCol()  ; Resize each column to fit
   LV_ModifyCol(2, 60)  ; Expand "Preview" to keep the header visible
   LV_ModifyCol(4, 60)  ; Expand "Extension" to keep the header visible
   LV_ModifyCol(5, 110)  ; Expand "TVDB Series ID No" to keep the header visible
   Return

;Provide a filename (greek.s01e01.avi) and this will hopefully detect and return the show name
GetShowName(FileName)
{
   IfInString, FileName, .
      StringReplace, NormalName, FileName, ., %A_Space%, All
   IfInString, NormalName, _
      StringReplace, NormalName, NormalName, _, %A_Space%, All
   If RegExMatch(NormalName, "i)s[0-9][0-9]? ?e[0-9][0-9]?", SeasonAndEpisode)
   {
      StringGetPos, SeasonAndEpisodePos, NormalName, %SeasonAndEpisode%
      StringLeft, ShowName, NormalName, (SeasonAndEpisodePos - 1)
   }
   Else If RegExMatch(NormalName, "i)[0-9][0-9]?x[0-9][0-9]?", SeasonAndEpisode)
   {
      StringGetPos, SeasonAndEpisodePos, NormalName, %SeasonAndEpisode%
      StringLeft, ShowName, NormalName, (SeasonAndEpisodePos - 1)
   }
   Else If RegExMatch(NormalName, "[0-9][0-9][0-9][0-9]?", SeasonAndEpisode)
   {
      StringGetPos, SeasonAndEpisodePos, NormalName, %SeasonAndEpisode%
      StringLeft, ShowName, NormalName, (SeasonAndEpisodePos - 1)
   }
   Loop
   {
      StringRight, LastChar, ShowName, 1
      If (LastChar = "-" or LastChar = " ")
         StringTrimRight, ShowName, ShowName, 1
      Else
         Break
   }
   AutoTrim, off 
   global PatternShowName = ShowName
   Return ShowName
   
}

;Provide a filename (greek.s01e01.avi) and this will hopefully detect and return the season number
GetSeasonNumber(FileName)
{
   If RegExMatch(FileName, "i)s\K[0-9][0-9]?.?e[0-9][0-9]?", SeasonAndEpisode)
   {
      StringGetPos, EPos, SeasonAndEpisode, e
      StringLeft, SeasonNumber, SeasonAndEpisode, %EPos%
      IfInString, SeasonNumber, .
         StringTrimRight, SeasonNumber, SeasonNumber, 1
      IfInString, SeasonNumber, 0
      {
         StringGetPos, ZeroLoc, SeasonNumber, 0
         If ZeroLoc = 0
            StringTrimLeft, SeasonNumber, SeasonNumber, 1
      }
         
   }
   Else If RegExMatch(FileName, "i)[0-9][0-9]?x[0-9][0-9]?", SeasonAndEpisode)
   {
      StringGetPos, XPos, SeasonAndEpisode, x
      StringLeft, SeasonNumber, SeasonAndEpisode, %XPos%
      IfInString, SeasonNumber, 0
      {
        StringGetPos, ZeroLoc, SeasonNumber, 0
         If ZeroLoc = 0
            StringTrimLeft, SeasonNumber, SeasonNumber, 1
      }
   }
   Else If RegExMatch(FileName, "[0-9][0-9][0-9][0-9]?", SeasonAndEpisode)
   {
      StringTrimRight, SeasonNumber, SeasonAndEpisode, 2
      IfInString, SeasonNumber, 0
      {
         StringGetPos, ZeroLoc, SeasonNumber, 0
         If ZeroLoc = 0
            StringTrimLeft, SeasonNumber, SeasonNumber, 1
      }
   }
   Return SeasonNumber
}

;Provide a filename (greek.s01e01.avi) and this will hopefully detect and return the episode number
GetEpisodeNumber(FileName)
{
   If RegExMatch(FileName, "i)s\K[0-9][0-9]?.?e[0-9][0-9]?", SeasonAndEpisode)
   {
      StringGetPos, EPos, SeasonAndEpisode, e
      StringRight, EpisodeNumber, SeasonAndEpisode, %EPos%
      IfInString, EpisodeNumber, e
         StringTrimLeft, EpisodeNumber, EpisodeNumber, 1
      IfInString, EpisodeNumber, 0
      {
         StringGetPos, ZeroLoc, EpisodeNumber, 0
         If ZeroLoc = 0
            StringTrimLeft, EpisodeNumber, EpisodeNumber, 1
      }
   }
   Else If RegExMatch(FileName, "i)[0-9][0-9]?x[0-9][0-9]?", SeasonAndEpisode)
   {
      StringGetPos, XPos, SeasonAndEpisode, x
      StringRight, EpisodeNumber, SeasonAndEpisode, %XPos%
      IfInString, EpisodeNumber, 0
      {
         StringGetPos, ZeroLoc, EpisodeNumber, 0
         If ZeroLoc = 0
            StringTrimLeft, EpisodeNumber, EpisodeNumber, 1
      }
   }
   Else If RegExMatch(FileName, "[0-9][0-9][0-9][0-9]?", SeasonAndEpisode)
   {
      StringRight, EpisodeNumber, SeasonAndEpisode, 2
      IfInString, EpisodeNumber, 0
      {
         StringGetPos, ZeroLoc, EpisodeNumber, 0
         If ZeroLoc = 0
            StringTrimLeft, EpisodeNumber, EpisodeNumber, 1
      }
   }
   Return EpisodeNumber
}


;Provide a show name (greek) and it will return the TVDB data for the show name (Greek) and series ID (80301) as a CSV (Greek,80301)
GetTVDBShows(ShowName)
{
;Check the rules.ini for a match
	IniRead, AllRuleNames, rules.ini, Rules, AllRuleNames
	Loop, Parse, AllRuleNames, |
	{
		thisRule = %A_LoopField%
		
		;Continue on if there is no rule
		if (thisRule = "ERROR") or (thisRule = "")
		{
			Continue
		}
		if (thisRule = ShowName)
		{
		IniRead, SeriesName, rules.ini, %thisRule%, SeriesName
		IniRead, SeriesIDNum, rules.ini, %thisRule%, SeriesIDNum
		;Jump to the end of GetTVDBShows if match is found in rules.
		goto finish
		}
	}
;Check for match online
   IfExist, Series_ID.xml
      FileDelete, Series_ID.xml
   UrlDownloadToFile, http://www.thetvdb.com/api/GetSeries.php?seriesname="%ShowName%", Series_ID.xml
   XPath_Load(xml, "Series_ID.xml")
   SeriesNameNodeCount := XPath(xml, "/Data/Series/SeriesName/Count()")
   If SeriesNameNodeCount = 1
   {
      SeriesIDNum := XPath(xml, "/Data/Series/seriesid/text()")
      SeriesName := XPath(xml, "/Data/Series/SeriesName/text()")
   }
   Else If SeriesNameNodeCount >= 2
   {
      SeriesIDNum := XPath(xml, "/Data/Series/seriesid/text()")
      SeriesName := XPath(xml, "/Data/Series/SeriesName/text()")
      SeriesOverview := XPath(xml, "/Data/Series/Overview/text()")
      StringSplit, OutputArraySID, SeriesIDNum, `,
      StringSplit, OutputArraySN, SeriesName, `,
      StringSplit, OutputArraySO, SeriesOverview, `,
	  Loop, %SeriesNameNodeCount%
      {
         SeriesIDNum := OutputArraySID%A_Index%
         SeriesName := OutputArraySN%A_Index%
         SeriesOverview := OutputArraySO%A_Index%
         IfInString, SeriesOverview, ,`;
            StringReplace, SeriesOverview, SeriesOverview, ,`;, `,, All
         If not SeriesOverview
            SeriesOverview = (No show description provided)
         MsgBox, 3, Which show do you want?, %SeriesName%`n`n%SeriesOverview%
			IfMsgBox, Yes
			Break
         IfMsgBox, No
         {
            NoCount = %A_Index%
            If NoCount = %SeriesNameNodeCount%
            {
               SeriesName =
               SeriesIDNum =
               MsgBox, 0, Fatal Error!, No more show name suggestions provided!`n`nI will use the show name parsed from the filename and move on to the next row...
            }
         }
         IfMsgBox, Cancel
            Return
      }
   }
   finish:
   If not SeriesName
      SeriesName = %ShowName%
   FileDelete, Series_ID.xml
   Data = %SeriesName%,%SeriesIDNum%
   Return Data
}

;Provide the "TVDB series ID", "season number" and "episode number" and this will return the matching TVDB season number,episode number, and episode title as a CSV (3,1,The Day After)
GetTVDBEpisodes(SeriesIDNum, SeasonNum, EpisodeNum)
{
   IfExist, Episode_Info.xml
      FileDelete, Episode_Info.xml
   UrlDownloadToFile, http://www.thetvdb.com/api/563E39CDC7F666DF/series/%SeriesIDNum%/default/%SeasonNum%/%EpisodeNum%/en.xml, Episode_Info.xml
   XPath_Load(xml, "Episode_Info.xml")
   SeasonNumber := XPath(xml, "/Data/Episode/SeasonNumber/text()")
   EpisodeNumber := XPath(xml, "/Data/Episode/EpisodeNumber/text()")
   EpisodeTitle := XPath(xml, "/Data/Episode/EpisodeName/text()")
   FileDelete, Episode_Info.xml
   If not SeasonNumber
      SeasonNumber = %SeasonNum%
   If not EpisodeNumber
      EpisodeNumber = %EpisodeNum%
   IfInString, EpisodeTitle, ?
      StringReplace, EpisodeTitle, EpisodeTitle, ?,, All
   GuiControlGet, PadZero, , Zero
   If PadZero = 1
   {
      SeasonLen := StrLen(SeasonNumber)
      EpisodeLen := StrLen(EpisodeNumber)
      ;If SeasonLen = 1
       ;  SeasonNumber = 0%SeasonNumber%
      If EpisodeLen = 1
         EpisodeNumber = 0%EpisodeNumber%
   }
   K = %SeasonNumber%,%EpisodeNumber%,%EpisodeTitle%
   Return K
}


ButtonEditRules:
Gui, 1: Destroy
Gui, 1: Add, ListView, x22 y30 w140 h340 AltSubmit vAllRules gSelectRule, Rules
Gui, 1: Add, Edit, x252 y70 w220 h20 vSeriesName, 
Gui, 1: Add, Edit, x272 y110 w200 h20 vSeriesIDNum, 
Gui, 1: Add, Text, x182 y70 w70 h20 , Series Name
Gui, 1: Add, Text, x182 y110 w90 h20 , TVDB ID Number
Gui, 1: Add, Button, x182 y320 w100 h30 gButtonSave, Save
Gui, 1: Add, Button, x352 y250 w100 h30 gButtonRemoveRule, Remove Rule
Gui, 1: Add, Button, x352 y320 w100 h30 gButtonCancel, Back
Gui, Add, Text, x182 y140 w290 h100 , `nSeries Name: Is the title that will be used in the file name.`n`nTVDB ID Number: Is used to get the episode names.
; Generated using SmartGUI Creator 4.0
Gui, Show, Edit Rules
gosub AllRules
Return

AllRules:
LV_Delete()
GuiControl, -Redraw, AllRules
IniRead, AllRuleNames, rules.ini, Rules, AllRuleNames
Loop, Parse, Allrulenames, |
	{
		If (A_LoopField = "")
			Break
		Else	
		LV_Add(Row,A_LoopField)
	}
LV_Modify(1, "Select")
LV_Modify(1, "Focus")
GuiControl, +Redraw, AllRules
gosub SelectRule
Return

SelectRule:
FocusedRowNumber := LV_GetNext(0, "F")
LV_GetText(RuleName, FocusedRowNumber)
IniRead, SeriesName, rules.ini, %RuleName%, SeriesName
IniRead, SeriesIDNum, rules.ini, %RuleName%, SeriesIDNum
GuiControl,, SeriesName, %SeriesName%
GuiControl,, SeriesIDNum, %SeriesIDNum%
Return

ButtonSave:
GuiControlGet, SeriesName
GuiControlGet, SeriesIDNum
IniWrite, %SeriesName%, rules.ini, %RuleName%, SeriesName
IniWrite, %SeriesIDNum%, rules.ini, %RuleName%, SeriesIDNum
Return

ButtonCancel:
Goto MainGUI
Return


ButtonRemoveRule:
	FocusedRowNumber := LV_GetNext(0, "F")
	LV_GetText(RemoveRule, FocusedRowNumber)
		Msgbox, 4, Confirm Rule Removal, Are you sure you want to remove the rule for %RemoveRule%
		IfMsgBox No
			Return
	IniRead, AllRuleNames, rules.ini, Rules, AllRuleNames
	Loop, Parse, AllRuleNames,|
	{
		if (A_LoopField = RemoveRule)
		{
			StringReplace, AllRuleNames, AllRuleNames, |%A_LoopField%|,|, UseErrorLevel
			If ErrorLevel = 0
			{
				StringReplace, AllRuleNames, AllRuleNames, %A_LoopField%|
			}
		IniDelete, rules.ini, %A_LoopField%
			
		}
	}
	IniWrite, %AllRuleNames%, rules.ini, Rules, AllRuleNames
gosub AllRules
Return

Edit - Forgot to add the code that checks if any video files are in the default folder before scanning.
Edit 2 - Fixed a mistake with the variables for adding rules. General clean-up.

rednoah
  • Guests
  • Last active:
  • Joined: --
I've posted this before, but try FileBot, it's the ultimate tv renamer:

http://filebot.sourceforge.net

Works for pretty much anything, scene releases, anime, whatever. It's got a clean and efficient user interface and it will run on any platform. It's deployed via a single executable jar, or if you are really lazy you can launch it via Java Web Start directly from the homepage.

strictlyfocused02
  • Members
  • 64 posts
  • Last active: Jul 27 2014 03:43 PM
  • Joined: 21 Jan 2009

I've posted this before, but try FileBot, it's the ultimate tv renamer:

<!-- m -->http://filebot.sourceforge.net<!-- m -->

Works for pretty much anything, scene releases, anime, whatever. It's got a clean and efficient user interface and it will run on any platform. It's deployed via a single executable jar, or if you are really lazy you can launch it via Java Web Start directly from the homepage.


But its so much more fun to code things yourself :lol:

Regardless, thanks for the heads-up about that app ... I may use some bits of it as "inspiration" haha

  • Guests
  • Last active:
  • Joined: --

But its so much more fun to code things yourself :lol:

Did you have a look at the episode naming system? You'll definitely like it. :wink:

strictlyfocused02
  • Members
  • 64 posts
  • Last active: Jul 27 2014 03:43 PM
  • Joined: 21 Jan 2009
Okay, Im turning to you guys for help. Im re-writing a portion of the GetTVDBShows() function but I cannot for the life of me get the function to return the showname selected from the listview in Gui, 2. Heres what Im working with:

#Include xpath.ahk

#NoEnv
SendMode, Input
SetWorkingDir, %A_ScriptDir%

ShowInfo := GetTVDBShows("Greek")
MsgBox, ShowInfo = %ShowInfo%
ExitApp


;Provide a show name (greek) and it will return the TVDB data for the show name (Greek) and series ID (80301) as a CSV (Greek,80301)
GetTVDBShows(ShowName)
{
   IfExist, Series_ID.xml
      FileDelete, Series_ID.xml
   If not ShowName
   {
      MsgBox, 0, Fatal Error!, The ShowName variable is empty`n`nAborting query against TheTVDB.com
      Return
   }
   UrlDownloadToFile, http://www.thetvdb.com/api/GetSeries.php?seriesname="%ShowName%", Series_ID.xml
   XPath_Load(xml, "Series_ID.xml")
   FileDelete, Series_ID.xml
   SeriesNameNodeCount := XPath(xml, "/Data/Series/SeriesName/Count()")
   If SeriesNameNodeCount = 1
   {
      SeriesIDNum := XPath(xml, "/Data/Series/seriesid/text()")
      SeriesName := XPath(xml, "/Data/Series/SeriesName/text()")
   }
   Else If SeriesNameNodeCount >= 2
   {
      SeriesIDNum := XPath(xml, "/Data/Series/seriesid/text()")
      SeriesName := XPath(xml, "/Data/Series/SeriesName/text()")
      SeriesOverview := XPath(xml, "/Data/Series/Overview/text()")
      StringSplit, OutputArraySID, SeriesIDNum, `,
      StringSplit, OutputArraySN, SeriesName, `,
      StringSplit, OutputArraySO, SeriesOverview, `,
      Gui, 2: Default 
      Gui, 2: +ToolWindow
      Gui, 2: Add, ListView, xm r10 w550, Show name|Show description|TVDB series ID no.
      Gui, 2: Add, Text, y+7
      Gui, 2: Add, Button, x+400, Select
      Gui, 2: Add, Button, x+15, Cancel
      Loop, %SeriesNameNodeCount%
      {
         SeriesIDNum := OutputArraySID%A_Index%
         SeriesName := OutputArraySN%A_Index%
         SeriesOverview := OutputArraySO%A_Index%
         IfInString, SeriesOverview, ,`;
            StringReplace, SeriesOverview, SeriesOverview, ,`;, `,, All
         If not SeriesOverview
            SeriesOverview = (No show description provided)
         LV_Add(Row, SeriesName, SeriesOverview, SeriesIDNum)
         LV_ModifyCol()
         LV_ModifyCol(3, 110)
         SeriesIDNum =
         SeriesName =
         SeriesOverview =
      }
      Gui, 2:Show,,Which Show?
      Gui, 2:+LastFound
      WinWaitClose
   }
   If not SeriesName
      SeriesName = %ShowName%
   J = %SeriesName%,%SeriesIDNum%
   Return J
}

2GuiEscape:
2GuiClose:
2ButtonCancel:
{
   Gui, 2: Destroy
   Return
}

Any help would be greatly appreciated!!

strictlyfocused02
  • Members
  • 64 posts
  • Last active: Jul 27 2014 03:43 PM
  • Joined: 21 Jan 2009
Im still working on figuring out a nice way to to return the selected choice in this example. I added a small bit that show the vars I need (TVDB Name and Series ID No) are retrievable I just cant figure out a way to get them back into the function :oops:

#Include xpath.ahk

#NoEnv
SendMode, Input
SetWorkingDir, %A_ScriptDir%

ShowInfo := GetTVDBShows("Greek")
;MsgBox, ShowInfo = %ShowInfo%
ExitApp


;Provide a show name (greek) and it will return the TVDB data for the show name (Greek) and series ID (80301) as a CSV (Greek,80301)
GetTVDBShows(ShowName)
{
   IfExist, Series_ID.xml
      FileDelete, Series_ID.xml
   If not ShowName
   {
      MsgBox, 0, Fatal Error!, The ShowName variable is empty`n`nAborting query against TheTVDB.com
      Return
   }
   UrlDownloadToFile, http://www.thetvdb.com/api/GetSeries.php?seriesname="%ShowName%", Series_ID.xml
   XPath_Load(xml, "Series_ID.xml")
   FileDelete, Series_ID.xml
   SeriesNameNodeCount := XPath(xml, "/Data/Series/SeriesName/Count()")
   If SeriesNameNodeCount = 1
   {
      SeriesIDNum := XPath(xml, "/Data/Series/seriesid/text()")
      SeriesName := XPath(xml, "/Data/Series/SeriesName/text()")
   }
   Else If SeriesNameNodeCount > 1
   {
      SeriesIDNum := XPath(xml, "/Data/Series/seriesid/text()")
      SeriesName := XPath(xml, "/Data/Series/SeriesName/text()")
      SeriesOverview := XPath(xml, "/Data/Series/Overview/text()")
      StringSplit, OutputArraySID, SeriesIDNum, `,
      StringSplit, OutputArraySN, SeriesName, `,
      StringSplit, OutputArraySO, SeriesOverview, `,
      Gui, 2: Default 
      Gui, 2: +ToolWindow
      Gui, 2: Add, ListView, xm r10 w550, Show name|Show description|TVDB series ID no.
      Gui, 2: Add, Text, y+7
      Gui, 2: Add, Button, x+400, Select
      Gui, 2: Add, Button, x+15, Cancel
      Loop, %SeriesNameNodeCount%
      {
         SeriesIDNum := OutputArraySID%A_Index%
         SeriesName := OutputArraySN%A_Index%
         SeriesOverview := OutputArraySO%A_Index%
         IfInString, SeriesOverview, ,`;
            StringReplace, SeriesOverview, SeriesOverview, ,`;, `,, All
         If not SeriesOverview
            SeriesOverview = (No show description provided)
         LV_Add(Row, SeriesName, SeriesOverview, SeriesIDNum)
         LV_ModifyCol()
         LV_ModifyCol(3, 110)
         SeriesIDNum =
         SeriesName =
         SeriesOverview =
      }
      Gui, 2:Show,,Which Show?
      Gui, 2:+LastFound
      WinWaitClose
   }
   If not SeriesName
      SeriesName = %ShowName%
   J = %SeriesName%,%SeriesIDNum%
   Return J
}

2GuiEscape:
2GuiClose:
2ButtonCancel:
{
   Gui, 2: Destroy
   Return
}

2ButtonSelect:
{
   FocusedRowNumber := LV_GetNext(0, "F")
   If not FocusedRowNumber
   {
      MsgBox, 0, Warning!, You must select a show or press cancel!
      Return
   }
   LV_GetText(SeriesName, FocusedRowNumber, 1)
   LV_GetText(SeriesIDNum, FocusedRowNumber, 3)
   MsgBox, SeriesName = %SeriesName%`nSeriesIDNum = %SeriesIDNum%
   ;Gui, 2:Destroy
   Return 
}


skwire
  • Moderators
  • 279 posts
  • Last active: Aug 12 2014 05:16 PM
  • Joined: 18 Jan 2006
The easiest way would be to just make those two variables global:

;Provide a show name (greek) and it will return the TVDB data for the show name (Greek) and series ID (80301) as a CSV (Greek,80301)
GetTVDBShows(ShowName)
{
    Global SeriesName, SeriesIDNum
    [...]
}

Also, if I may make a suggestion, make use of the unHTML() function when adding the preview filenames to the list.

LV_Modify(RowNumber, Col1, LVFileName, [color=red]unHTML( NewFileName )[/color], LVFileDir, LVFileExt, SeriesIDNo)

Great script...well written and easy to follow. =]

strictlyfocused02
  • Members
  • 64 posts
  • Last active: Jul 27 2014 03:43 PM
  • Joined: 21 Jan 2009

The easiest way would be to just make those two variables global:

;Provide a show name (greek) and it will return the TVDB data for the show name (Greek) and series ID (80301) as a CSV (Greek,80301)
GetTVDBShows(ShowName)
{
    Global SeriesName, SeriesIDNum
    [...]
}

Also, if I may make a suggestion, make use of the unHTML() function when adding the preview filenames to the list.

LV_Modify(RowNumber, Col1, LVFileName, [color=red]unHTML( NewFileName )[/color], LVFileDir, LVFileExt, SeriesIDNo)

Great script...well written and easy to follow. =]


Thank you, skwire! That did the trick. :D

Ive updated the main post with my now *much* improved version. Let me know what you guys think!

marcusmpe
  • Members
  • 2 posts
  • Last active: Jan 17 2011 11:42 PM
  • Joined: 27 Feb 2009
Great work! I ran into this quirky part today:
StringGetPos, XPos, SeasonAndEpisode, x
StringLeft, SeasonNumber, SeasonAndEpisode, %XPos%
I had a case where this did not correctly extract the episode number from the regular expression result. But here I look today and you've already fixed it! Nicely done.