コード例 #1
0
ファイル: indexes.py プロジェクト: edmw/scripts
def create(users, fspath, wspath, htpasswd, **args):
    verbose = args.get("verbose", False)

    term.banner("CREATE INDEXES")

    progress = term.Progress(0, title="Searching:", bar=(verbose is False))
    galleries = search_galleries(fspath, load_access=True, load_albums=True, progress=progress.progress)
    progress.finish()

    # create default index file
    create_write(fspath, galleries, path=wspath)

    if users:
        users = collect_users(galleries)
        for user in users:
            user_path = os.path.join(fspath, "~{0}".format(safe(user.name)))
            if not os.path.exists(user_path):
                os.mkdir(user_path)
            if os.path.isdir(user_path):
                user_galleries = collect_galleries_for_user(galleries, user)
                # create user index file
                create_write(user_path, user_galleries, path=wspath, title=user.name)
                # create htaccess file for user directory
                access = Access(authname=TITLE, authuserfile=htpasswd)
                access.users.extend([user])
                access.write(user_path)
            else:
                raise IOError("CREATE INDEXES: could not write index for user '{0}'".format(str(user)))
    term.banner("DONE", type="INFO")
コード例 #2
0
ファイル: galleries_script.py プロジェクト: edmw/scripts
def galleries_list(fspath, stat=False, **args):
    term.banner("LIST OF GALLERIES")

    compact = not stat

    galleries = search_galleries(fspath)

    if compact:
        print(term.em('#    '), end='')
        print_gallery_name('Name', term.em)
        print(term.em("{1}{0}".format('Albums', SYMBOL_SEPARATOR_CLEAR)))
    for i, gallery in enumerate(galleries):
        if compact:
            print(term.p("{:<5d}".format(i)), end='')
            print_gallery_name(gallery.name)
            print(term.p("{1}{0}".format(
                ', '.join(str(x) for x in gallery.albums),
                SYMBOL_SEPARATOR
            )))
        else:
            print_gallery_name(gallery.name, term.em, end='\n')
            print(term.p("{0:>20}: {1}".format('Albums', ', '.join(str(x) for x in gallery.albums))))
            nop, notp, sod = gallery_stat(gallery.path)
            print(term.p("{0:>20}: {1!s}".format("Number of pictures", nop)))
            print(term.p("{0:>20}: {1}".format("Size on disk", humanfriendly.format_size(sod))))
            print()
コード例 #3
0
ファイル: galleries_script.py プロジェクト: edmw/scripts
    def install(self, gallery):
        term.banner("INSTALL GALLERY")

        self.destination_path = os.path.join(self.fspath, gallery.name)

        self.__check_destination(gallery.name)
        self.__install(gallery)
        self.__restore_access()
コード例 #4
0
ファイル: galleries_script.py プロジェクト: edmw/scripts
 def __check_destination(self, gallery_name):
     assert self.destination_path
     if os.path.exists(self.destination_path):
         if os.path.isdir(self.destination_path):
             term.banner("GALLERY '{0}' ALREADY EXISTS".format(gallery_name), type='WARN')
             if not self.interactive or not term.ask("OVERWRITE EXISTING GALLERY?"):
                 raise GSAbortError("OVERWRITE EXISTING GALLERY")
             self.__backup_destination(gallery_name)
         else:
             raise GSError(
                 "COULDN'T OVERWRITE EXISTING GALLERY\nAT '{0}'".format(self.destination_path)
             )
     return True
コード例 #5
0
ファイル: indexes.py プロジェクト: edmw/scripts
def install(wspath, fspath, htpasswd, **args):
    """ Install indexes: Create htaccess file with rewrite rules to
        serve user-specific indexes.

        Indexes must be created by executing 'index create' command.

        NOTE: htaccess file will be overwritten!
    """
    term.banner("INSTALL INDEXES")

    galleries = search_galleries(fspath, load_access=True)

    users = collect_users(galleries)
    access = Access(authname=TITLE, authuserfile=htpasswd)
    access.users.extend(users)
    access.conf.append(("RewriteEngine", "On"))
    access.conf.append(("RewriteBase", wspath))
    access.conf.append(("RewriteCond", "%{REMOTE_user} ^.+$"))
    access.conf.append(("RewriteRule", "^$ {0}~%{{REMOTE_user}} [R,L]".format(wspath)))
    access.write(fspath)
    term.banner("DONE", type="INFO")
コード例 #6
0
ファイル: albums.py プロジェクト: edmw/scripts
def setcover(gallery_name, album_name, image_name, fspath, **args):
    gallery = get_gallery(fspath, gallery_name)
    album = get_album_in_gallery(gallery, album_name)

    term.banner("SET ALBUM COVER")

    image_filename = os.path.join(gallery.path, 't', "{0}.jpg".format(image_name))
    if not os.path.exists(image_filename) or not os.path.isfile(image_filename):
        term.banner("IMAGE '{0}' NOT FOUND IN GALLERY '{1}'\nAT '{2}'".format(
                image_name, gallery.name, image_filename),
            type='ERROR')
        return

    shutil.copyfile(image_filename, os.path.join(gallery.path, "{0}.jpg".format(album.label)))

    term.banner("DONE", type='INFO')
