예제 #1
0
    def main(self,
             model: db.Base,
             term: str,
             match_options: dict = {}) -> typing.Set[int]:

        self.model = model
        model_name = db.model_name(self.model)
        self.term = term
        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))

        options = get_search_options(match_options)
        log.d("Match options", options)

        related_models = db.related_classes(model)

        sess = constants.db_session()

        model_count = sess.query(model).count()

        with self.match_model.call_capture(model_name, model_name, model_name,
                                           self.term, options) as plg:
            for i in plg.all_or_default():
                self.matched_ids.update(i)
                if len(self.matched_ids) == model_count:
                    break

        has_all = False
        for m in related_models:
            if m in self._supported_models:
                with self.match_model.call_capture(db.model_name(m),
                                                   model_name,
                                                   db.model_name(m), self.term,
                                                   options) as plg:
                    for i in plg.all_or_default():
                        self.matched_ids.update(i)
                        if len(self.matched_ids) == model_count:
                            has_all = True
                            break
            if has_all:
                break

        self.matched.emit(self.matched_ids)

        return self.matched_ids
예제 #2
0
 def _namespacetags_orderby(model_name,
                            capture=db.model_name(db.NamespaceTags)):
     return {
         ItemSort.NamespaceTagNamespace.value:
         (db.Namespace.name, db.Tag.name),
         ItemSort.NamespaceTagTag.value: (db.Tag.name, db.Namespace.name),
     }
예제 #3
0
    def main(self,
             model: db.Base,
             limit: int = 999,
             filter: str = "",
             order_by: str = "",
             offset: int = 0,
             join: str = "") -> tuple:

        s = constants.db_session()

        q = s.query(model)

        if join:
            if not isinstance(join, (list, tuple)):
                join = [join]

            for j in join:
                if isinstance(j, str):
                    q = q.join(db.sa_text(j))
                else:
                    q = q.join(j)

        if filter:
            if isinstance(filter, str):
                q = q.filter(db.sa_text(filter))
            else:
                q = q.filter(filter)

        if order_by:
            q = q.order_by(db.sa_text(order_by))

        self.fetched_items = tuple(self._query(q, limit, offset))

        self.fetched.emit(db.model_name(model), self.fetched_items)
        return self.fetched_items
예제 #4
0
파일: search_cmd.py 프로젝트: naafx8/server
    def _match_gallery(parent_model,
                       child_model,
                       term,
                       options,
                       capture=db.model_name(db.Gallery)):
        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
        match_int = PartialModelFilter._match_integer_column
        term = ParseTerm().run(term)
        ids = set()

        s = constants.db_session()

        if term.namespace:
            lower_ns = term.namespace.lower()
            if lower_ns == 'path':
                ids.update(x[0] for x in s.query(parent_model.id).filter(
                    match_string(db.Gallery.path, term, options)).all())
            elif lower_ns in ("rating", "stars"):
                ids.update(x[0] for x in s.query(parent_model.id).filter(
                    match_int(db.Gallery.rating, term, options)).all())

        return ids
예제 #5
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
예제 #6
0
    def _generate_and_add(self, img_hash, old_img_hash, generate, model,
                          item_id, image_size, profile_size):

        model_name = db.model_name(model)

        cover = db.Profile()
        if generate:
            log.d("Generating new profile", image_size, "for database item",
                  model)
            with self.generate.call_capture(model_name, model_name, item_id,
                                            image_size) as plg:
                p = plg.first_or_default()
                if not p:
                    p = ""
                cover.path = p

            cover.data = img_hash
            cover.size = profile_size
        self.next_progress()
        if cover.path and generate:
            log.d("Updating database")
            self._update_db(cover, item_id, model, old_img_hash)
        elif not cover.path:
            cover = None
        return cover
예제 #7
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
예제 #8
0
 def _aliasname_joins(
     model_name,
     capture=tuple(db.model_name(x) for x in (db.Artist, db.Parody))):
     return {
         ItemSort.ArtistName.value: (db.Artist.names, ),
         ItemSort.ParodyName.value: (db.Parody.names, ),
     }
예제 #9
0
 def _aliasname_names(
     model_name,
     capture=tuple(db.model_name(x) for x in (db.Artist, db.Parody))):
     return {
         ItemSort.ArtistName.value: "Name",
         ItemSort.ParodyName.value: "Name",
     }
