implement sharemetadata, fixes 165

This commit is contained in:
j 2016-01-19 15:35:16 +05:30
commit 7a42473919
11 changed files with 162 additions and 43 deletions

View file

@ -140,7 +140,7 @@ def edit(data):
for id in ids:
item = models.Item.get(id)
if item and item.json()['mediastate'] == 'available':
item.edit(data, reset_from=True)
item.edit(data)
response = item.json()
edited.append(id)
else:

View file

@ -3,6 +3,7 @@
from datetime import datetime
import base64
import hashlib
import json
import os
import re
import shutil
@ -10,6 +11,7 @@ import stat
import unicodedata
import ox
from sqlalchemy.orm import load_only
from sqlalchemy.schema import CreateTable
import sqlalchemy as sa
@ -136,7 +138,7 @@ class Item(db.Model):
for k in list(j):
if k not in keys:
del j[k]
for key in [k['id'] for k in settings.config['itemKeys'] if isinstance(k['type'], list)]:
for key in self.array_keys:
if key in j and not isinstance(j[key], list):
j[key] = [j[key]]
return j
@ -272,11 +274,12 @@ class Item(db.Model):
'place',
'publisher',
'series',
'sharemetadata',
'tableofcontents',
'title'
)
def update_meta(self, data, modified=None, reset_from=False):
def update_metadata(self, data, modified=None):
update = False
record = {}
for key in self.meta_keys:
@ -289,9 +292,6 @@ class Item(db.Model):
if key not in self.meta_keys:
del self.meta[key]
update = True
if reset_from and '_from' in self.info:
del self.info['_from']
update = True
if update:
self.update(modified)
self.save()
@ -300,13 +300,58 @@ class Item(db.Model):
user = state.user()
if record and user in self.users:
Changelog.record_ts(user, modified, 'edititem', self.id, record)
logger.debug('edititem foobar, got sharemetadata?', record)
if 'sharemetadata' in record and not record['sharemetadata']:
logger.debug('metadata no longer true, lets sync up')
self.sync_metadata()
def edit(self, data, modified=None, reset_from=False):
def edit(self, data, modified=None):
Scrape.query.filter_by(item_id=self.id).delete()
self.update_meta(data, modified, reset_from=reset_from)
self.update_metadata(data, modified)
for f in self.files.all():
f.move()
def get_hash(self):
return utils.get_meta_hash(self.meta.copy())
def sync_metadata(self):
from user.models import Metadata
if self.meta.get('sharemetadata'):
return
peers = [u for u in self.users if u.id != settings.USER_ID]
peers.sort(key=lambda u: ox.sort_string(str(u.info.get('index', ''))
+ 'Z' + (u.info.get('name') or '')))
sync_from = None
first_peer = None
# get first peer with sharemetadata set
for u in peers:
m = Metadata.get(u.id, self.id)
if m:
if m.data.get('sharemetadata'):
sync_from = m
break
if not first_peer:
first_peer = m
# of fall back to first peer that has this item
# in case its not available locally
if not sync_from and self.info['mediastate'] != 'available' and first_peer:
logger.debug('syncing from first peer that has item %s', first_peer)
sync_from = first_peer
if sync_from:
if self.get_hash() != sync_from.data_hash:
logger.debug('update %s with metadata from %s', self, sync_from.user_id)
record = {}
for key in sync_from.data:
if key != 'sharemetadata' and self.meta.get(key) != sync_from.data[key]:
record[key] = self.meta[key] = sync_from.data[key]
for key in set(self.meta)-set(sync_from.data):
record[key] = self.meta[key] = [] if key in self.array_keys else ''
self.update(sync_from.modified)
self.save()
user = state.user()
if record and user in self.users:
Changelog.record_ts(user, self.modified, 'edititem', self.id, record)
def extract_preview(self):
path = self.get_path()
if path:
@ -493,6 +538,7 @@ for key in config['itemKeys']:
Item.id_keys = ['isbn', 'lccn', 'olid', 'oclc', 'asin']
Item.item_keys = config['itemKeys']
Item.filter_keys = [k['id'] for k in config['itemKeys'] if k.get('filter')]
Item.array_keys = [k['id'] for k in config['itemKeys'] if isinstance(k['type'], list)]
class Find(db.Model):
__tablename__ = 'find'
@ -814,3 +860,25 @@ def update_sort_table():
for q in sql:
s.connection().execute(q)
s.commit()
def sync_metadata(ids=None):
#logger.debug('sync_metadata(%s)', len(ids) if ids else ids)
step = 1000
delay = 10
with db.session():
if not ids:
ids = [i.id for i in Item.query.options(load_only('id'))]
if len(ids) > step:
later = ids[step:]
ids = ids[:step]
else:
later = []
if ids:
for i in Item.query.filter(Item.id.in_(ids)):
i.sync_metadata()
if later:
if state.main and state.tasks:
state.main.call_later(delay, lambda: state.tasks.queue('syncmetadata', [later]))
#else:
# logger.debug('sync_metadata done')