示例#1
0
#!/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)
示例#2
0
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()
示例#3
0
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)