Blame | Last modification | View Log | Download
# Written by John Hoffman and Uoti Urpala# see LICENSE.txt for license informationfrom bencode import bencode, bdecodefrom BT1.btformats import check_infofrom os.path import exists, isfilefrom sha import shaimport sys, ostry:Trueexcept:True = 1False = 0NOISY = Falsedef _errfunc(x):print ":: "+xdef parsedir(directory, parsed, files, blocked,exts = ['.torrent'], return_metainfo = False, errfunc = _errfunc):if NOISY:errfunc('checking dir')dirs_to_check = [directory]new_files = {}new_blocked = {}torrent_type = {}while dirs_to_check: # first, recurse directories and gather torrentsdirectory = dirs_to_check.pop()newtorrents = Falsefor f in os.listdir(directory):newtorrent = Nonefor ext in exts:if f.endswith(ext):newtorrent = ext[1:]breakif newtorrent:newtorrents = Truep = os.path.join(directory, f)new_files[p] = [(os.path.getmtime(p), os.path.getsize(p)), 0]torrent_type[p] = newtorrentif not newtorrents:for f in os.listdir(directory):p = os.path.join(directory, f)if os.path.isdir(p):dirs_to_check.append(p)new_parsed = {}to_add = []added = {}removed = {}# files[path] = [(modification_time, size), hash], hash is 0 if the file# has not been successfully parsedfor p,v in new_files.items(): # re-add old items and check for changesoldval = files.get(p)if not oldval: # new fileto_add.append(p)continueh = oldval[1]if oldval[0] == v[0]: # file is unchanged from last parseif h:if blocked.has_key(p): # parseable + blocked means duplicateto_add.append(p) # other duplicate may have gone awayelse:new_parsed[h] = parsed[h]new_files[p] = oldvalelse:new_blocked[p] = 1 # same broken unparseable filecontinueif parsed.has_key(h) and not blocked.has_key(p):if NOISY:errfunc('removing '+p+' (will re-add)')removed[h] = parsed[h]to_add.append(p)to_add.sort()for p in to_add: # then, parse new and changed torrentsnew_file = new_files[p]v,h = new_fileif new_parsed.has_key(h): # duplicateif not blocked.has_key(p) or files[p][0] != v:errfunc('**warning** '+p +' is a duplicate torrent for '+new_parsed[h]['path'])new_blocked[p] = 1continueif NOISY:errfunc('adding '+p)try:ff = open(p, 'rb')d = bdecode(ff.read())check_info(d['info'])h = sha(bencode(d['info'])).digest()new_file[1] = hif new_parsed.has_key(h):errfunc('**warning** '+p +' is a duplicate torrent for '+new_parsed[h]['path'])new_blocked[p] = 1continuea = {}a['path'] = pf = os.path.basename(p)a['file'] = fa['type'] = torrent_type[p]i = d['info']l = 0nf = 0if i.has_key('length'):l = i.get('length',0)nf = 1elif i.has_key('files'):for li in i['files']:nf += 1if li.has_key('length'):l += li['length']a['numfiles'] = nfa['length'] = la['name'] = i.get('name', f)def setkey(k, d = d, a = a):if d.has_key(k):a[k] = d[k]setkey('failure reason')setkey('warning message')setkey('announce-list')if return_metainfo:a['metainfo'] = dexcept:errfunc('**warning** '+p+' has errors')new_blocked[p] = 1continuetry:ff.close()except:passif NOISY:errfunc('... successful')new_parsed[h] = aadded[h] = afor p,v in files.items(): # and finally, mark removed torrentsif not new_files.has_key(p) and not blocked.has_key(p):if NOISY:errfunc('removing '+p)removed[v[1]] = parsed[v[1]]if NOISY:errfunc('done checking')return (new_parsed, new_files, new_blocked, added, removed)