예제 #10
0
    def _generate_and_add(self, img_hash, generate, cover_path, model, item_id,
                          image_size):

        sess = constants.db_session()

        model_name = db.model_name(model)

        new = False
        if cover_path:
            self.cover = sess.query(
                db.Profile).filter(db.Profile.data == img_hash).one_or_none()
        else:
            self.cover = db.Profile()
            new = True

        if generate:
            with self.generate.call_capture(model_name, model_name, item_id,
                                            image_size) as plg:
                self.cover.path = plg.first()

            self.cover.data = img_hash
            self.cover.size = str(tuple(image_size))

        if self.cover.path and generate:
            if new:
                s = constants.db_session()
                i = s.query(model).get(item_id)
                i.profiles.append(self.cover)
            sess.commit()
        elif not self.cover.path:
            self.cover = None
        return self.cover
예제 #11
0
    def _match_parody(parent_model, child_model, term, options,
                      capture=db.model_name(db.Parody)):
        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()

        if term.namespace.lower() == 'parody' or not term.namespace:
            col_on_parent = db.relationship_column(parent_model, child_model)

            s = constants.db_session()
            q = s.query(parent_model.id)
            if col_on_parent:
                q = q.join(col_on_parent)
            ids.update(
                x[0] for x in q.join(
                    child_model.names).filter(
                    match_string(
                        db.ParodyName.name,
                        term.tag,
                        options)).all())
        return ids
예제 #12
0
def get_items(
    item_type: enums.ItemType = enums.ItemType.Gallery,
    limit: int = 100,
    offset: int = None,
):
    """
    Get a list of items

    Args:
        item_type: type of item to get
        limit: limit the amount of items returned
        offset: offset the results by n items

    Returns:
        .. code-block:: guess

            [
                item message object,
                ...
            ]
    """

    item_type = enums.ItemType.get(item_type)

    db_msg, db_model = item_type._msg_and_model()

    items = database_cmd.GetModelItems().run(db_model,
                                             limit=limit,
                                             offset=offset)

    item_list = message.List(db.model_name(db_model), db_msg)
    [item_list.append(db_msg(i)) for i in items]
    return item_list
예제 #13
0
    def _match_namemixin(parent_model,
                         child_model,
                         term,
                         options,
                         capture=[
                             db.model_name(x) for x in _models()
                             if issubclass(x, (db.NameMixin, db.Url))
                         ]):
        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()

        if term.namespace.lower() == child_model.__name__.lower(
        ) or not term.namespace:
            col_on_parent = db.relationship_column(parent_model, child_model)
            s = constants.db_session()
            q = s.query(parent_model.id)
            if col_on_parent:
                q = q.join(col_on_parent)
            ids.update(x[0] for x in q.filter(
                match_string(child_model.name, term.tag, options)).all())
        return ids
예제 #14
0
    def main(self, model: db.Base, search_filter: str, match_options: dict = {}) -> typing.Set[int]:
        assert issubclass(model, db.Base)

        self._model = model
        model_name = db.model_name(self._model)

        if search_filter:

            self.parsesearchfilter = ParseSearch()

            pieces = self.parsesearchfilter.run(search_filter)

            options = get_search_options(match_options)

            include = set()
            exclude = set()

            with self.separate.call(pieces) as plg:

                for p in plg.all(True):
                    if len(p) == 2:
                        include.update(p[0])
                        exclude.update(p[1])

            if options.get("all"):
                for n, p in enumerate(include):
                    with self.include.call(model_name, {p}, options) as plg:
                        for i in plg.all_or_default():
                            if n != 0:
                                self.included_ids.intersection_update(i)
                            else:
                                self.included_ids.update(i)
            else:
                with self.include.call(model_name, include, options) as plg:

                    for n, i in enumerate(plg.all_or_default()):
                        self.included_ids.update(i)

            self.included.emit(model_name, self.included_ids)

            with self.exclude.call(model_name, exclude, options) as plg:

                for i in plg.all_or_default():
                    self.excluded_ids.update(i)

            self.excluded.emit(self._model.__name__, self.excluded_ids)

            self.matched_ids = self.included_ids
            self.matched_ids.difference_update(self.excluded_ids)

        else:

            with self.empty.call(model_name) as plg:
                for i in plg.all_or_default():
                    self.matched_ids.update(i)

        self.matched.emit(self._model.__name__, self.matched_ids)

        return self.matched_ids
예제 #15
0
 def _collection_names(model_name, capture=db.model_name(db.Collection)):
     return {
         ItemSort.CollectionRandom.value: "Random",
         ItemSort.CollectionName.value: "Name",
         ItemSort.CollectionDate.value: "Date Added",
         ItemSort.CollectionPublished.value: "Date Published",
         ItemSort.CollectionGalleryCount.value: "Gallery Count",
     }
