AutoHotkey Community

It is currently May 26th, 2012, 9:45 pm

All times are UTC [ DST ]




Post new topic Reply to topic  [ 4 posts ] 
Author Message
PostPosted: September 21st, 2009, 4:29 pm 
Offline

Joined: January 21st, 2009, 1:06 pm
Posts: 63
Edit - This code has been completely re-written. The new script can be found here

Lately Ive found myself with a bunch of TV series stored on my external drive and they all have crytpic "scene group" names. I figured I could whip something up in AHK that could connect to TheTVDB.com and automatically rename my files for me.

Heres my rather unpolished and gritty attempt. Im not claiming it to be anything amazing, nor did I intend it to be. I spent my casual free time over the course of a week putting this together. For having no formal training in any sort of other programming language I dont feel like this is too shabby if I do say so myself =P

As always, tweaks, tips, etc will be greatly appreciated!!!

Code:
; AutoHotkey Version: 1.0.48+
;
; Script Function:
;   Extracts season and episode info from the file name
;   then retreives enough info from TheTVDB.com to rename
;   the file to this format: Series Title - SSxEE - Episode Title

#NoEnv
SendMode, Input
SetWorkingDir, %A_ScriptDir%

Mirror_Path = http://www.thetvdb.com
apikey = 563E39CDC7F666DF
File_Types_Search = avi,mkv,mp4

FileSelectFolder, Target_Folder

