Beispiel #1
0
    def _match_tags(parent_model,
                    child_model,
                    term,
                    options,
                    capture=db.model_name(db.Taggable)):
        get_model = database_cmd.GetModelClass()
        parent_model = get_model.run(parent_model)
        child_model = get_model.run(child_model)

        match_string = PartialModelFilter._match_string_column
        term = ParseTerm().run(term)
        ids = set()

        col_on_parent = db.relationship_column(parent_model, child_model)
        col_on_child = db.relationship_column(child_model, db.NamespaceTags)
        col_tag = db.relationship_column(db.NamespaceTags, db.Tag)
        s = constants.db_session()
        q = s.query(parent_model.id)
        if term.namespace:
            col_ns = db.relationship_column(db.NamespaceTags, db.Namespace)
            items = q.join(col_on_parent).join(col_on_child).join(col_ns).join(
                col_tag).filter(
                    db.and_op(
                        match_string(db.Namespace.name,
                                     term.namespace,
                                     options,
                                     whole=True),
                        match_string(db.Tag.name, term.tag, options))).all()
        else:
            items = q.join(col_on_parent).join(col_on_child).join(
                col_tag).filter(match_string(db.Tag.name, term.tag,
                                             options)).all()

        ids.update(x[0] for x in items)
        return ids
Beispiel #2
0
    def _generate_collection(model,
                             item_id,
                             size,
                             capture=db.model_name(db.Collection)):
        im_path = ""
        model = GetModelClass().run(model)

        page = GetSession().run().query(db.Page.path).join(
            db.Collection.galleries).join(db.Gallery.pages).filter(
                db.and_op(db.Collection.id == item_id,
                          db.Page.number == 1)).first()

        # gallery sorted by insertion:
        # page = GetSession().run().query(
        #    db.Page.path, db.gallery_collections.c.timestamp.label("timestamp")).join(db.Collection.galleries).join(db.Gallery.pages).filter(
        #    db.and_op(
        #        db.Collection.id == item_id,
        #        db.Page.number == 1)).sort_by("timestamp").first()
        if page:
            im_path = page[0]

        if im_path:
            im_props = io_cmd.ImageProperties(size, 0, constants.dir_thumbs)
            im_path = io_cmd.ImageItem(im_path, im_props).main()
        return im_path
Beispiel #3
0
 def _generate(model, item_id, size, capture=db.model_name(db.Gallery)):
     im_path = ""
     page = GetSession().run().query(db.Page.path).filter(
         db.and_op(db.Page.gallery_id == item_id,
                   db.Page.number == 1)).one_or_none()
     if page:
         im_props = io_cmd.ImageProperties(size, 0, constants.dir_thumbs)
         im_path = io_cmd.ImageItem(None, page[0], im_props).main()
     return im_path
Beispiel #4
0
    def main(self, model: db.Base, item_id: int,
             image_size: enums.ImageSize) -> db.Profile:
        self.model = model

        if image_size == enums.ImageSize.Original:
            image_size = utils.ImageSize(0, 0)
        else:
            image_size = utils.ImageSize(
                *constants.image_sizes[image_size.name.lower()])

        with self.models.call() as plg:
            for p in plg.all(default=True):
                self._supported_models.update(p)

        if self.model not in self._supported_models:
            raise exceptions.CommandError(
                utils.this_command(self),
                "Model '{}' is not supported".format(model))

        img_hash = io_cmd.ImageItem.gen_hash(model, image_size, item_id)

        generate = True
        sess = constants.db_session()

        profile_size = str(tuple(image_size))

        self.cover = sess.query(db.Profile).filter(
            db.and_op(db.Profile.data == img_hash,
                      db.Profile.size == profile_size)).first()

        old_img_hash = None
        if self.cover:
            if io_cmd.CoreFS(self.cover.path).exists:
                generate = False
            else:
                old_img_hash = self.cover.data

        self.next_progress()
        if not generate:
            model_name = db.model_name(model)
            with self.invalidate.call_capture(model_name, model_name, item_id,
                                              image_size) as plg:
                if plg.first_or_default():
                    generate = True

        self.next_progress()
        if generate:
            constants.task_command.thumbnail_cleaner.wake_up()
            self.cover = self.run_native(self._generate_and_add, img_hash,
                                         old_img_hash, generate, model,
                                         item_id, image_size,
                                         profile_size).get()
        self.cover_event.emit(self.cover)
        return self.cover