예제 #16
0
 def _namespacetags_joins(model_name,
                          capture=db.model_name(db.NamespaceTags)):
     return {
         ItemSort.NamespaceTagNamespace.value:
         (db.NamespaceTags.namespace, db.NamespaceTags.tag),
         ItemSort.NamespaceTagTag.value:
         (db.NamespaceTags.tag, db.NamespaceTags.namespace),
     }
예제 #17
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
예제 #18
0
 def _collection_orderby(model_name, capture=db.model_name(db.Collection)):
     return {
         ItemSort.CollectionRandom.value: (func.random(), ),
         ItemSort.CollectionName.value: (db.Collection.name, ),
         ItemSort.CollectionDate.value: (db.Collection.timestamp, ),
         ItemSort.CollectionPublished.value: (db.Collection.pub_date, ),
         ItemSort.CollectionGalleryCount.value:
         (db.func.count(db.Gallery.id), ),
     }
예제 #19
0
 def _gallery_joins(model_name, capture=db.model_name(db.Gallery)):
     return {
         ItemSort.GalleryTitle.value: (db.Gallery.titles, ),
         ItemSort.GalleryArtist.value: (
             db.Gallery.artists,
             db.Artist.names,
         ),
         ItemSort.GalleryPageCount.value: (db.Gallery.pages, ),
     }
예제 #20
0
파일: search_cmd.py 프로젝트: naafx8/server
    def main(self, model: db.Base, search_filter: str) -> set:
        assert issubclass(model, db.Base)

        self._model = model
        model_name = db.model_name(self._model)

        if search_filter:

            self.parsesearchfilter = ParseSearch()

            pieces = self.parsesearchfilter.run(search_filter)

            options = get_search_options()

            include = set()
            exclude = set()

            with self.separate.call(pieces) as plg:

                for p in plg.all():
                    if len(p) == 2:
                        include.update(p[0])
                        exclude.update(p[1])

            with self.include.call(model_name, include) as plg:

                for i in plg.all():
                    if options.get("all"):
                        if self.included_ids:
                            self.included_ids.intersection_update(i)
                        else:
                            self.included_ids.update(i)
                    else:
                        self.included_ids.update(i)

            self.included.emit(model_name, self.included_ids)

            with self.exclude.call(model_name, exclude) as plg:

                for i in plg.all():
                    self.excluded_ids.update(i)

            self.excluded.emit(self._model.__name__, self.excluded_ids)

            self.matched_ids = self.included_ids
            self.matched_ids.difference_update(self.excluded_ids)

        else:

            with self.empty.call(model_name) as plg:
                for i in plg.all():
                    self.matched_ids.update(i)

        self.matched.emit(self._model.__name__, self.matched_ids)

        return self.matched_ids
예제 #21
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
예제 #22
0
def get_related_items(
    item_type: enums.ItemType = enums.ItemType.Gallery,
    item_id: int = 0,
    related_type: enums.ItemType = enums.ItemType.Page,
    limit: int = 100,
    offset: int = None,
):
    """
    Get item related to given item

    Args:
        item_type: parent item
        item_id: id of parent item
        related_type: child item
        limit: limit the amount of items returned
        offset: offset the results by n items

    Returns:
        .. code-block:: guess

            [
                related item message object,
                ...
            ]
    """
    if not item_id:
        raise exceptions.APIError(utils.this_function(),
                                  "item_id must be a valid item id")
    item_type = enums.ItemType.get(item_type)
    related_type = enums.ItemType.get(related_type)

    _, parent_model = item_type._msg_and_model()
    child_msg, child_model = related_type._msg_and_model()

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

    s = constants.db_session()
    q = s.query(child_model.id).join(col).filter(parent_model.id == item_id)
    if offset:
        q = q.offset(offset)
    item_ids = q.limit(limit).all()
    items = database_cmd.GetModelItems().run(child_model,
                                             {x[0]
                                              for x in item_ids})

    item_list = message.List(db.model_name(child_model), child_msg)
    [item_list.append(child_msg(x)) for x in items]
    return item_list
예제 #23
0
 def _gallery_names(model_name, capture=db.model_name(db.Gallery)):
     return {
         ItemSort.GalleryRandom.value: "Random",
         ItemSort.GalleryTitle.value: "Title",
         ItemSort.GalleryArtist.value: "Artist",
         ItemSort.GalleryDate.value: "Date Added",
         ItemSort.GalleryPublished.value: "Date Published",
         ItemSort.GalleryRead.value: "Last Read",
         ItemSort.GalleryUpdated.value: "Last Updated",
         ItemSort.GalleryRating.value: "Rating",
         ItemSort.GalleryReadCount.value: "Read Count",
         ItemSort.GalleryPageCount.value: "Page Count",
     }