コード例 #7
0
ファイル: images.py プロジェクト: edmw/scripts
def optimize(gallery_name, fspath, **args):
    gallery = get_gallery(fspath, gallery_name)

    term.banner("OPTIMIZE IMAGES (JPEG)")

    dry = args.get('dry_run')

    try:
        subprocess.call(['djpeg', '-version'], stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
        subprocess.call(['cjpeg', '-version'], stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
    except FileNotFoundError as x:
        term.banner("MOZJPEG MUST BE INSTALLED", type='INFO')
        raise GSError("OPTIMIZE: {0}".format(x))

    if dry:
        term.banner("DRY RUN", type='INFO')

    for directory in ['p', 't']:
        path = os.path.join(gallery.path, directory)
        for root, directories, files in os.walk(path):
            for filename in sorted(fnmatch.filter(files, '*.jpg')):
                path = os.path.join(root, filename)
                size = os.path.getsize(path)

                if size:
                    djpeg = subprocess.Popen(['djpeg', path],
                        stdout=subprocess.PIPE)
                    cjpeg = subprocess.Popen(['cjpeg',
                            '-quality', '92',
                            '-opt',
                            '-sample', '1x1',
                            '-notrellis'
                        ],
                        stdin=djpeg.stdout, stdout=subprocess.PIPE)

                    new_size = 0
                    new_path = None

                    if dry:
                        with cjpeg:
                            for chunk in iter(lambda: cjpeg.stdout.read(4096), b''):
                                new_size = new_size + len(chunk)
                    else:
                        new_path = path + ".new"
                        with cjpeg, open(new_path, 'wb') as f:
                            for chunk in iter(lambda: cjpeg.stdout.read(4096), b''):
                                f.write(chunk)
                                new_size = new_size + len(chunk)

                    ratio = 100 / size * new_size
                    print(term.p("{0:32} {1:6.2f}% {2:8} {3:8}".format(filename, ratio, size, new_size)), end='  ')

                    if new_path:
                        if ratio < 95:
                            print("... gained {0:.2f}%".format(100 - ratio), end='  ')
                            shutil.move(new_path, path)
                        else:
                            print("... skipping", end='  ')
                            os.remove(new_path)

                    print()

    term.banner("DONE", type='INFO')
コード例 #8
0
ファイル: galleries_script.py プロジェクト: edmw/scripts
 def __exit__(self, exception, value, traceback):
     if exception is None:
         term.banner("DONE", type='INFO')
         self.__backup_destination_clean()
     else:
         self.__backup_destination_restore()
コード例 #9
0
ファイル: galleries_script.py プロジェクト: edmw/scripts
def main(args=None):
    config = configparser.ConfigParser()
    config.read('galleries.ini')

    config_htpasswd = config['Access'].get('htpasswd') if 'Access' in config else None

    parser = argparse.ArgumentParser(
        prog=os.getenv('SCRIPT'),
        description=DESCRIPTION,
        epilog=EPILOG,
        formatter_class=argparse.RawDescriptionHelpFormatter
    )
    parser.add_argument('--fspath', type=path_argument, default='/var/www/web/',
        help="Path to web galleries on filesystem. Defaults to '/var/www/web/'.")
    parser.add_argument('--wspath', type=path_argument, default='/',
        help="Path to web galleries on webserver. Defaults to '/'.")
    if 'Defaults' in config:
        parser.set_defaults(**config['Defaults'])
    subparsers = parser.add_subparsers(title='commands', dest='command')
    subparsers.required = True

    parser_interactive = argparse.ArgumentParser(add_help=False)
    parser_interactive.add_argument('-i', '--interactive', action='store_true', default=False,
        help="enable interactive mode and ask for input")
    parser_verbose = argparse.ArgumentParser(add_help=False)
    parser_verbose.add_argument('-v', '--verbose', action='store_true', default=False,
        help="enable verbose output")
    parser_dryrun = argparse.ArgumentParser(add_help=False)
    parser_dryrun.add_argument('-n', '--dry-run', action='store_true', default=False,
        help="simulate actions only and print expected results")

    # list command
    parser_list = subparsers.add_parser('list',
        help="List all web galleries.")
    parser_list.set_defaults(function=galleries_list)
    parser_list.add_argument('--stat', action='store_true', default=False,
        help="Print statistics for web galleries.")

    # install command
    parser_install = subparsers.add_parser('install', parents=[parser_interactive],
        help="Install web gallery.")
    parser_install.set_defaults(function=galleries_install)
    parser_install.add_argument('--htpasswd', default=config_htpasswd,
        help="Path to htpasswd file for access control.")
    parser_install.add_argument('--set-albums-cover', metavar='image_name',
        help="Set cover for albums of web gallery.")
    parser_install.add_argument('gallery_path',
        help="Path to web gallery to install.")

    # access command
    parser_access = subparsers.add_parser('access',
        help="Manage access to web gallery.")
    subparsers_access = parser_access.add_subparsers(
        title='access commands', dest='access_command')
    subparsers_access.required = True
    # access show command
    parser_access_show = subparsers_access.add_parser('show',
        help="Show access to web galleries.")
    parser_access_show.set_defaults(function=access.show)
    # access init command
    parser_access_init = subparsers_access.add_parser('init',
        help="Initialize access to web gallery.")
    parser_access_init.set_defaults(function=access.manage)
    parser_access_init.add_argument('--htpasswd',
        required=(config_htpasswd is None), default=config_htpasswd,
        help="Path to htpasswd file for access control.")
    parser_access_init.add_argument('gallery_name',
        help="Name of web gallery to manage.")
    # access list command
    parser_access_list = subparsers_access.add_parser('list',
        help="List access to web gallery.")
    parser_access_list.set_defaults(function=access.manage)
    parser_access_list.add_argument('gallery_name',
        help="Name of web gallery to manage.")
    # access adduser command
    parser_access_adduser = subparsers_access.add_parser('adduser',
        help="Add access for user to web gallery.")
    parser_access_adduser.set_defaults(function=access_manage)
    parser_access_adduser.add_argument('username', nargs='+',
        help="Name of user to grant access to web gallery.")
    parser_access_adduser.add_argument('galleries_name_pattern',
        help="Pattern for names of web galleries to manage.")
    # access deluser command
    parser_access_removeuser = subparsers_access.add_parser('removeuser',
        help="Remove access for user to web gallery.")
    parser_access_removeuser.set_defaults(function=access_manage)
    parser_access_removeuser.add_argument('username', nargs='+',
        help="Name of user to revoke access to web gallery.")
    parser_access_removeuser.add_argument('galleries_name_pattern',
        help="Pattern for names of web galleries to manage.")

    # indexes command
    parser_indexes = subparsers.add_parser('indexes',
        help="Manage indexes of web galleries.")
    subparsers_indexes = parser_indexes.add_subparsers(
        title='indexes commands', dest='indexes command')
    subparsers_indexes.required = True
    # indexes create command
    parser_indexes_create = subparsers_indexes.add_parser('create', parents=[parser_verbose],
        help="Create indexes for web galleries.")
    parser_indexes_create.add_argument('--users', action='store_true', default=False,
        help="Create indexes for users.")
    parser_indexes_create.add_argument('--htpasswd', default=config_htpasswd,
        help="Path to htpasswd file for access control.")
    parser_indexes_create.set_defaults(function=indexes.create)
    # indexes install command
    config_htpasswd = config['Access'].get('htpasswd') if 'Access' in config else None
    parser_indexes_install = subparsers_indexes.add_parser('install',
        help="Install indexes for web galleries.")
    parser_indexes_install.add_argument('--htpasswd',
        required=(config_htpasswd is None), default=config_htpasswd,
        help="Path to htpasswd file for access control.")
    parser_indexes_install.set_defaults(function=indexes.install)

    # albums command
    parser_albums = subparsers.add_parser('albums',
        help="Manage albums of web gallery.")
    subparsers_albums = parser_albums.add_subparsers(
        title='albums commands', dest='albums command')
    subparsers_albums.required = True
    # albums setcover command
    parser_albums_setcover = subparsers_albums.add_parser('setcover',
        help="Set cover for album of web gallery.")
    parser_albums_setcover.set_defaults(function=albums.setcover)
    parser_albums_setcover.add_argument('image_name',
        help="Name of image to be used as cover (must exist inside gallery).")
    parser_albums_setcover.add_argument('album_name',
        help="Name of album inside web gallery.")
    parser_albums_setcover.add_argument('gallery_name',
        help="Name of web gallery to manage.")

    # images command
    parser_images = subparsers.add_parser('images',
        help="Manage images of web gallery.")
    subparsers_images = parser_images.add_subparsers(
        title='images commands', dest='images_command')
    subparsers_images.required = True
    # images optimize command
    parser_images_optimize = subparsers_images.add_parser('optimize', parents=[parser_dryrun],
        help="Optimize images of web gallery.")
    parser_images_optimize.set_defaults(function=images.optimize)
    parser_images_optimize.add_argument('gallery_name',
        help="Name of web gallery to manage.")

    try:
        arguments = parser.parse_args() if args == None else parser.parse_args(args)
        if 'verbose' in arguments and arguments.verbose == True:
            logging_level = logging.INFO
        else:
            logging_level = logging.WARNING
        logging.basicConfig(level=logging_level,
            format='[%(levelname)s][%(funcName)s] %(message)s')
        arguments.function(**vars(arguments))
    except GSError as x:
        term.banner(str(x), type='ERROR')
    except FileNotFoundError as x:
        term.banner("NOT FOUND '{0}'".format(x), type='ERROR')