Beispiel #5
0
    def _update_db(self, stale_cover, item_id, model, old_hash):
        log.d("Updating profile for database item", model)
        s = constants.db_session()
        cover = s.query(db.Profile).filter(
            db.and_op(db.Profile.data == old_hash,
                      db.Profile.size == stale_cover.size)).all()

        if len(cover) > 1:
            cover, *cover_ex = cover
            for x in cover_ex:
                s.delete(x)
        elif cover:
            cover = cover[0]

        new = False

        if cover:
            # sometimes an identical img has already been generated and exists so we shouldnt do anything
            fs = io_cmd.CoreFS(cover.path)
            if (cover.path != stale_cover.path) and fs.exists:
                fs.delete()
        else:
            cover = db.Profile()
            new = True

        cover.data = stale_cover.data
        cover.path = stale_cover.path
        cover.size = stale_cover.size

        if new or not s.query(db.Profile).join(
                db.relationship_column(model, db.Profile)).filter(
                    db.and_op(db.Profile.id == cover.id, model.id
                              == item_id)).scalar():
            log.d("Adding new profile to database item", model,
                  "()".format(item_id))
            i = s.query(model).get(item_id)
            i.profiles.append(cover)

        s.commit()
        self.next_progress()
Beispiel #6
0
    def get_context(self, user=None, password=None):
        "Creates or retrieves existing context object for this client"
        s = constants.db_session()
        user_obj = None
        if user or password:
            log.d("Client provided credentials, authenticating...")
            user_obj = s.query(
                db.User).filter(db.User.name == user).one_or_none()
            if user_obj:
                if not user_obj.password == password:
                    raise exceptions.AuthError(utils.this_function(),
                                               "Wrong credentials")
            else:
                raise exceptions.AuthError(utils.this_function(),
                                           "Wrong credentials")
        else:
            log.d("Client did not provide credentials")

            if not constants.disable_default_user:
                log.d("Authenticating with default user")
                user_obj = s.query(db.User).filter(
                    db.User.role == db.User.Role.default).one()
            else:
                if not constants.allow_guests:
                    log.d("Guests are disallowed on this server")
                    raise exceptions.AuthRequiredError(utils.this_function())
                log.d("Authencticating as guest")
                user_obj = s.query(db.User).filter(
                    db.and_op(
                        db.User.address == self._ip,
                        db.User.role == db.User.Role.guest)).one_or_none()
                if not user_obj:
                    user_obj = db.User(role=db.User.Role.guest)
                    s.add(user_obj)

        self.context = user_obj

        self.context.address = self._ip
        if not self.context.context_id:
            self.context.context_id = uuid.uuid4().hex

        self.context.config = None
        log.d("Client accepted")
        self._accepted = True

        s.commit()
Beispiel #7
0
def get_page(page_id: int = None,
             gallery_id: int = None,
             number: int = None,
             prev: bool = False):
    """
    Get next/prev page by either gallery or page id

    Args:
        page_id: id of page
        gallery_id: id of gallery
        number: retrieve specific page number
        prev: by default next page is retrieved, to retrieve prev page set this to true

    Returns:
        Page object
    """
    if not (gallery_id or page_id):
        raise exceptions.APIError(
            utils.this_function(),
            "Either a gallery id or page id is required")

    if number is None:
        number = 0

    item = None

    if page_id:
        p = database_cmd.GetModelItems().run(db.Page, {page_id})[0]
        if number and p and number == p.number:
            item = p
        elif p:
            number = number or p.number
            gallery_id = p.gallery_id

    if not item:
        f = db.Page.number < number if prev else db.Page.number == number
        f = db.and_op(f, db.Page.gallery_id == gallery_id)
        item = database_cmd.GetModelItems().run(
            db.Page,
            order_by=db.Page.number.desc() if prev else db.Page.number,
            filter=f,
            limit=1)
        if item:
            item = item[0]

    return message.Page(item) if item else None
