Skip to content
Newer
Older
100644 315 lines (241 sloc) 10.6 KB
357a78a @midgetspy Added GPL stuff
authored Nov 7, 2009
1 # Author: Nic Wolfe <nic@wolfeden.ca>
2 # URL: http://code.google.com/p/sickbeard/
3 #
e46eb09 @midgetspy Fixed some comments
authored Nov 10, 2009
4 # This file is part of Sick Beard.
357a78a @midgetspy Added GPL stuff
authored Nov 7, 2009
5 #
e46eb09 @midgetspy Fixed some comments
authored Nov 10, 2009
6 # Sick Beard is free software: you can redistribute it and/or modify
357a78a @midgetspy Added GPL stuff
authored Nov 7, 2009
7 # it under the terms of the GNU General Public License as published by
8 # the Free Software Foundation, either version 3 of the License, or
9 # (at your option) any later version.
10 #
e46eb09 @midgetspy Fixed some comments
authored Nov 10, 2009
11 # Sick Beard is distributed in the hope that it will be useful,
357a78a @midgetspy Added GPL stuff
authored Nov 7, 2009
12 # but WITHOUT ANY WARRANTY; without even the implied warranty of
13 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 # GNU General Public License for more details.
15 #
16 # You should have received a copy of the GNU General Public License
e46eb09 @midgetspy Fixed some comments
authored Nov 10, 2009
17 # along with Sick Beard. If not, see <http://www.gnu.org/licenses/>.
357a78a @midgetspy Added GPL stuff
authored Nov 7, 2009
18
19
20
7c9aaa8 @midgetspy Initial commit
authored Nov 6, 2009
21 import os
22 import shutil
23 import sys
24
25 import contactXBMC
26 import exceptions
27 import helpers
28 import sickbeard
16e5b92 @midgetspy * Fixed issue 20
authored Nov 16, 2009
29 import sqlite3
30 import db
7c9aaa8 @midgetspy Initial commit
authored Nov 6, 2009
31
32 from logging import *
33 from common import *
34
35 from sickbeard import classes
16e5b92 @midgetspy * Fixed issue 20
authored Nov 16, 2009
36 from lib.tvdb_api import tvnamer, tvdb_api, tvdb_exceptions
7c9aaa8 @midgetspy Initial commit
authored Nov 6, 2009
37
38 #from tvdb_api.nfogen import createXBMCInfo
39
40 sample_ratio = 0.3
41
42 # #########################
43 # Find the file we're dealing with
44 # #########################
45 def findMainFile (show_dir):
46 # init vars
47 biggest_file = None
48 biggest_file_size = 0
49 next_biggest_file_size = 0
50
51 # find the biggest file in the folder
52 for file in filter(helpers.isMediaFile, os.listdir(show_dir)):
53 cur_size = os.path.getsize(os.path.join(show_dir, file))
54 if cur_size > biggest_file_size:
55 biggest_file = file
56 next_biggest_file_size = biggest_file_size
57 biggest_file_size = cur_size
58
59 if biggest_file == None:
60 return biggest_file
61
62 # it should be by far the biggest file in the folder. If it isn't, we have a problem (multi-show nzb or something, not going to deal with it)
63 if float(next_biggest_file_size) / float(biggest_file_size) > sample_ratio:
64 Logger().log("Multiple files in the folder are comparably large, giving up", ERROR)
65 return None
66
67 return os.path.join(show_dir, biggest_file)
68
69
70 # ########################
71 # Checks if another file exists already, if it
72 # does then we replace only if it's larger.
73 # ########################
74 def moveEpisode(file, ep):
75
76 # if the ep already has an associated file
2717952 @midgetspy Fixed some pathing mistakes in the new template
authored Nov 19, 2009
77 if ep.location != None and os.path.isfile(ep.location):
7c9aaa8 @midgetspy Initial commit
authored Nov 6, 2009
78
79 Logger().log("The episode already has a file downloaded", DEBUG)
80
81 # see if it's smaller than our new file
2717952 @midgetspy Fixed some pathing mistakes in the new template
authored Nov 19, 2009
82 if os.path.getsize(file) > os.path.getsize(ep.location):
7c9aaa8 @midgetspy Initial commit
authored Nov 6, 2009
83
84 Logger().log("The old file is smaller, replacing it", DEBUG)
85
86 try:
2717952 @midgetspy Fixed some pathing mistakes in the new template
authored Nov 19, 2009
87 os.remove(ep.location)
88 Logger().log("Deleted " + str(ep.location), DEBUG)
7c9aaa8 @midgetspy Initial commit
authored Nov 6, 2009
89 with ep.lock:
90 ep.location = None
91 except OSError as e:
92 Logger().log("Unable to delete existing file, it's probably in use (" + str(e) + ")", ERROR)
93
94 # move it to the right folder
95 if ep.show.seasonfolders == True:
96 seasonFolder = 'Season ' + str(ep.season)
97 else:
98 seasonFolder = ''
7d982b4 @midgetspy Fixed a bug with creation of new season folders
authored Nov 18, 2009
99 Logger().log("Seasonfolders were " + str(ep.show.seasonfolders) + " which gave " + seasonFolder, DEBUG)
7c9aaa8 @midgetspy Initial commit
authored Nov 6, 2009
100
101 destDir = os.path.join(ep.show.location, seasonFolder)
7d982b4 @midgetspy Fixed a bug with creation of new season folders
authored Nov 18, 2009
102
103 # if the dir doesn't exist (new season folder) then make it
104 if not os.path.isdir(destDir):
105 Logger().log("Season folder didn't exist, creating it", DEBUG)
106 os.mkdir(destDir)
7c9aaa8 @midgetspy Initial commit
authored Nov 6, 2009
107
108 Logger().log("Moving from " + file + " to " + destDir, DEBUG)
109 try:
110 shutil.move(file, destDir)
111 for curEp in [ep] + ep.relatedEps:
112 with curEp.lock:
113 curEp.location = os.path.join(destDir, os.path.basename(file))
114
115 # don't mess up the status - if this is a legit download it should be SNATCHED
116 if curEp.status != PREDOWNLOADED:
117 curEp.status = DOWNLOADED
2717952 @midgetspy Fixed some pathing mistakes in the new template
authored Nov 19, 2009
118 curEp.saveToDB()
7c9aaa8 @midgetspy Initial commit
authored Nov 6, 2009
119
120 except IOError as e:
121 Logger().log("Unable to move the file: " + str(e), ERROR)
122 return False
123
124 return True
125
126
127 def renameFile(curFile, newName):
128
129 filePath = os.path.split(curFile)
130 oldFile = os.path.splitext(filePath[1])
131
132 newFilename = os.path.join(filePath[0], helpers.sanitizeFileName(newName) + oldFile[1])
133 Logger().log("Renaming from " + curFile + " to " + newFilename)
134
135 try:
136 os.rename(curFile, newFilename)
137 except (OSError, IOError) as e:
138 Logger().log("Failed renaming " + curFile + " to " + os.path.basename(newFilename) + ": " + str(e), ERROR)
139 return False
140
141 return newFilename
142
143
144 def doIt(downloadDir, showList):
145
146 returnStr = ""
147
148 if not os.path.isdir(downloadDir):
149 return "Uh, this is not a directory: " + str(downloadDir)
150
151 # pretty up the path, just in case
152 downloadDir = os.path.abspath(downloadDir)
153 logStr = "Pretty'd up folder is " + downloadDir
154 Logger().log(logStr, DEBUG)
155 returnStr += logStr + "\n"
156
157 # TODO: check if it's failed and deal with it if it is
158 if downloadDir.startswith('_FAILED_'):
159 logStr = "The directory name indicates it failed to extract, cancelling"
160 Logger().log(logStr, DEBUG)
161 returnStr += logStr + "\n"
162 return returnStr
163
164 # find the file we're dealing with
165 biggest_file = findMainFile(downloadDir)
166 if biggest_file == None:
167 logStr = "Unable to find the biggest file - is this really a TV download?"
168 Logger().log(logStr, DEBUG)
169 returnStr += logStr + "\n"
170 return returnStr
171
172 logStr = "The biggest file in the dir is: " + biggest_file
173 Logger().log(logStr, DEBUG)
174 returnStr += logStr + "\n"
175
176 # try to use the file name to get the episode
177 result = None
178 for curName in (biggest_file, downloadDir.split(os.path.sep)[-1]):
179
180 result = tvnamer.processSingleName(curName)
181 logStr = curName + " parsed into: " + str(result)
182 Logger().log(logStr, DEBUG)
183 returnStr += logStr + "\n"
184
185 # if this one doesn't work try the next one
186 if result == None:
187 logStr = "Unable to parse this name"
188 Logger().log(logStr, DEBUG)
189 returnStr += logStr + "\n"
190 continue
16e5b92 @midgetspy * Fixed issue 20
authored Nov 16, 2009
191
192 try:
193 t = tvdb_api.Tvdb(custom_ui=classes.ShowListUI, lastTimeout=sickbeard.LAST_TVDB_TIMEOUT)
194 showObj = t[result["file_seriesname"]]
195 showInfo = (int(showObj["id"]), showObj["seriesname"])
0f4c429 @midgetspy Tons of untested changes, fun.
authored Nov 16, 2009
196 except (tvdb_exceptions.tvdb_error, IOError) as e:
16e5b92 @midgetspy * Fixed issue 20
authored Nov 16, 2009
197
198 logStr = "TVDB didn't respond, trying to look up the show in the DB instead"
199 Logger().log(logStr, DEBUG)
200 returnStr += logStr + "\n"
201
0f4c429 @midgetspy Tons of untested changes, fun.
authored Nov 16, 2009
202 showInfo = helpers.searchDBForShow(result["file_seriesname"])
16e5b92 @midgetspy * Fixed issue 20
authored Nov 16, 2009
203
0f4c429 @midgetspy Tons of untested changes, fun.
authored Nov 16, 2009
204 # if we didn't get anything from TVDB or the DB then try the next option
205 if showInfo == None:
206 continue
207
7c9aaa8 @midgetspy Initial commit
authored Nov 6, 2009
208 # find the show in the showlist
209 try:
16e5b92 @midgetspy * Fixed issue 20
authored Nov 16, 2009
210 showResults = helpers.findCertainShow(showList, showInfo[0])
7c9aaa8 @midgetspy Initial commit
authored Nov 6, 2009
211 except exceptions.MultipleShowObjectsException:
212 raise #TODO: later I'll just log this, for now I want to know about it ASAP
213
214 if showResults != None:
215 logStr = "Found the show in our list, continuing"
216 Logger().log(logStr, DEBUG)
217 returnStr += logStr + "\n"
218 break
16e5b92 @midgetspy * Fixed issue 20
authored Nov 16, 2009
219
220 # end for
7c9aaa8 @midgetspy Initial commit
authored Nov 6, 2009
221
222 if result == None:
223 logStr = "Unable to figure out what this episode is, giving up"
224 Logger().log(logStr, DEBUG)
225 returnStr += logStr + "\n"
226 return returnStr
227
228 if showResults == None:
229 logStr = "The episode doesn't match a show in my list - bad naming?"
230 Logger().log(logStr, DEBUG)
231 returnStr += logStr + "\n"
232 return returnStr
233
234
235
236 # get or create the episode (should be created probably, but not for sure)
237 season = int(result["seasno"])
238
239 rootEp = None
240 for curEpisode in result["epno"]:
241 episode = int(curEpisode)
242
16e5b92 @midgetspy * Fixed issue 20
authored Nov 16, 2009
243 logStr = "TVDB thinks the file is " + showInfo[1] + str(season) + "x" + str(episode)
7c9aaa8 @midgetspy Initial commit
authored Nov 6, 2009
244 Logger().log(logStr, DEBUG)
245 returnStr += logStr + "\n"
246
247 # now that we've figured out which episode this file is just load it manually
248 curEp = showResults.getEpisode(season, episode, True)
249
250 if rootEp == None:
251 rootEp = curEp
252 rootEp.relatedEps = []
253 else:
254 rootEp.relatedEps.append(curEp)
255
2717952 @midgetspy Fixed some pathing mistakes in the new template
authored Nov 19, 2009
256 # wait for the copy to finish
257
7c9aaa8 @midgetspy Initial commit
authored Nov 6, 2009
258 if sickbeard.XBMC_NOTIFY_ONDOWNLOAD == True:
259 contactXBMC.notifyXBMC(rootEp.prettyName(), "Download finished")
260
2717952 @midgetspy Fixed some pathing mistakes in the new template
authored Nov 19, 2009
261 # move it to the show folder
262 #result = moveEpisode(os.path.join(downloadDir, os.path.basename(result)), rootEp)
263 result = moveEpisode(biggest_file, rootEp)
7c9aaa8 @midgetspy Initial commit
authored Nov 6, 2009
264 if result == True:
265 logStr = "File was moved successfully"
266 Logger().log(logStr, DEBUG)
267 returnStr += logStr + "\n"
268 else:
269 logStr = "I couldn't move it, giving up"
270 Logger().log(logStr, DEBUG)
271 returnStr += logStr + "\n"
272 return returnStr
273
2717952 @midgetspy Fixed some pathing mistakes in the new template
authored Nov 19, 2009
274 # rename it
275 logStr = "Renaming the file " + rootEp.location + " to " + rootEp.prettyName()
276 Logger().log(logStr, DEBUG)
277 returnStr += logStr + "\n"
278
279 result = renameFile(rootEp.location, rootEp.prettyName())
280
281 if result == False:
282 logStr = "ERROR: Unable to rename the file " + rootEp.location
283 Logger().log(logStr, DEBUG)
284 returnStr += logStr + "\n"
285 return logStr
286
287 with rootEp.lock:
288 rootEp.location = result
289 rootEp.saveToDB()
290
7c9aaa8 @midgetspy Initial commit
authored Nov 6, 2009
291 # generate nfo/tbn
2717952 @midgetspy Fixed some pathing mistakes in the new template
authored Nov 19, 2009
292 rootEp.createMetaFiles()
293 rootEp.saveToDB()
7c9aaa8 @midgetspy Initial commit
authored Nov 6, 2009
294
295 logStr = "Deleting folder " + downloadDir
296 Logger().log(logStr, DEBUG)
297 returnStr += logStr + "\n"
298
299 # we don't want to put predownloads in the library until we can deal with removing them
300 if sickbeard.XBMC_UPDATE_LIBRARY == True and rootEp.status != PREDOWNLOADED:
301 contactXBMC.updateLibrary(rootEp.show.location)
302
303 # delete the old folder full of useless files
304 try:
305 shutil.rmtree(downloadDir)
306 except (OSError, IOError) as e:
307 logStr = "Warning: unable to remove the folder " + downloadDir + ": " + str(e)
308 Logger().log(logStr, ERROR)
309 returnStr += logStr + "\n"
310
311 return returnStr
312
313 if __name__ == "__main__":
314 doIt(sys.argv[1])
Something went wrong with that request. Please try again.