#!/usr/bin/env python

#***************************************************************************
#*                                                                         *
#*   This program is free software; you can redistribute it and/or modify  *
#*   it under the terms of the GNU General Public License as published by  *
#*   the Free Software Foundation; either version 2 of the License, or     *
#*   (at your option) any later version.                                   *
#*                                                                         *
#***************************************************************************

""" usage: unrarer.py [options]
    Note: .rar files are the only supported file postfix
		  
	This script goes recursivly through folders, finds all rar
    files and extracts them without overwriting existing files. If
    unrar is successfully completed, it automatically removes the 
    rar files it just extracted. 

    	It's useful to create a symbolic link to /usr/bin/unarer so
    it can be called without providing full path to the executable.
    E.g. ln -s /path/to/unrarer.py /usr/bin/unrarer

        You use this script like this;
    $ cd /home/me/downloads/
    $ unrarer    
    
    -h  this help
    
    Written by Ari Bjornsson ari.bjornsson (at) gmail.com
"""

import os
import sys
import getopt
import subprocess


def usage(*args):
    sys.stdout = sys.stderr
    print __doc__
    print 50*"-"
    for msg in args: print msg
    sys.exit(2)

def find(basedir):	
	# list of rar file sets
	set_of_files = []
	# list of rar files that belong together
	set = []
	# sequence indicator, 001..0045 or 01..56
	seq = ''

	# TODO
	# Add support for .r001 files

	#print "find %s -name '*.rar'" % basedir	
	p = subprocess.Popen("find %s -name '*.rar'" % basedir, shell=True, stdout=subprocess.PIPE)

	if p.stdout:
		for line in p.stdout:
			# split fullpath into directory and file name
			split = line.rsplit('/',1)
			
			dir = split[0]
			file = split[1]

			# sequencing has changed, find out how sequencing is done
			# e.g. ...part001 -> 001 (max=3)
			# e.g. ...p07 -> 07 (max=2)
			if seq == '':
				i = 1
				max = 0
				while file.rsplit('.',1)[0][-i:].isdigit():
					max = i
					i = i + 1	

                        # store sequence of file, if no sequence exist lets assume
                        # it is a master file (the one to extract with unrar)   
                        if max != 0:
                                seq = file.rsplit('.',1)[0][-max:]
                        else:
                                seq = 0 

			# Directory has changed, save set in set of files and reset set
			# 
			if len(set) > 0:
				change = False

				old_file_name_base = set[len(set)-1][1].rsplit('.',1)[0][:-max]
                                file_name_base = file.rsplit('.',1)[0][:-max]

				# Change set if the file name base changes or no sequence is found
				if old_file_name_base != file_name_base or seq == 0:
					change = True

				# Change set if directory changes
				if set[len(set)-1][0] != dir:
					change = True

				# Make the change
				if change:				
					set_of_files.append(set)
					set = []
					seq = ''

										

			set.append([dir,file, seq, 0])			
		
		# Add the last set to set of files
		set_of_files.append(set)	

	#print set_of_files			
	return set_of_files

def execute(sets):
	for set in sets:
		master = ''
		seq_min = 10000

		for file in set:
			# compare sequence number
			if file[2] != '':
				if int(file[2]) < seq_min:
					seq_min = int(file[2])
					master = file	
			else:
				master = file
		#print master		
		os.chdir(master[0])
		p = subprocess.Popen("unrar e -o- %s" % master[1], shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
			
		print "Extracting file %s" % master[0] + "/" + master[1]
		p.wait()
		#print p.communicate()[0]

		if p.returncode == 0:
			for file in set:
				print "Removing file %s" % master[0] + "/" + master[1]
				os.remove(file[0]+"/"+file[1].rstrip('\n'))


def main():
	try:
		opts, args = getopt.getopt(sys.argv[1:], ':h')
	except getopt.error, msg:
		usage(msg)

	for o, a in opts:
		if o == '-h':
			print __doc__
			sys.exit()


	basedir = os.getcwd()
	f = find(basedir)	
	if len(f[0]) == 0:
		print "No rar files found"
		sys.exit(1)
	else:	
		execute(f)	

        
if __name__ == '__main__':
	main()