예제 #24
0
 def _gallery_orderby(model_name, capture=db.model_name(db.Gallery)):
     return {
         ItemSort.GalleryRandom.value: (func.random(), ),
         ItemSort.GalleryTitle.value: (db.Title.name, ),
         ItemSort.GalleryArtist.value: (db.ArtistName.name, ),
         ItemSort.GalleryDate.value: (db.Gallery.timestamp, ),
         ItemSort.GalleryPublished.value: (db.Gallery.pub_date, ),
         ItemSort.GalleryRead.value: (db.Gallery.last_read, ),
         ItemSort.GalleryUpdated.value: (db.Gallery.last_updated, ),
         ItemSort.GalleryRating.value: (db.Gallery.rating, ),
         ItemSort.GalleryReadCount.value: (db.Gallery.times_read, ),
         ItemSort.GalleryPageCount.value: (db.func.count(db.Page.id), ),
     }
예제 #25
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()
        self.cover = sess.query(
            db.Profile).filter(db.Profile.data == img_hash).one_or_none()

        if self.cover:
            if io_cmd.CoreFS(self.cover.path).exists:
                generate = False
        else:
            self.cover = db.Profile()

        if generate:
            model_name = db.model_name(model)
            with self.generate.call_capture(model_name, model_name, item_id,
                                            image_size) as plg:
                self.cover.path = plg.first()

            self.cover.data = img_hash
            self.cover.size = str(tuple(image_size))

        if self.cover.path and generate:
            i = GetModelItemByID().run(model, {item_id})[0]
            i.profiles.append(self.cover)
            sess.commit()
        elif not self.cover.path:
            self.cover = None

        self.cover_event.emit(self.cover)
        return self.cover
예제 #26
0
def _get_similar(kwargs, similar_items):
    item_list = message.List(db.model_name(kwargs['db_model']),
                             kwargs['db_msg'])
    items = []
    if similar_items:
        similar_items = similar_items[:kwargs['limit']]
        db_items = {}  # needed to sort them the way they came in
        for g in database_cmd.GetModelItems().run(kwargs['db_model'],
                                                  set(similar_items)):
            db_items[g.id] = g
        [items.append(db_items[x]) for x in similar_items if x in db_items]

    [item_list.append(kwargs['db_msg'](x)) for x in items]
    return item_list
예제 #27
0
    def main(self,
             model: db.Base,
             sort_index: int = None,
             name: bool = False) -> typing.Union[dict, SortTuple]:
        self.model = model
        model_name = db.model_name(self.model)
        items = {}
        if name:
            with self.names.call_capture(model_name, model_name) as plg:
                for x in plg.all(default=True):
                    items.update(x)
        else:
            orders = {}
            with self.orderby.call_capture(model_name, model_name) as plg:
                for x in plg.all(default=True):
                    orders.update(x)

            groups = {}
            with self.groupby.call_capture(model_name, model_name) as plg:
                for x in plg.all(default=True):
                    groups.update(x)

            joins = {}
            with self.joins.call_capture(model_name, model_name) as plg:
                for x in plg.all(default=True):
                    joins.update(x)

            for k, v in orders.items():
                a = v
                b = tuple()
                c = None
                if k in joins:
                    t = joins[k]
                    if isinstance(t, tuple):
                        b = t
                if k in groups:
                    c = groups[k]
                items[k] = self.SortTuple(a, b, c)

        return items.get(sort_index) if sort_index else items
예제 #28
0
    def main(self,
             model: db.Base,
             limit: int = 999,
             filter: str = "",
             order_by: str = "",
             offset: int = 0) -> tuple:

        s = constants.db_session()

        q = s.query(model)

        if filter:
            q = q.filter(db.sa_text(filter))

        if order_by:
            q = q.order_by(db.sa_text(order_by))

        self.fetched_items = tuple(self._query(q, limit, offset))

        self.fetched.emit(db.model_name(model), self.fetched_items)

        return self.fetched_items
예제 #29
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
예제 #30
0
def get_items(item_type: enums.ItemType = enums.ItemType.Gallery,
              limit: int = 100):
    """
    Get a list of items

    Args:
        item_type: type of item to get
        limit: limit the amount of items returned

    Returns:
        list of item message objects
    """

    item_type = enums.ItemType.get(item_type)

    db_msg, db_model = item_type._msg_and_model()

    items = database_cmd.GetModelItems().run(db_model, limit=limit)

    item_list = message.List(db.model_name(db_model), db_msg)
    [item_list.append(db_msg(i)) for i in items]
    return item_list