File_List =
Loop, %Target_Folder%\*.*
{
   If A_LoopFileExt contains %File_Types_Search%
      File_List = %File_List%%A_LoopFileName%`n                 ; Append the current filename from the parsing loop to File_List
}

If File_List =
{
   MsgBox, 0, Fatal Error!,No matching filetypes found in %Target_Folder%`n`nExiting script...
   ExitApp
}

Loop, Parse, File_List, `n
{
   If A_LoopField =                                             ; Removes the blank item at the end of the list
      Break
   Original_File_Name = %A_LoopField%                           ; Stores the original file name for later use
   No_Period_Name := RegExReplace(A_LoopField, "\.", " ")       ; Remove all periods from file name
   ;Get file ext
   IfInString, No_Period_Name, avi
      RegExMatch(No_Period_Name, "avi", File_Ext)               ; Store "avi" in File_Ext
   IfInString, No_Period_Name, mkv
      RegExMatch(No_Period_Name, "mkv", File_Ext)               ; Store "mkv" in File_Ext
   IfInString, No_Period_Name, mp4
      RegExMatch(No_Period_Name, "mp4", File_Ext)               ; Store "mp4" in File_Ext
   ;Get series title
   RegExMatch(No_Period_Name, "[a-zA-Z -&]+", First_Word_Set)   ; Match everything up to the first digit
   StringTrimRight, Series_Name, First_Word_Set, 1              ; Remove proceeding space that almost always exists
   StringLen, Series_Name_Len, Series_Name                      ; Count chars for StringMid
   StringMid, Last_Char, Series_Name, %Series_Name_Len%, 1, L   ; Pull the last char from the right
   If (Last_Char = "-") or (Last_Char = " ")                    ; If last char is a dash or space
      StringTrimRight, Series_Name, Series_Name, 1              ; Trim it
   ;Get season number and episode number
   If RegExMatch(No_Period_Name, "i)s[0-9][0-9]?e[0-9][0-9]?", Season_Ep_Raw)
   {                                                            ; ===s04e02 and similar variations===
      ; ==Season==
      StringTrimRight, Season_Num, Season_Ep_Raw, 2             ; Remove episode number(s) and potentially "e"
      StringTrimLeft, Season_Num, Season_Num, 1                 ; Remove preceeding "S"
      IfInString, Season_Num, e                                 ; If proceeding "e" still exists
         StringTrimRight, Season_Num, Season_Num, 1             ; Trim it
      IfInString, Season_Num, 0                                 ; If a zero exists in Season_Num
      {
         StringGetPos, Zero_Loc, Season_Num, 0                  ; Determine the zero loc
         If Zero_Loc = 0                                        ; If it is the first char
            StringTrimLeft, Season_Num, Season_Num, 1           ; Trim it
      }
      ; ==Episode==
      StringTrimLeft, Episode_Num, Season_Ep_Raw, 3             ; Remove season number(s) and potentially "e"
      IfInString, Episode_Num, e                                ; If proceeding "e" still exists
         StringTrimleft, Episode_Num, Episode_Num, 1            ; Trim it
      IfInString, Episode_Num, 0                                ; If a zero exists in Episode_Num
      {
         StringGetPos, Zero_Loc, Episode_Num, 0                 ; Determine the zero loc
         If Zero_Loc = 0                                        ; If it is the first char
            StringTrimLeft, Episode_Num, Episode_Num, 1         ; Trim it
      }
   }
   Else If RegExMatch(No_Period_Name, "i)[0-9][0-9]?x[0-9][0-9]?", Season_Ep_Raw)
   {                                                            ; ===04x02 and similar variations===
      ; ==Season==
      StringTrimRight, Season_Num, Season_Ep_Raw, 2             ; Remove episode number(s) and potentialy "x"
      IfInString, Season_Num, x                                 ; If proceeding "x" still exists
         StringTrimRight, Season_Num, Season_Num, 1             ; Trim it
      IfInString, Season_Num, 0                                 ; If a zero exists in Season_Num
      {
         StringGetPos, Zero_Loc, Season_Num, 0                  ; Determine the zero loc
         If Zero_Loc = 0                                        ; If it is the first char
            StringTrimLeft, Season_Num, Season_Num, 1           ; Trim it
      }
      ; ==Episode==
      StringTrimLeft, Episode_Num, Season_Ep_Raw, 2             ; Remove season number(s) and potentially "x"
      IfInString, Episode_Num, x                                ; If preceeding "x" still exists
         StringTrimLeft, Episode_Num, Episode_Num, 1            ; Trim It
      IfInString, Episode_Num, 0                                ; If a zero exists in Episode_Num
      {
         StringGetPos, Zero_Loc, Episode_Num, 0                 ; Determine the zero loc
         If Zero_Loc = 0                                        ; If it is the first char
            StringTrimLeft, Episode_Num, Episode_Num, 1         ; Trim it
      }
   }
   Else If RegExMatch(No_Period_Name, "[0-9][0-9][0-9][0-9]?", Season_Ep_Raw)
   {                                                            ; ===0402 and 402 are the only supported formats===
      ; ==Season==
      StringTrimRight, Season_Num, Season_Ep_Raw, 2             ; Remove two episode numbers
      IfInString, Season_Num, 0                                 ; If a zero exists in Season_Num
      {
         StringGetPos, Zero_Loc, Season_Num, 0                  ; Determine the zero loc
         If Zero_Loc = 0                                        ; If it is the first char
            StringTrimLeft, Season_Num, Season_Num, 1           ; Trim it
      }
      ; ==Episode==
      StringTrimLeft, Episode_Num, Season_Ep_Raw, 1             ; Remove first char as it should always be part of the season number
      StringLen, Episode_Num_Len, Episode_Num                   ; Count string chars to determine if trim is needed
      If Episode_Num_Len = 3                                    ; 3 chars usually means part of season number still exists
         StringTrimLeft, Episode_Num, Episode_Num, 1            ; Trim it
      IfInString, Episode_Num, 0                                ; If a zero exists in Episode_Num
      {
         StringGetPos, Zero_Loc, Episode_Num, 0                 ; Determine the zero loc
         If Zero_Loc = 0                                        ; If it is the first char
            StringTrimLeft, Episode_Num, Episode_Num, 1         ; Trim it
      }
   }   
   GoSub, Get_Series_ID
}
MsgBox, 0, Attention, No more files left to rename
ExitApp

Get_Series_ID:
{
   IfExist, Series_ID.xml
      FileDelete, Series_ID.xml
   UrlDownloadToFile, http://www.thetvdb.com/api/GetSeries.php?seriesname="%Series_Name%", Series_ID.xml
   Loop
   {
      IfExist, Series_ID.xml
         Break
   }
   FileRead, Series_ID_Full, Series_ID.xml
   Loop
   {
      StringReplace, Series_ID_Full, Series_ID_Full, </Series>, ¤, UseErrorLevel
      If ErrorLevel = 0
         Break
   }
   Loop, Parse, Series_ID_Full, ¤
   {
      RegExMatch(A_LoopField, "<seriesid>\K[^<>]+", Series_ID_No)
      RegExMatch(A_LoopField, "i)<seriesname>\K[^<>]+", Series_X_Name)
      RegExMatch(A_LoopField, "i)<overview>\K[^<>]+", Series_Overview)
      If (Series_X_Name = "" && Series_ID_No = "")
         Continue
      MsgBox, 4, , Using "%Series_Name%" as the show name`n`nHeres what matches from TheTVDB.com:`n`n%A_Tab%Show Name:%A_Tab%%Series_X_Name%`n%A_Tab%Series ID:%A_Tab%%A_Tab%%Series_ID_No%`n%A_Tab%Series Overview: `n%Series_Overview%
      IfMsgBox, Yes
         {
         GoSub, Get_Episode_Info
         Break
         }
   }
   If (Series_X_Name = "" && Series_ID_No = "")
      MsgBox, 0, Critical Error!, No shows found for %A_LoopField% on TheTVDB.com
   FileDelete, Series_ID.xml
}
Return

Get_Episode_Info:
{
   IfExist, Episode_Info.xml
      FileDelete, Episode_Info.xml
   UrlDownloadToFile, %Mirror_Path%/api/%APIKey%/series/%Series_ID_No%/default/%Season_Num%/%Episode_Num%/en.xml, Episode_Info.xml
   Loop
   {
      IfExist, Episode_Info.xml
         Break
   }
   FileRead, Episode_Info_Full, Episode_Info.xml
   Loop
   {
      StringReplace, Episode_Info_Full, Episode_Info_Full, </Episode>, ¤, UseErrorLevel
         If ErrorLevel = 0
            Break
   }
   Loop, Parse, Episode_Info_Full, ¤
   {
      RegExMatch(A_LoopField, "i)<EpisodeNumber>\K[^<>]+", Episode_X_Num)
      RegExMatch(A_LoopField, "i)<EpisodeName>\K[^<>]+", Episode_X_Name)
      RegExMatch(A_LoopField, "i)<Overview>\K[^<>]+", Episode_X_Overview)
      RegExMatch(A_LoopField, "i)<SeasonNumber>\K[^<>]+", Season_X_Num)
      If (Episode_X_Num = "" && Episode_X_Name = "" && Season_X_Num = "")
         Continue
      MsgBox, 4, , Using "%Series_X_Name%" with season number "%Season_Num%" and episode number "%Episode_Num%"`n`nHeres what matches on TheTVDB.com:`n`n%A_Tab%Show Name:%A_Tab%%Series_X_Name%`n%A_Tab%Season Number :%A_Tab%%Season_X_Num%`n%A_Tab%Episode Number :%A_Tab%%Episode_X_Num%`n%A_Tab%Episode Title :%A_Tab%%Episode_X_Name%`n%A_Tab%Episode Overview :`n%Episode_X_Overview%
      IfMsgBox, Yes
      {
         GoSub, Rename_File
         Break
      }
   }
   If (Episode_X_Num = "" && Episode_X_Name = "" && Season_X_Num = "")
      MsgBox, 0, Critical Error!, No episode matches for "%Series_X_Name%" season "%Season_Num%" episode "%Episode_Num%"
   FileDelete, Episode_Info.xml
}
Return

Rename_File:
   If (Season_X_Num != "" && Episode_X_Num != "" and Episode_X_Name != "")
   {
      StringLen, Season_X_Num_Len, Season_X_Num
      If Season_X_Num_Len = 1
         Season_X_Num = 0%Season_X_Num%
      StringLen, Episode_X_Num_Len, Episode_X_Num
      If Episode_X_Num_Len = 1
         Episode_X_Num = 0%Episode_X_Num%
      New_File_Name = %Series_X_Name% - %Season_X_Num%x%Episode_X_Num% - %Episode_X_Name%.%File_Ext%
      MsgBox, 4, Confirm rename?, %Original_File_Name%`n`nwill become`n`n%New_File_Name%
      IfMsgBox, No
         MsgBox, 0, Rename cancelled!, File **WAS NOT** renamed
      IfMsgBox, Yes
      {
         FileMove, %Target_Folder%\%Original_File_Name%, %Target_Folder%\%New_File_Name%
         MsgBox, 0, Congratulations!, File was succesfully renamed!!
      }
   }
Return


Edit - Tweaked naming scheme (thanks Trubbleguy!).
Edit2 - Misc code tweaks and cleanup


Last edited by strictlyfocused02 on October 6th, 2009, 5:50 pm, edited 5 times in total.

Report this post
Top
 Profile  
Reply with quote  
 Post subject: Renamer
PostPosted: September 22nd, 2009, 2:13 am 
Offline

Joined: January 20th, 2007, 1:29 pm
Posts: 96
Location: Melbourne
Great Job, but it removes the series name, leaving just a number and episode name, a second try on the same folder finds no matches online as the series name is now missing. eg.
03x01 - Bad to the Drone.avi

I would suggest a listview with the original name in column 1, the fixed name in column 2, and option to fix all names at the end with a "Fix" button or press enter on a Row to rename individual files.

but most important is the missing Series name as windows search will not find your avi file at a later date.....eg.

Eureka - 03x01 - Bad to the Drone.avi

_________________
Image


Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: September 22nd, 2009, 5:33 am 
Offline

Joined: January 21st, 2009, 1:06 pm
Posts: 63
Thanks Trubbleguy! I edited my first post to now include the series title in the filename.

The reason it was missing to begin with is because I stream the episodes to my 360 and I need the filename to be short so I can see the episode title.

As for the list view, I am definitely going to play around with that idea and see what I can work up. Thanks for the idea!


Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: October 25th, 2009, 2:49 pm 
There are lots of tv renamers out there.

http://filebot.sourceforge.net
FileBot is the ultimate all-in-one tool for tv renaming, downloading subtitles and file verification. Very efficient but not necessarily easy to use.

http://www.therenamer.com
Very simple and works for most stuff.

There is also EpRenamer, Natbur's TV Renamer, etc.


Report this post
Top
  
Reply with quote  
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 4 posts ] 

All times are UTC [ DST ]


Who is online

Users browsing this forum: Bing [Bot] and 6 guests


You can post new topics in this forum
You can reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot post attachments in this forum

Search for:
Powered by phpBB® Forum Software © phpBB Group