#!/usr/bin/env python import sys import logging from mylib._misc import ExitCode from mylib.easy.logging import LOG_FMT_MESSAGE_ONLY from mylib.easy.ostk import ensure_sigint_signal from __dump__.hentai import NHentaiKit if __name__ == '__main__': ensure_sigint_signal() logging.basicConfig( level=logging.INFO, format=LOG_FMT_MESSAGE_ONLY, ) nhk = NHentaiKit() try: nhk.save_gallery_to_cbz(nhk.get_gallery(sys.argv[1])) except KeyboardInterrupt: exit(ExitCode.CTRL_C)
def rename_dialog(src: str): import PySimpleGUIQt as G ske = PySimpleGUISpecialKeyEvent() conf_file = real_join_path('~', '.config/rename_dialog.json') root = 'root' fname = 'fname' ext = 'ext' key_new_root = 'key_new_root' key_new_base = 'key_new_base' ok = 'OK' cancel = 'Cancel' pattern = 'pattern' replace = 'replace' substitute = 'substitute' save_replace = 'save_replace' save_pattern = 'save_pattern' add_root = 'add_root' rename_info_file = 'rename_info_file' bytes_count = 'bytes_count' title = 'Rename - {}'.format(src) h = None conf = read_json_file(conf_file, default={pattern: [''], replace: ['']}) tmp_pl = conf[pattern] or [''] tmp_rl = conf[replace] or [''] old_root, old_base = os.path.split(src) old_fn, old_ext = os.path.splitext(old_base) info_file_base = [ f for f in os.listdir(old_root) if f.endswith('.info') and ( f.startswith(old_fn) or old_fn.startswith(f.rstrip('.info'))) ] has_info = True if info_file_base else False @deco_factory_retry(Exception, 0, enable_default=True, default=None) def re_sub(): return re.sub(data[pattern], data[replace], data[fname] + data[ext]) def count_name_bytes(name: str): d = {} try: c, b = encode_default_locale(name) d[c] = len(b) except UnicodeEncodeError: pass u8 = 'utf-8' if u8 not in d: try: c, b = encode_default_locale(name, u8) d[c] = len(b) except UnicodeEncodeError: pass return f'Basename Length: {len(name)}, {", ".join([f"{k.upper()} {v} bytes" for k, v in d.items()])}' # sg.theme('SystemDefaultForReal') layout = [[G.T(src, key='src')], [G.HorizontalSeparator()], [ G.I(old_fn, key=fname, focus=True), G.I(old_ext, key=ext, size=(42, h)) ], [ G.I(old_root, key=root), G.B('+', key=add_root, size=(20, h)), G.FolderBrowse('...', target=root, initial_folder=old_root, size=(20, h)) ], [G.HorizontalSeparator()], [G.T('Regular Expression Pattern & Replacement')], [ G.T(size=(0, h)), G.Drop(tmp_pl, key=pattern, enable_events=True, text_color='blue'), G.CB('', default=True, key=save_pattern, enable_events=True, size=(15, h)), G.Drop(tmp_rl, key=replace, enable_events=True, text_color='blue'), G.CB('', default=True, key=save_replace, enable_events=True, size=(15, h)), G.B('Go', key=substitute, size=(25, h)) ], [G.HorizontalSeparator()], [G.I(old_root, key=key_new_root)], [G.I(old_base, key=key_new_base)], [ G.Submit(ok, size=(10, 1)), G.Stretch(), G.T(count_name_bytes(old_base), key=bytes_count), G.Stretch(), G.Cancel(cancel, size=(10, 1)) ]] if has_info: info_file_base = info_file_base[0] info_filepath = os.path.join(old_root, info_file_base) with open(info_filepath, encoding='utf8') as f: info = f.read() layout.insert(2, [ G.CB(info_file_base, default=True, key=rename_info_file, enable_events=True) ]) layout.insert(2, [G.ML(info, key='ML')]) layout.insert(4, [G.HorizontalSeparator()]) ensure_sigint_signal() window = G.Window(title, layout, return_keyboard_events=True, finalize=True, font='arial 10', element_padding=(1, 1)) window.bring_to_front() ml = window.find_element('ML', silent_on_error=True) if ml: ml.update(readonly=True) loop = True data = { fname: old_fn, ext: old_ext, pattern: tmp_pl[0], replace: tmp_rl[0], root: old_root, key_new_root: '', key_new_base: '' } while loop: dst_from_data = os.path.join(data[key_new_root], data[key_new_base]) try: tmp_fname = re_sub() or data[fname] + data[ext] dst = os.path.realpath(os.path.join(data[root], tmp_fname)) except TypeError: dst = src if dst != dst_from_data: nr, nb = os.path.split(dst) window[key_new_root].update(nr) window[key_new_base].update(nb) window[bytes_count].update(count_name_bytes(nb)) event, data = window.read() for k in (root, fname, ext, key_new_root, key_new_base): window[k].update(text_color=None) cur_p = data[pattern] cur_r = data[replace] if event == ske.esc: loop = False elif event == add_root: os.makedirs(data[root], exist_ok=True) elif event == substitute: data[fname], data[ext] = os.path.splitext( re_sub() or data[fname] + data[ext]) window[fname].update(data[fname]) window[ext].update(data[ext]) elif event == save_pattern: if data[save_pattern]: conf[pattern].insert(0, cur_p) conf[pattern] = dedup_list(conf[pattern]) else: conf[pattern] = remove_from_list(conf[pattern], [cur_p]) elif event == save_replace: if data[save_replace]: conf[replace].insert(0, cur_r) conf[replace] = dedup_list(conf[replace]) else: conf[replace] = remove_from_list(conf[replace], [cur_r]) elif event == pattern: window[save_pattern].update(value=cur_p in conf[pattern]) elif event == replace: window[save_replace].update(value=cur_r in conf[replace]) elif event == ok: try: shutil.move(src, dst) if has_info: if data[rename_info_file]: shutil.move(info_filepath, os.path.splitext(dst)[0] + '.info') loop = False except FileNotFoundError: for k in (root, fname, ext): window[k].update(text_color='red') except FileExistsError: for k in (key_new_root, key_new_base): window[k].update(text_color='red') except OSError as e: G.PopupError(str(e)) elif event in (None, cancel): loop = False else: ... else: write_json_file(conf_file, conf, indent=0) window.close()
def main(url: str = None): ensure_sigint_signal() args = parse_args() # Get verbose level from args if args.verbose: lvl = logging.DEBUG fmt = LOG_FMT else: lvl = logging.INFO fmt = LOG_FMT_MESSAGE_ONLY logging.basicConfig( stream=sys.stderr, level=lvl, format=fmt, ) # Get URL from args if url: album_url = url else: album_url = args.url if re.search(r'photosmasters\.com/thumbnails\.php\?album=', album_url): album_url = re.sub(r'(^.*?album=\d*).*$', r'\1', album_url) else: _logger.warning('NOT A PHOTOSMASTERS.COM URL!') sys.exit() db['url'] = album_url global server server, _ = url_split(album_url) # Parse album page album_soup, _ = soup(album_url) if album_soup('div', class_='cpg_message_warning'): _logger.warning('ALBUM NOT EXISTS!') sys.exit() album_title = album_soup.title.contents[0] album_name = re.sub(r'^(.*) - photosmasters\.com', r'\1', album_title) album_name = re.sub(r'^.* \((.*)\)', r'\1', album_name) album_name = album_name.strip() db['name'] = album_name _logger.info(album_title) # Get album directory to store downloaded photos album_id = get_query_dict(album_url)['album'] album_dir = os.path.join(args.dir, 'photosmasters', '{} - {}'.format(album_id, album_name)) if not os.path.exists(album_dir): os.makedirs(album_dir) _logger.info('{} -->> {}'.format(album_url, album_dir)) # Meta info_file = os.path.join(album_dir, INFO_FILE) db_file = os.path.join(album_dir, DB_FILE) restore_db(db_file) totals = album_soup('td', class_='tableh1')[0].contents[0] _, total_images, _, _, total_pages = totals.split() global stat stat = { 'dd': album_dir, # download directory 'at': album_title, # title 'ti': int(total_images), # total images 'tp': int(total_pages), # total pages 'li': 0, # last image 'lp': 0, # last page } display_stat() # Let's roll out try: for _ in range(stat['tp']): stat['lp'] += 1 page_url = '{}&page={}'.format(album_url, stat['lp']) _logger.debug('Page: {}'.format(page_url)) page_soup, _ = soup(page_url) thumbnails = page_soup('td', class_='thumbnails') for thumb in thumbnails: if not thumb.td: break stat['li'] += 1 thumb_title = thumb.td.span.contents[0] photo_url = server + '/' + thumb.a['href'].replace('#top_display_media', '&fullsize=1') _logger.debug('Photo: {}'.format(photo_url)) photo_id = get_query_dict(photo_url)['pid'] # Go! th = Thread(target=download, args=(photo_id, photo_url, thumb_title)) while len(thl) >= args.threads: for t in thl: if not t.is_alive(): thl.remove(t) sleep(0.1) display_stat() th.start() thl.append(th) sleep(0.1) except KeyboardInterrupt: _logger.info('Wait: {} threads to finish.'.format(len(thl))) sys.exit(ExitCode.CTRL_C) finally: for th in thl: th.reunion() save_db(db_file) save_info(info_file)