358 |
ira |
1 |
################################################################################
|
|
|
2 |
# The PAR2 Classifier Module
|
|
|
3 |
#
|
|
|
4 |
# Copyright 2006, Ira W. Snyder (devel@irasnyder.com)
|
|
|
5 |
# License: GNU General Public License v2 (or, at your option, any later version)
|
|
|
6 |
#
|
|
|
7 |
# This class makes a best guess as to what type of set we're dealing
|
|
|
8 |
# with here. Of course, this is just a _GUESS_, but I hope it's pretty good.
|
|
|
9 |
#
|
|
|
10 |
# Future Improvements
|
|
|
11 |
# 1. Read a config file to get a few extra customizable types, which
|
|
|
12 |
# will let you run an arbitrary command on a set of files that contains
|
|
|
13 |
# a certain type of file
|
|
|
14 |
################################################################################
|
|
|
15 |
|
|
|
16 |
import os, re, sys
|
|
|
17 |
|
|
|
18 |
class Par2Classifier (object):
|
|
|
19 |
|
|
|
20 |
def __init__ (self, Par2Parser):
|
|
|
21 |
# Give this function a valid Par2Parser that has already
|
|
|
22 |
# been run on your set of files. It will be used to figure
|
|
|
23 |
# out the types that are in this set
|
|
|
24 |
|
|
|
25 |
# An enum of types
|
|
|
26 |
( self.UNKNOWN_TYPE, # Represents a type that we don't know about yet
|
|
|
27 |
|
|
|
28 |
self.S_SPLIT_000, # Single file protected, LXSplit, starting with .000
|
|
|
29 |
self.M_SPLIT_000, # Multiple files protected, LXSplit, starting with .000
|
|
|
30 |
self.S_SPLIT_001, # Single file protected, LXSplit, starting with .001
|
|
|
31 |
self.M_SPLIT_001, # Multiple files protected, LXSplit, starting with .001
|
|
|
32 |
|
|
|
33 |
self.S_PROT_SPLIT_000, # All .DDD files protected, LXSplit, starting with .000 (single set)
|
|
|
34 |
self.M_PROT_SPLIT_000, # All .DDD files protected, LXSplit, starting with .000 (multiple sets)
|
|
|
35 |
self.S_PROT_SPLIT_001, # All .DDD files protected, LXSplit, starting with .001 (single set)
|
|
|
36 |
self.M_PROT_SPLIT_001, # All .DDD files protected, LXSplit, starting with .001 (multiple sets)
|
|
|
37 |
|
|
|
38 |
self.S_RAR_OLD, # Single set of rars, Old style, starting with .rDD
|
|
|
39 |
self.M_RAR_OLD, # Multiple set of rars, Old style, starting with .rDD
|
|
|
40 |
self.S_RAR_NEW, # Single set of rars, New style, starting with .partDD.rar
|
|
|
41 |
self.M_RAR_NEW, # Multiple set of rars, New style, starting with .partDD.rar
|
|
|
42 |
|
|
|
43 |
) = range (13) # WARNING: If adding types, increment this number appropriately
|
|
|
44 |
|
|
|
45 |
|
|
|
46 |
self.Par2Parser = Par2Parser
|
|
|
47 |
self.type = self.UNKNOWN_TYPE
|
|
|
48 |
self.heads = []
|
|
|
49 |
|
|
|
50 |
def __get_type (self):
|
|
|
51 |
# This will return one of the enums above corresponding to the
|
|
|
52 |
# best guess about what type of set we're trying to extract.
|
|
|
53 |
#
|
|
|
54 |
# This information will be used later to decide how to repair
|
|
|
55 |
# and possibly extract this set of files
|
|
|
56 |
|
|
|
57 |
matches = self.__apply_regex ('^.*\.000$', self.Par2Parser.protected_files)
|
|
|
58 |
|
|
|
59 |
# Check to see if we've got a M_PROT_SPLIT_000 set
|
|
|
60 |
if len (matches) > 1:
|
|
|
61 |
return self.M_PROT_SPLIT_000
|
|
|
62 |
|
|
|
63 |
# Check to see if we've got a S_PROT_SPLIT_000 set
|
|
|
64 |
if len (matches) == 1:
|
|
|
65 |
return self.S_PROT_SPLIT_000
|
|
|
66 |
|
|
|
67 |
matches = self.__apply_regex ('^.*\.001$', self.Par2Parser.protected_files)
|
|
|
68 |
|
|
|
69 |
# Check to see if we've got a M_PROT_SPLIT_001 set
|
|
|
70 |
if len (matches) > 1:
|
|
|
71 |
return self.M_PROT_SPLIT_001
|
|
|
72 |
|
|
|
73 |
# Check if we've got a S_PROT_SPLIT_001 set
|
|
|
74 |
if len (matches) == 1:
|
|
|
75 |
return self.S_PROT_SPLIT_001
|
|
|
76 |
|
|
|
77 |
matches = self.__apply_regex ('^.*\.000$', self.Par2Parser.possible_files)
|
|
|
78 |
|
|
|
79 |
# Check if we've got a M_SPLIT_000 set
|
|
|
80 |
if len (matches) > 1 and len (self.Par2Parser.protected_files) > 1:
|
|
|
81 |
return self.M_SPLIT_000
|
|
|
82 |
|
|
|
83 |
# Check if we've got a S_SPLIT_000 set
|
|
|
84 |
if len (matches) == 1 and len (self.Par2Parser.protected_files) == 1:
|
|
|
85 |
return self.S_SPLIT_000
|
|
|
86 |
|
|
|
87 |
matches = self.__apply_regex ('^.*\.001$', self.Par2Parser.possible_files)
|
|
|
88 |
|
|
|
89 |
# Check if we've got a M_SPLIT_001 set
|
|
|
90 |
if len (matches) > 1 and len (self.Par2Parser.protected_files) > 1:
|
|
|
91 |
return self.M_SPLIT_001
|
|
|
92 |
|
|
|
93 |
# Check if we've got a S_SPLIT_001 set
|
|
|
94 |
if len (matches) == 1 and len (self.Par2Parser.protected_files) == 1:
|
|
|
95 |
return self.S_SPLIT_001
|
|
|
96 |
|
|
|
97 |
matches = self.__apply_regex ('^.*\.part0*1\.rar$',
|
|
|
98 |
self.Par2Parser.protected_files,
|
|
|
99 |
ignorecase=True)
|
|
|
100 |
|
|
|
101 |
# Check if we've got a M_RAR_NEW set
|
|
|
102 |
if len (matches) > 1:
|
|
|
103 |
return self.M_RAR_NEW
|
|
|
104 |
|
|
|
105 |
# Check if we've got a S_RAR_NEW set
|
|
|
106 |
if len (matches) == 1:
|
|
|
107 |
return self.S_RAR_NEW
|
|
|
108 |
|
|
|
109 |
matches = self.__apply_regex ('^.*\.r00$',
|
|
|
110 |
self.Par2Parser.protected_files,
|
|
|
111 |
ignorecase=True)
|
|
|
112 |
|
|
|
113 |
# Check if we've got a M_RAR_OLD set
|
|
|
114 |
if len (matches) > 1:
|
|
|
115 |
return self.M_RAR_OLD
|
|
|
116 |
|
|
|
117 |
# Check if we've got a S_RAR_OLD set
|
|
|
118 |
if len (matches) == 1:
|
|
|
119 |
return self.S_RAR_OLD
|
|
|
120 |
|
|
|
121 |
return self.UNKNOWN_TYPE
|
|
|
122 |
|
|
|
123 |
def __apply_regex (self, regex_str, li, ignorecase=False, search=False):
|
|
|
124 |
"""Runs the regex given through the list, and returns matches
|
|
|
125 |
a list of things that either match() (the default) or search()"""
|
|
|
126 |
|
|
|
127 |
# Decide whether or not to use re.IGNORECASE
|
|
|
128 |
if ignorecase:
|
|
|
129 |
regex = re.compile (regex_str, re.IGNORECASE)
|
|
|
130 |
else:
|
|
|
131 |
regex = re.compile (regex_str)
|
|
|
132 |
|
|
|
133 |
# Decide whether to use re.search() or re.match()
|
|
|
134 |
if search:
|
|
|
135 |
return [i for i in li if regex.search (i)]
|
|
|
136 |
else:
|
|
|
137 |
return [i for i in li if regex.match (i)]
|
|
|
138 |
|
|
|
139 |
def __get_extractable_files (self):
|
|
|
140 |
# Returns a list of all of the "head" extractable files
|
|
|
141 |
# NOTE: an extractable file is a .000, .001, .r00, .rar
|
|
|
142 |
# or whatever else makes sense for this type of set
|
|
|
143 |
#
|
|
|
144 |
if self.type == self.S_SPLIT_000 or self.type == self.M_SPLIT_000:
|
|
|
145 |
return self.__apply_regex ('^.*\.000$', self.Par2Parser.possible_files)
|
|
|
146 |
|
|
|
147 |
if self.type == self.S_SPLIT_001 or self.type == self.M_SPLIT_001:
|
|
|
148 |
return self.__apply_regex ('^.*\.001$', self.Par2Parser.possible_files)
|
|
|
149 |
|
|
|
150 |
if self.type == self.S_PROT_SPLIT_000 or self.type == self.M_PROT_SPLIT_000:
|
|
|
151 |
return self.__apply_regex ('^.*\.000$', self.Par2Parser.protected_files)
|
|
|
152 |
|
|
|
153 |
if self.type == self.S_PROT_SPLIT_001 or self.type == self.M_PROT_SPLIT_001:
|
|
|
154 |
return self.__apply_regex ('^.*\.001$', self.Par2Parser.protected_files)
|
|
|
155 |
|
|
|
156 |
if self.type == self.S_RAR_OLD or self.type == self.M_RAR_OLD:
|
|
|
157 |
return self.__apply_regex ('^.*\.r00$', self.Par2Parser.protected_files,
|
|
|
158 |
ignorecase=True)
|
|
|
159 |
|
|
|
160 |
if self.type == self.S_RAR_NEW or self.type == self.M_RAR_NEW:
|
|
|
161 |
return self.__apply_regex ('^.*\.part0*1\.rar$', self.Par2Parser.protected_files,
|
|
|
162 |
ignorecase=True)
|
|
|
163 |
|
|
|
164 |
return [] # Return nothing by default (this covers UNKNOWN_TYPE)
|
|
|
165 |
|
|
|
166 |
def do_magic (self):
|
|
|
167 |
"""Do all the magic to fill our fields by classifying files
|
|
|
168 |
and finding the extractable heads"""
|
|
|
169 |
|
|
|
170 |
self.type = self.__get_type ()
|
|
|
171 |
self.heads = self.__get_extractable_files ()
|
|
|
172 |
|
|
|
173 |
|
|
|
174 |
if __name__ == '__main__':
|
|
|
175 |
pass
|