Beispiel #8
0
    def _generate(model,
                  item_id,
                  size,
                  capture=[db.model_name(x) for x in (db.Page, db.Gallery)]):
        im_path = ""
        model = GetModelClass().run(model)

        if model == db.Gallery:
            page = GetSession().run().query(db.Page.path).filter(
                db.and_op(db.Page.gallery_id == item_id,
                          db.Page.number == 1)).one_or_none()
        else:
            page = GetSession().run().query(
                db.Page.path).filter(db.Page.id == item_id).one_or_none()

        if page:
            im_path = page[0]

        if im_path:
            im_props = io_cmd.ImageProperties(size, 0, constants.dir_thumbs)
            im_path = io_cmd.ImageItem(None, im_path, im_props).main()
        return im_path
Beispiel #9
0
def _view_helper(item_type: enums.ItemType=enums.ItemType.Gallery,
                 search_query: str = "",
                 filter_id: int = None,
                 view_filter: enums.ViewType = enums.ViewType.Library,
                 item_id: int = None,
                 related_type: enums.ItemType = None,
                 search_options: dict = {},
                 ):
    if view_filter is not None:
        view_filter = enums.ViewType.get(view_filter)
    if related_type is not None:
        related_type = enums.ItemType.get(related_type)
    item_type = enums.ItemType.get(item_type)

    if search_options:
        search_option_names = [x.name for x in search_cmd._get_search_options()]
        for n in search_options:
            if n not in search_option_names:
                raise exceptions.APIError(utils.this_function(), "Invalid search option name '{}'".format(n))

    filter_op = []
    join_exp = []
    parent_model = None

    db_msg, db_model = item_type._msg_and_model(
        (enums.ItemType.Gallery, enums.ItemType.Collection, enums.ItemType.Grouping))

    if related_type:
        parent_model = db_model
        db_msg, db_model = related_type._msg_and_model(
            (enums.ItemType.Gallery, enums.ItemType.Page))

        col = db.relationship_column(parent_model, db_model)
        if not col:
            raise exceptions.APIError(
                utils.this_function(),
                "{} has no relationship with {}".format(
                    related_type,
                    item_type))

        if item_id is None:
            raise exceptions.APIError(utils.this_function(), "Missing id of parent item")

    if filter_id:
        if db_model != db.Gallery:
            g_col = db.relationship_column(db_model, db.Gallery)
            if not g_col:
                raise exceptions.APIError(
                    utils.this_function(),
                    "Cannot use {} because {} has no relationship with {}".format(
                        enums.ItemType.GalleryFilter,
                        related_type if related_type else item_type,
                        enums.ItemType.Gallery))
            join_exp.append(g_col)
        join_exp.append(db.relationship_column(db.Gallery, db.GalleryFilter))
        filter_op.append(db.GalleryFilter.id == filter_id)

    model_ids = None
    if not db_model == db.Page:
        model_ids = search_cmd.ModelFilter().run(db_model, search_query, search_options)

    metatag_name = None
    if view_filter == enums.ViewType.Favorite:
        metatag_name = db.MetaTag.names.favorite
    elif view_filter == enums.ViewType.Inbox:
        metatag_name = db.MetaTag.names.inbox
    elif view_filter == enums.ViewType.Trash:
        metatag_name = db.MetaTag.names.trash

    if metatag_name:
        if hasattr(db_model, "metatags"):
            filter_op.append(db.MetaTag.name == metatag_name)
            join_exp.append(db_model.metatags)
    elif view_filter == enums.ViewType.Library:
        if hasattr(db_model, "metatags"):
            filter_op.append(~db_model.metatags.any(db.MetaTag.name == db.MetaTag.names.inbox))
            filter_op.append(~db_model.metatags.any(db.MetaTag.name == db.MetaTag.names.trash))
    elif view_filter == enums.ViewType.All:
        if hasattr(db_model, "metatags"):
            filter_op.append(~db_model.metatags.any(db.MetaTag.name == db.MetaTag.names.trash))

    if related_type:
        filter_op.append(parent_model.id == item_id)
        join_exp.append(col)

    if len(filter_op) > 1:
        filter_op = db.and_op(*filter_op)
    elif filter_op:
        filter_op = filter_op[0]
    else:
        filter_op = None

    return view_filter, item_type, db_msg, db_model, model_ids, filter_op, join_exp, metatag_name