diff --git a/oml/changelog.py b/oml/changelog.py index 3ef61b1..aa43adc 100644 --- a/oml/changelog.py +++ b/oml/changelog.py @@ -130,13 +130,13 @@ class Changelog(db.Model): i = Item.get(itemid) if i: if user not in i.users: - i.users.append(user) + i.add_user(user) i.update() else: i = Item.get_or_create(itemid, info) i.modified = ts2datetime(timestamp) if user not in i.users: - i.users.append(user) + i.add_user(user) i.update() user.clear_smart_list_cache() return True @@ -150,13 +150,16 @@ class Changelog(db.Model): if i.timestamp > timestamp: logger.debug('ignore edititem change %s %s %s', timestamp, itemid, meta) return True + primary = None if 'primaryid' in meta: - keys = [meta['primaryid'][0]] + primary = meta['primaryid'] + key = primary[0] else: keys = [k for k in meta if k in Item.id_keys] - if keys: - key = keys[0] - primary = [key, meta[key]] + if keys: + key = keys[0] + primary = [key, meta[key]] + if primary: if not meta[key] and i.meta.get('primaryid', [''])[0] == key: logger.debug('remove id mapping %s %s', i.id, primary) i.update_primaryid(*primary, scrape=False) @@ -222,8 +225,6 @@ class Changelog(db.Model): from user.models import List l = List.get_or_create(user.id, name) l.add_items(ids) - user.clear_list_cache() - user.clear_smart_list_cache() return True def action_removelistitems(self, user, timestamp, name, ids): @@ -231,8 +232,6 @@ class Changelog(db.Model): l = List.get(user.id, name) if l: l.remove_items(ids) - user.clear_list_cache() - user.clear_smart_list_cache() return True def action_editusername(self, user, timestamp, username): diff --git a/oml/item/api.py b/oml/item/api.py index e705222..6084ecd 100644 --- a/oml/item/api.py +++ b/oml/item/api.py @@ -168,7 +168,9 @@ def remove(data): if 'ids' in data and data['ids']: for i in models.Item.query.filter(models.Item.id.in_(data['ids'])): i.remove_file() - state.user().clear_smart_list_cache() + u = state.user() + u.clear_smart_list_cache() + u.clear_list_cache() return { 'items': [] } diff --git a/oml/item/models.py b/oml/item/models.py index 3e1c87f..16a735b 100644 --- a/oml/item/models.py +++ b/oml/item/models.py @@ -90,6 +90,12 @@ class Item(db.Model): state.db.session.commit() return item + def add_user(self, user): + self.users.append(user) + l = user.library + l.items.append(self) + state.db.session.add(l) + def json(self, keys=None): j = {} j['id'] = self.id @@ -384,7 +390,7 @@ class Item(db.Model): if not u in self.users: t = Transfer.get_or_create(self.id) logger.debug('queue %s for download', self.id) - self.users.append(u) + self.add_user(u) def save_file(self, content): u = state.user() @@ -406,7 +412,7 @@ class Item(db.Model): with open(path, 'wb') as fd: fd.write(content) if u not in self.users: - self.users.append(u) + self.add_user(u) t = Transfer.get_or_create(self.id) t.progress = 1 t.save() diff --git a/oml/item/scan.py b/oml/item/scan.py index a0618d2..33703e7 100644 --- a/oml/item/scan.py +++ b/oml/item/scan.py @@ -52,7 +52,7 @@ def add_file(id, f, prefix, from_=None): if 'primaryid' in item.info: item.meta['primaryid'] = item.info.pop('primaryid') state.db.session.add(item) - item.users.append(user) + item.add_user(user) Changelog.record(user, 'additem', item.id, file.info) item.added = datetime.utcnow() if state.online: diff --git a/oml/queryparser.py b/oml/queryparser.py index 8720bd0..a7dbfbe 100644 --- a/oml/queryparser.py +++ b/oml/queryparser.py @@ -119,25 +119,18 @@ class Parser(object): u = self._user.query.filter_by(nickname=nickname).one() else: u = self._user.query.filter_by(id=settings.USER_ID).one() - if name: - l = self._list.query.filter_by(user_id=u.id, name=name).one() - else: - l = None - if not l: - if not u: - q = (self._user_items.columns['user_id'] == 0) - else: - q = (self._user_items.columns['user_id'] == u.id) - self._joins.append(self._user_items) - elif l.type == 'smart': - data = l._query - q = self.parse_conditions(data.get('conditions', []), - data.get('operator', '&')) - else: - q = (self._list.id == l.id) - self._joins.append(self._list.items) + l = self._list.query.filter_by(user_id=u.id, name=name).one() if exclude: - q = ~q + ids = [i.id for i in l.get_items()] + q = operators.notin_op(self._model.id, ids) + else: + if l.type == 'smart': + data = l._query + q = self.parse_conditions(data.get('conditions', []), + data.get('operator', '&')) + else: + q = (self._list.id == l.id) + self._joins.append(self._list.items) return q elif key_type == 'date': def parse_date(d): diff --git a/oml/setup.py b/oml/setup.py index 7b418e6..5430806 100644 --- a/oml/setup.py +++ b/oml/setup.py @@ -245,6 +245,24 @@ def upgrade_db(old, new=None): m.save() if old <= '20160106-495-d1b9e96': run_sql('CREATE INDEX ix_useritem_user ON useritem ("user_id")') + if old <= '20160106-497-c86ba8a': + with db.session() as session: + u = User.get(settings.USER_ID) + l = u.library + for i in u.items.all(): + if not i in l.items: + l.items.append(i) + session.add(l) + u.clear_list_cache() + for u in User.query.filter_by(peered=True): + l = u.library + for i in u.items.all(): + if not i in l.items: + l.items.append(i) + session.add(l) + u.clear_list_cache() + l.items_count() + session.commit() def create_default_lists(user_id=None): with db.session(): diff --git a/oml/user/api.py b/oml/user/api.py index 673c03d..0474362 100644 --- a/oml/user/api.py +++ b/oml/user/api.py @@ -181,9 +181,8 @@ def editList(data): l._query = data['query'] if l.type == 'static' and name != l.name: Changelog.record(state.user(), 'editlist', name, {'name': l.name}) - else: - l.user.clear_smart_list_cache() l.save() + l.user.clear_smart_list_cache() return l.json() actions.register(editList, cache=False) diff --git a/oml/user/models.py b/oml/user/models.py index ed6001e..4ad7cce 100644 --- a/oml/user/models.py +++ b/oml/user/models.py @@ -50,8 +50,6 @@ class User(db.Model): user.info['username'] = user.info['local']['username'] user.update_name() user.save() - if state.nodes: - state.nodes.queue('add', user.id) return user def save(self): @@ -62,7 +60,15 @@ class User(db.Model): def name(self): name = self.nickname if self.id != settings.USER_ID else '' return name - + + @property + def library(self): + l = List.get_or_create(self.id, '') + if l.index_ != -1: + l.index_ = -1 + l.save() + return l + def json(self): j = {} if self.info: @@ -81,21 +87,21 @@ class User(db.Model): return state.nodes and state.nodes.is_online(self.id) def lists_json(self): - return [{ - 'id': '%s:' % ('' if self.id == settings.USER_ID else self.nickname), - 'name': 'Library', - 'type': 'library', - 'items': self.items.count(), - 'user': self.name - }] + [l.json() for l in self.lists.order_by('index_')] + self.library + return [l.json() for l in self.lists.order_by('index_')] def clear_list_cache(self): + if self.id == settings.USER_ID: + prefix = ':' + else: + prefix = self.id + ':' for key in list(settings.list_cache): - if key.startswith(self.id + ':'): + if key.startswith(prefix): del settings.list_cache[key] def clear_smart_list_cache(self): - smart_lists = [':%d' % l.id for l in List.query.filter_by(type='smart')] + qs = List.query.filter_by(type='smart') + smart_lists = [':%d' % l.id for l in qs] for key in list(settings.list_cache): if key in smart_lists: del settings.list_cache[key] @@ -258,7 +264,15 @@ class List(db.Model): state.db.session.commit() if self.user_id == settings.USER_ID: Changelog.record(self.user, 'addlistitems', self.name, items) - self.clear_smart_list_cache() + self.user.clear_smart_list_cache() + self.user.clear_list_cache() + + def get_items(self): + if self.type == 'smart': + from item.models import Item, user_items + return Parser(Item, user_items).find({'query': self._query}) + else: + return self.items def remove_items(self, items): from item.models import Item @@ -271,6 +285,8 @@ class List(db.Model): state.db.session.commit() if self.user_id == settings.USER_ID: Changelog.record(self.user, 'removelistitems', self.name, items) + self.user.clear_smart_list_cache() + self.user.clear_list_cache() def remove(self): if not self._query: @@ -306,10 +322,8 @@ class List(db.Model): if key in settings.list_cache: value = settings.list_cache[key] else: - from item.models import Item, user_items - if self._query: - data = self._query - value = Parser(Item, user_items).find({'query': data}).count() + if self.type == 'smart': + value = self.get_items().count() else: value = len(self.items) settings.list_cache[key] = value @@ -324,6 +338,10 @@ class List(db.Model): 'items': self.items_count(), 'type': self.type } + if self.name == '': + r['name'] = 'Library' + r['type'] = 'library' + del r['index'] if self.type == 'smart': r['query'] = self._query return r