]>
src.bluestatic.org Git - armadillo.git/blob - src/tv_rename.go
2 // Armadillo File Manager
3 // Copyright (c) 2011, Robert Sesek <http://www.bluestatic.org>
5 // This program is free software: you can redistribute it and/or modify it under
6 // the terms of the GNU General Public License as published by the Free Software
7 // Foundation, either version 3 of the License, or any later version.
25 // Takes a full file path and renames the last path component as if it were a
26 // TV episode. This performs the actual rename as well.
27 func RenameEpisode(inPath
string) (*string, os
.Error
) {
28 // Make sure a path was given.
30 return nil, os
.NewError("Invalid path")
32 // Check that it's inside the jail.
33 var safePath
*string = paths
.Verify(inPath
)
35 return nil, os
.NewError("Path is invalid or outside of jail")
37 // Make sure that the file exists.
38 _
, err
:= os
.Stat(*safePath
)
43 // Parse the filename into its components.
44 dirName
, fileName
:= path
.Split(*safePath
)
45 info
:= parseEpisodeName(fileName
)
47 return nil, os
.NewError("Could not parse file name")
50 // Create the URL and perform the lookup.
51 queryURL
:= buildURL(info
)
52 response
, err
:= performLookup(queryURL
)
57 // Parse the response into the fullEpisodeInfo struct.
58 fullInfo
:= parseResponse(response
)
60 // Create the new path.
61 newName
:= fmt
.Sprintf("%s - %dx%02d - %s", fullInfo
.episode
.showName
,
62 fullInfo
.episode
.season
, fullInfo
.episode
.episode
, fullInfo
.episodeName
)
63 newName
= strings
.Replace(newName
, "/", "_", -1)
64 newName
+= path
.Ext(fileName
)
65 newPath
:= path
.Join(dirName
, newName
)
70 type episodeInfo
struct {
76 type fullEpisodeInfo
struct {
81 // Parses the last path component into a the component structure.
82 func parseEpisodeName(name
string) *episodeInfo
{
83 regex
:= regexp
.MustCompile("(.+)( |\\.)[sS]?([0-9]+)[xeXE]([0-9]+)")
84 matches
:= regex
.FindAllStringSubmatch(name
, -1)
85 if len(matches
) < 1 ||
len(matches
[0]) < 4 {
89 // Convert the season and episode numbers to integers.
90 season
, episode
:= convertEpisode(matches
[0][3], matches
[0][4])
91 if season
== 0 && season
== episode
{
95 // If the separator between the show title and episode is a period, then
96 // it's likely of the form "some.show.name.s03e06.720p.blah.mkv", so strip the
97 // periods in the title.
98 var showName
string = matches
[0][1]
99 if matches
[0][2] == "." {
100 showName
= strings
.Replace(matches
[0][1], ".", " ", -1)
103 return &episodeInfo
{
110 // Builds the URL to which we send a HTTP request to get the episode name.
111 func buildURL(info
*episodeInfo
) string {
112 return fmt
.Sprintf("http://services.tvrage.com/tools/quickinfo.php?show=%s&ep=%dx%d",
113 http
.URLEscape(info
.showName
), info
.season
, info
.episode
)
116 // Converts a season and episode to integers. If the return values are both 0,
117 // an error occurred.
118 func convertEpisode(season
string, episode
string) (int, int) {
119 seasonInt
, err
:= strconv
.Atoi(season
)
123 episodeInt
, err
:= strconv
.Atoi(episode
)
127 return seasonInt
, episodeInt
130 // Performs the actual lookup and returns the HTTP response.
131 func performLookup(urlString
string) (*http
.Response
, os
.Error
) {
132 url
, err
:= http
.ParseURL(urlString
)
137 // Open a TCP connection.
138 conn
, err
:= net
.Dial("tcp", "", url
.Host
+ ":" + url
.Scheme
)
143 // Perform the HTTP request.
144 client
:= http
.NewClientConn(conn
, nil)
145 var request http
.Request
147 request
.Method
= "GET"
148 request
.UserAgent
= "Armadillo File Manager"
149 err
= client
.Write(&request
)
156 // Parses the HTTP response from performLookup().
157 func parseResponse(response
*http
.Response
) *fullEpisodeInfo
{
160 var info fullEpisodeInfo
162 buf
:= bufio
.NewReader(response
.Body
)
163 for ; err
!= os
.EOF
; line
, err
= buf
.ReadString('\n') {
164 // An error ocurred while reading.
168 var parts
[]string = strings
.Split(line
, "@", 2)
174 info
.episode
.showName
= strings
.TrimSpace(parts
[1])
176 // Split the line, which is of the form: |SxE^Name^AirDate|.
177 parts
= strings
.Split(parts
[1], "^", 3)
178 info
.episodeName
= parts
[1]
179 // Split the episode string.
180 episode
:= strings
.Split(parts
[0], "x", 2)
181 info
.episode
.season
, info
.episode
.episode
= convertEpisode(episode
[0], episode
[1])
182 if info
.episode
.season
== 0 && info
.episode
.season
== info
.episode
.episode
{