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
def get_related_count(item_type: enums.ItemType = enums.ItemType.Gallery, item_id: int = 0, related_type: enums.ItemType = enums.ItemType.Page): """ Get count of items related to given item Args: item_type: parent item item_id: id of parent item related_type: child item Returns: ``` { 'id': int, 'count': int } ``` """ 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() count = s.query( child_model.id).join(col).filter(parent_model.id == item_id).count() return message.Identity('count', {'id': item_id, 'count': count})
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
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() 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) if term.namespace: lower_ns = term.namespace.lower() if lower_ns == 'path': ids.update(x[0] for x in q.filter(match_string(db.Gallery.path, term.tag, options)).all()) elif lower_ns in ("rating", "stars"): ids.update(x[0] for x in q.filter(match_int(db.Gallery.rating, term.tag, options)).all()) return ids
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
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
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()
def _match_namemixin(parent_model, child_model, term, options, capture=[ db.model_name(x) for x in _models() if issubclass(x, db.NameMixin) ]): 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() s = constants.db_session() col = db.relationship_column(parent_model, child_model) ids.update(x[0] for x in s.query(parent_model.id).join(col).filter( match_string(child_model.name, term, options)).all()) return ids
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