implement sharemetadata, fixes 165
This commit is contained in:
parent
8c5e39448b
commit
7a42473919
11 changed files with 162 additions and 43 deletions
|
|
@ -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:
|
||||
|
|
|
|||
|
|
@ -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')
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue