def user_unpack_comic(self, ish_id, comic_path): logger.info("%s unpack requested" % comic_path) for root, dirs, files in os.walk(os.path.join(mylar.CONFIG.CACHE_DIR, "webviewer", ish_id), topdown=False): for f in files: os.chmod(os.path.join(root, f), stat.S_IRWXU | stat.S_IRWXG | stat.S_IRWXO) # 0777 os.remove(os.path.join(root, f)) for root, dirs, files in os.walk(os.path.join(mylar.CONFIG.CACHE_DIR, "webviewer", ish_id), topdown=False): for d in dirs: os.chmod(os.path.join(root, d), stat.S_IRWXU | stat.S_IRWXG | stat.S_IRWXO) # 0777 os.rmdir(os.path.join(root, d)) if comic_path.endswith(".cbr"): opened_rar = rarfile.RarFile(comic_path) opened_rar.extractall( os.path.join(mylar.CONFIG.CACHE_DIR, "webviewer", ish_id)) elif comic_path.endswith(".cbz"): opened_zip = zipfile.ZipFile(comic_path) opened_zip.extractall( os.path.join(mylar.CONFIG.CACHE_DIR, "webviewer", ish_id)) return
def user_unpack_comic(self, ish_id, comic_path): logger.info("%s unpack requested" % comic_path) for root, dirs, files in os.walk(os.path.join(mylar.CONFIG.CACHE_DIR, "webviewer", ish_id), topdown=False): for f in files: os.chmod(os.path.join(root, f), stat.S_IRWXU | stat.S_IRWXG | stat.S_IRWXO) # 0777 os.remove(os.path.join(root, f)) for root, dirs, files in os.walk(os.path.join(mylar.CONFIG.CACHE_DIR, "webviewer", ish_id), topdown=False): for d in dirs: os.chmod(os.path.join(root, d), stat.S_IRWXU | stat.S_IRWXG | stat.S_IRWXO) # 0777 os.rmdir(os.path.join(root, d)) if comic_path.endswith(".cbr"): opened_rar = rarfile.RarFile(comic_path) for rar_info in opened_rar.infolist(): if rar_info.filename[-1] == '/': continue rar_info.filename = os.path.basename(rar_info.filename) opened_rar.extract( rar_info, os.path.join(mylar.CONFIG.CACHE_DIR, "webviewer", ish_id)) elif comic_path.endswith(".cbz"): opened_zip = zipfile.ZipFile(comic_path) for zip_info in opened_zip.infolist(): if zip_info.filename[-1] == '/': continue zip_info.filename = os.path.basename(zip_info.filename) opened_zip.extract( zip_info, os.path.join(mylar.CONFIG.CACHE_DIR, "webviewer", ish_id)) return
def open_archive(location): if location.endswith(".cbz"): return zipfile.ZipFile(location), 'is_dir' else: try: return rarfile.RarFile(location), 'isdir' except rarfile.BadRarFile as e: logger.warn('[WARNING] %s: %s' % (location, e)) try: logger.info( 'Trying to see if this is a zip renamed as a rar: %s' % (location)) return zipfile.ZipFile(location), 'is_dir' except Exception as e: logger.warn('[EXCEPTION] %s' % e) except Exception as e: logger.warn('[EXCEPTION]: %s' % e)
def _custom_exceptions_fetcher(): custom_exception_dict = {} cnt_updated_numbers = 0 src_id = 'GHSG' logger.log(u'Checking to update custom alternatives from %s' % src_id) dirpath = ek.ek(os.path.join, sickbeard.CACHE_DIR, 'alts') tmppath = ek.ek(os.path.join, dirpath, 'tmp') file_rar = ek.ek(os.path.join, tmppath, 'alt.rar') file_cache = ek.ek(os.path.join, dirpath, 'alt.json') iv = 30 * 60 # min interval to fetch updates refresh = should_refresh(src_id, iv) fetch_data = not ek.ek(os.path.isfile, file_cache) or ( not int(os.environ.get('NO_ALT_GET', 0)) and refresh) if fetch_data: if ek.ek(os.path.exists, tmppath): helpers.remove_file(tmppath, tree=True) helpers.make_dirs(tmppath) helpers.download_file( r'https://github.com/SickGear/sickgear.altdata/raw/master/alt.rar', file_rar) rar_handle = None if 'win32' == sys.platform: rarfile.UNRAR_TOOL = ek.ek(os.path.join, sickbeard.PROG_DIR, 'lib', 'rarfile', 'UnRAR.exe') try: rar_handle = rarfile.RarFile(file_rar) rar_handle.extractall(path=dirpath, pwd='sickgear_alt') except (BaseException, Exception) as e: logger.log( u'Failed to unpack archive: %s with error: %s' % (file_rar, ex(e)), logger.ERROR) if rar_handle: rar_handle.close() del rar_handle helpers.remove_file(tmppath, tree=True) if refresh: set_last_refresh(src_id) data = {} try: with io.open(file_cache) as fh: data = json.load(fh) except (BaseException, Exception) as e: logger.log( u'Failed to unpack json data: %s with error: %s' % (file_rar, ex(e)), logger.ERROR) # handle data from .scene_numbering import find_scene_numbering, set_scene_numbering_helper from .tv import TVidProdid for tvid_prodid, season_data in iteritems(data): show_obj = sickbeard.helpers.find_show_by_id(tvid_prodid, no_mapped_ids=True) if not show_obj: continue used = set() for for_season, data in iteritems(season_data): for_season = helpers.try_int(for_season, None) tvid, prodid = TVidProdid(tvid_prodid).tuple if data.get('n'): # alt names custom_exception_dict.setdefault((tvid, prodid), []) custom_exception_dict[(tvid, prodid)] += [{ name: for_season } for name in data.get('n')] for update in data.get('se') or []: for for_episode, se_range in iteritems( update): # scene episode alt numbers for_episode = helpers.try_int(for_episode, None) target_season, episode_range = se_range.split('x') scene_episodes = [ int(x) for x in episode_range.split('-') if None is not helpers.try_int(x, None) ] if 2 == len(scene_episodes): desc = scene_episodes[0] > scene_episodes[1] if desc: # handle a descending range case scene_episodes.reverse() scene_episodes = list_range( *[scene_episodes[0], scene_episodes[1] + 1]) if desc: scene_episodes.reverse() target_season = helpers.try_int(target_season, None) for target_episode in scene_episodes: sn = find_scene_numbering(tvid, prodid, for_season, for_episode) used.add((for_season, for_episode, target_season, target_episode)) if sn and ((for_season, for_episode) + sn) not in used \ and (for_season, for_episode) not in used: logger.log( u'Skipped setting "%s" episode %sx%s to target a release %sx%s because set to %sx%s' % (show_obj.name, for_season, for_episode, target_season, target_episode, sn[0], sn[1]), logger.DEBUG) else: used.add((for_season, for_episode)) if not sn or sn != (target_season, target_episode ): # not already set result = set_scene_numbering_helper( tvid, prodid, for_season=for_season, for_episode=for_episode, scene_season=target_season, scene_episode=target_episode) if result.get('success'): cnt_updated_numbers += 1 for_episode = for_episode + 1 return custom_exception_dict, cnt_updated_numbers, should_refresh( src_id, iv, remaining=True)
def extract_image(location, single=False, imquality=None): #location = full path to the cbr/cbz (filename included in path) #single = should be set to True so that a single file can have the coverfile # extracted and have the cover location returned to the calling function #imquality = the calling function ('notif' for notifications will initiate a resize image before saving the cover) if PIL_Found is False: return cover = "notfound" pic_extensions = ('.jpg','.png','.webp') issue_ends = ('1','0') modtime = os.path.getmtime(location) low_infile = 999999999999999999 low_num = 1000 local_filename = os.path.join(mylar.CONFIG.CACHE_DIR, 'temp_notif') cb_filename= None cb_filenames=[] metadata = None if single is True: if location.endswith(".cbz"): location_in = zipfile.ZipFile(location) dir_opt = 'is_dir' actual_ext = '.cbz' else: try: location_in = rarfile.RarFile(location) dir_opt = 'isdir' actual_ext = '.cbr' except rarfile.BadRarFile as e: logger.warn('[WARNING] %s: %s' % (location,e)) try: logger.info('Trying to see if this is a zip renamed as a rar: %s' % (location)) location_in = zipfile.ZipFile(location) dir_opt = 'is_dir' actual_ext = '.cbz' except Exception as e: logger.warn('[EXCEPTION] %s' % e) return except: logger.warn('[EXCEPTION]: %s' % sys.exec_info()[0]) return try: for infile in location_in.infolist(): basename = os.path.basename(infile.filename) if infile.filename == 'ComicInfo.xml': logger.fdebug('Extracting ComicInfo.xml to display.') metadata = location_in.read(infile.filename) if cover == 'found': break filename, extension = os.path.splitext(basename) tmp_infile = re.sub("[^0-9]","", filename).strip() if any([tmp_infile == '', not getattr(infile, dir_opt), 'zzz' in filename]): continue #logger.fdebug('[%s]issue_ends: %s' % (tmp_infile, tmp_infile.endswith(issue_ends))) #logger.fdebug('ext_ends: %s' % infile.filename.lower().endswith(pic_extensions)) #logger.fdebug('(%s) < (%s) == %s' % (int(tmp_infile), int(low_infile), int(tmp_infile)<int(low_infile))) #logger.fdebug('is_dir == %s' % (not getattr(infile, dir_opt))) if all([infile.filename.lower().endswith(pic_extensions), int(tmp_infile) < int(low_infile)]): low_infile = tmp_infile low_infile_name = infile.filename elif any(['00a' in infile.filename, '00b' in infile.filename, '00c' in infile.filename, '00d' in infile.filename, '00e' in infile.filename, '00fc' in infile.filename.lower()]) and infile.filename.endswith(pic_extensions) and cover == "notfound": altlist = ('00a', '00b', '00c', '00d', '00e', '00fc') for alt in altlist: if alt in infile.filename.lower(): cb_filename = infile.filename cover = "found" #logger.fdebug('[%s] cover found:%s' % (alt, infile.filename)) break elif all([tmp_infile.endswith(issue_ends), infile.filename.lower().endswith(pic_extensions), int(tmp_infile) < int(low_infile), cover == 'notfound']): cb_filenames.append(infile.filename) #logger.fdebug('filename set to: %s' % infile.filename) #low_infile_name = infile.filename #low_infile = tmp_infile if cover != "found" and any([len(cb_filenames) > 0, low_infile != 9999999999999]): logger.fdebug('Invalid naming sequence for jpgs discovered. Attempting to find the lowest sequence and will use as cover (it might not work). Currently : %s' % (low_infile_name)) cb_filename = low_infile_name cover = "found" except Exception as e: logger.error('[ERROR] Unable to properly retrieve the cover. It\'s probably best to re-tag this file : %s' % e) return logger.fdebug('cb_filename set to : %s' % cb_filename) if extension is not None: ComicImage = local_filename + extension try: insidefile = location_in.getinfo(cb_filename) img = Image.open( BytesIO( location_in.read(insidefile) )) wpercent = (600/float(img.size[0])) hsize = int((float(img.size[1])*float(wpercent))) img = img.resize((600, hsize), Image.ANTIALIAS) output = BytesIO() img.save(output, format="JPEG") try: ComicImage = str(base64.b64encode(output.getvalue()), 'utf-8') except Exception as e: ComicImage = str(base64.b64encode(output.getvalue() + "==="), 'utf-8') output.close() except Exception as e: logger.warn('[WARNING] Unable to resize existing image: %s' % e) else: ComicImage = local_filename return {'ComicImage': ComicImage, 'metadata': metadata}
def _unrar(self, path, rar_files, force): unpacked_files = [] if 'win32' == sys.platform: rarfile.UNRAR_TOOL = ek.ek(os.path.join, sickbeard.PROG_DIR, 'lib', 'rarfile', 'UnRAR.exe') if sickbeard.UNPACK and rar_files: self._log_helper(u'Packed releases detected: ' + str(rar_files)) for archive in rar_files: self._log_helper(u'Unpacking archive: ' + archive) try: rar_handle = rarfile.RarFile(ek.ek(os.path.join, path, archive)) except (StandardError, Exception): self._log_helper(u'Failed to open archive: %s' % archive, logger.ERROR) self._set_process_success(False) continue try: # Skip extraction if any file in archive has previously been extracted skip_file = False for file_in_archive in [ek.ek(os.path.basename, x.filename) for x in rar_handle.infolist() if not x.isdir()]: if self._already_postprocessed(path, file_in_archive, force): self._log_helper( u'Archive file already processed, extraction skipped: ' + file_in_archive) skip_file = True break if not skip_file: # need to test for password since rar4 doesn't raise PasswordRequired if rar_handle.needs_password(): raise rarfile.PasswordRequired rar_handle.extractall(path=path) rar_content = [ek.ek(os.path.normpath, x.filename) for x in rar_handle.infolist() if not x.isdir()] renamed = self.cleanup_names(path, rar_content) cur_unpacked = rar_content if not renamed else \ (list(set(rar_content) - set(renamed.keys())) + renamed.values()) self._log_helper(u'Unpacked content: [u\'%s\']' % '\', u\''.join(map(unicode, cur_unpacked))) unpacked_files += cur_unpacked except (rarfile.PasswordRequired, rarfile.RarWrongPassword): self._log_helper(u'Failed to unpack archive PasswordRequired: %s' % archive, logger.ERROR) self._set_process_success(False) self.fail_detected = True except (StandardError, Exception): self._log_helper(u'Failed to unpack archive: %s' % archive, logger.ERROR) self._set_process_success(False) finally: rar_handle.close() del rar_handle elif rar_files: # check for passworded rar's for archive in rar_files: try: rar_handle = rarfile.RarFile(ek.ek(os.path.join, path, archive)) except (StandardError, Exception): self._log_helper(u'Failed to open archive: %s' % archive, logger.ERROR) continue try: if rar_handle.needs_password(): self._log_helper(u'Failed to unpack archive PasswordRequired: %s' % archive, logger.ERROR) self._set_process_success(False) self.failure_detected = True rar_handle.close() del rar_handle except (StandardError, Exception): pass return unpacked_files
def extract_image(location, single=False, imquality=None, comicname=None): #location = full path to the cbr/cbz (filename included in path) #single = should be set to True so that a single file can have the coverfile # extracted and have the cover location returned to the calling function #imquality = the calling function ('notif' for notifications will initiate a resize image before saving the cover) if PIL_Found is False: return cover = "notfound" pic_extensions = ('.jpg', '.png', '.webp') issue_ends = ('1', '0') modtime = os.path.getmtime(location) low_infile = 999999999999999999 low_num = 1000 local_filename = os.path.join(mylar.CONFIG.CACHE_DIR, 'temp_notif') cb_filename = None cb_filenames = [] metadata = None if single is True: if location.endswith(".cbz"): location_in = zipfile.ZipFile(location) dir_opt = 'is_dir' actual_ext = '.cbz' else: try: location_in = rarfile.RarFile(location) dir_opt = 'isdir' actual_ext = '.cbr' except rarfile.BadRarFile as e: logger.warn('[WARNING] %s: %s' % (location, e)) try: logger.info( 'Trying to see if this is a zip renamed as a rar: %s' % (location)) location_in = zipfile.ZipFile(location) dir_opt = 'is_dir' actual_ext = '.cbz' except Exception as e: logger.warn('[EXCEPTION] %s' % e) return except Exception as e: logger.warn('[EXCEPTION]: %s' % e) return try: cntr = 0 newlencnt = 0 newlen = 0 newlist = [] for infile in location_in.infolist(): cntr += 1 basename = os.path.basename(infile.filename) if infile.filename == 'ComicInfo.xml': logger.fdebug('Extracting ComicInfo.xml to display.') metadata = location_in.read(infile.filename) if cover == 'found': break filename, extension = os.path.splitext(basename) tmp_infile = re.sub("[^0-9]", "", filename).strip() lenfile = len(infile.filename) if any([ tmp_infile == '', not getattr(infile, dir_opt), 'zzz' in filename.lower(), 'logo' in filename.lower() ]) or ((comicname is not None) and all([ comicname.lower().startswith('z'), filename.lower().startswith('z') ])): continue if all([ infile.filename.lower().endswith(pic_extensions), int(tmp_infile) < int(low_infile) ]): #logger.info('cntr: %s / infolist: %s' % (cntr, len(location_in.infolist())) ) #get the length of the filename, compare it to others. scanner ones are always different named than the other 98% of the files. if lenfile >= newlen: newlen = lenfile newlencnt += 1 newlist.append({ 'length': lenfile, 'filename': infile.filename, 'tmp_infile': tmp_infile }) #logger.info('newlen: %s / newlencnt: %s' % (newlen, newlencnt)) if newlencnt > 0 and lenfile >= newlen: #logger.info('setting it to : %s' % infile.filename) low_infile = tmp_infile low_infile_name = infile.filename elif any([ '00a' in infile.filename, '00b' in infile.filename, '00c' in infile.filename, '00d' in infile.filename, '00e' in infile.filename, '00fc' in infile.filename.lower() ]) and infile.filename.endswith( pic_extensions) and cover == "notfound": if cntr == 0: altlist = ('00a', '00b', '00c', '00d', '00e', '00fc') for alt in altlist: if alt in infile.filename.lower(): cb_filename = infile.filename cover = "found" #logger.fdebug('[%s] cover found:%s' % (alt, infile.filename)) break elif all([ tmp_infile.endswith(issue_ends), infile.filename.lower().endswith(pic_extensions), int(tmp_infile) < int(low_infile), cover == 'notfound' ]): cb_filenames.append(infile.filename) if cover != "found" and any( [len(cb_filenames) > 0, low_infile != 9999999999999]): logger.fdebug( 'Invalid naming sequence for jpgs discovered. Attempting to find the lowest sequence and will use as cover (it might not work). Currently : %s' % (low_infile_name)) # based on newlist - if issue doesn't end in 0 & 1, take the lowest numeric of the most common length of filenames within the rar if not any( [low_infile.endswith('0'), low_infile.endswith('1')]): from collections import Counter cnt = Counter([t['length'] for t in newlist]) #logger.info('cnt: %s' % (cnt,)) #cnt: Counter({15: 23, 20: 1}) tmpst = 999999999 cntkey = max(cnt.items(), key=itemgetter(1))[0] #logger.info('cntkey: %s' % cntkey) for x in newlist: if x['length'] == cntkey and int( x['tmp_infile']) < tmpst: tmpst = int(x['tmp_infile']) cb_filename = x['filename'] logger.fdebug('SETTING cb_filename set to : %s' % cb_filename) else: cb_filename = low_infile_name cover = "found" except Exception as e: logger.error( '[ERROR] Unable to properly retrieve the cover. It\'s probably best to re-tag this file : %s' % e) return logger.fdebug('cb_filename set to : %s' % cb_filename) if extension is not None: ComicImage = local_filename + extension try: insidefile = location_in.getinfo(cb_filename) img = Image.open(BytesIO(location_in.read(insidefile))) wpercent = (600 / float(img.size[0])) hsize = int((float(img.size[1]) * float(wpercent))) img = img.resize((600, hsize), Image.ANTIALIAS) output = BytesIO() img.save(output, format="JPEG") try: ComicImage = str(base64.b64encode(output.getvalue()), 'utf-8') RawImage = output.getvalue() except Exception as e: ComicImage = str( base64.b64encode(output.getvalue() + "==="), 'utf-8') RawImage = output.getvalue() + "===" output.close() except Exception as e: logger.warn('[WARNING] Unable to resize existing image: %s' % e) else: ComicImage = local_filename return { 'ComicImage': ComicImage, 'metadata': metadata, 'rawImage': RawImage }