forked from 0x2620/pandora
Merge branch 'master' of git.0x2620.org:/pandora
This commit is contained in:
commit
72643eb537
5 changed files with 116 additions and 74 deletions
|
@ -89,8 +89,8 @@ def add_subtitles(item, media, tmp):
|
||||||
def download(item_id, url):
|
def download(item_id, url):
|
||||||
item = Item.objects.get(public_id=item_id)
|
item = Item.objects.get(public_id=item_id)
|
||||||
info = get_info(url)
|
info = get_info(url)
|
||||||
if len(info) != 1:
|
if not len(info):
|
||||||
return '%s contains %d videos' % (url, len(info))
|
return '%s contains no videos' % url
|
||||||
media = info[0]
|
media = info[0]
|
||||||
cdir = os.path.abspath(os.curdir)
|
cdir = os.path.abspath(os.curdir)
|
||||||
tmp = tempfile.mkdtemp().decode('utf-8')
|
tmp = tempfile.mkdtemp().decode('utf-8')
|
||||||
|
@ -100,28 +100,34 @@ def download(item_id, url):
|
||||||
stdout=subprocess.PIPE,
|
stdout=subprocess.PIPE,
|
||||||
stderr=subprocess.PIPE, close_fds=True)
|
stderr=subprocess.PIPE, close_fds=True)
|
||||||
stdout, stderr = p.communicate()
|
stdout, stderr = p.communicate()
|
||||||
fname = list(os.listdir(tmp))
|
parts = list(os.listdir(tmp))
|
||||||
if fname:
|
if parts:
|
||||||
fname = os.path.join(tmp, fname[0])
|
part = 1
|
||||||
oshash = ox.oshash(fname)
|
for name in parts:
|
||||||
f, created = models.File.objects.get_or_create(oshash=oshash)
|
name = os.path.join(tmp, name)
|
||||||
if created:
|
oshash = ox.oshash(name)
|
||||||
f.data.name = f.get_path('data.' + fname.split('.')[-1])
|
f, created = models.File.objects.get_or_create(oshash=oshash)
|
||||||
ox.makedirs(os.path.dirname(f.data.path))
|
if created:
|
||||||
shutil.move(fname, f.data.path)
|
f.data.name = f.get_path('data.' + name.split('.')[-1])
|
||||||
f.item = item
|
ox.makedirs(os.path.dirname(f.data.path))
|
||||||
f.info = ox.avinfo(f.data.path)
|
shutil.move(name, f.data.path)
|
||||||
f.info['extension'] = media['extension']
|
f.item = item
|
||||||
f.path = '%(title)s.%(extension)s' % media
|
f.info = ox.avinfo(f.data.path)
|
||||||
f.parse_info()
|
f.info['extension'] = media['extension']
|
||||||
f.selected = True
|
f.path = '%(title)s.%(extension)s' % media
|
||||||
f.save()
|
f.parse_info()
|
||||||
f.item.save()
|
f.selected = True
|
||||||
f.extract_stream()
|
if len(parts) > 1:
|
||||||
status = True
|
f.part = part
|
||||||
else:
|
part += 1
|
||||||
status = 'file exists'
|
f.save()
|
||||||
add_subtitles(f.item, media, tmp)
|
f.item.save()
|
||||||
|
f.extract_stream()
|
||||||
|
status = True
|
||||||
|
else:
|
||||||
|
status = 'file exists'
|
||||||
|
if len(parts) == 1:
|
||||||
|
add_subtitles(f.item, media, tmp)
|
||||||
else:
|
else:
|
||||||
status = 'download failed'
|
status = 'download failed'
|
||||||
os.chdir(cdir)
|
os.chdir(cdir)
|
||||||
|
|
|
@ -51,6 +51,7 @@
|
||||||
"canEditUsers": {"admin": true},
|
"canEditUsers": {"admin": true},
|
||||||
"canExportAnnotations": {"friend": true, "staff": true, "admin": true},
|
"canExportAnnotations": {"friend": true, "staff": true, "admin": true},
|
||||||
"canImportAnnotations": {"staff": true, "admin": true},
|
"canImportAnnotations": {"staff": true, "admin": true},
|
||||||
|
"canImportItems": {},
|
||||||
"canManageDocuments": {"staff": true, "admin": true},
|
"canManageDocuments": {"staff": true, "admin": true},
|
||||||
"canManageEntities": {"staff": true, "admin": true},
|
"canManageEntities": {"staff": true, "admin": true},
|
||||||
"canManagePlacesAndEvents": {"staff": true, "admin": true},
|
"canManagePlacesAndEvents": {"staff": true, "admin": true},
|
||||||
|
@ -132,6 +133,18 @@
|
||||||
{"id": "embeds", "title": "Embeds"}
|
{"id": "embeds", "title": "Embeds"}
|
||||||
],
|
],
|
||||||
/*
|
/*
|
||||||
|
"importMetadata" defines what fields (as defined in "itemKeys") will get
|
||||||
|
populated with imported metadata. There is metadata for "title",
|
||||||
|
"description", "uploader", "date", "tags", "id", "url", and the value must
|
||||||
|
be a format string (like "{title} ({id})"). The type of the itemKeys must
|
||||||
|
be "string", ["string"], "text", "date" or "year". The last two only work
|
||||||
|
with "{date}".
|
||||||
|
*/
|
||||||
|
"importMetadata": {
|
||||||
|
"summary": "{description}",
|
||||||
|
"title": "{title}"
|
||||||
|
},
|
||||||
|
/*
|
||||||
"itemKeys" defines the metadata associated with each item. Required keys
|
"itemKeys" defines the metadata associated with each item. Required keys
|
||||||
are "*", "id" and "title". Annotation layers can be referenced too, which
|
are "*", "id" and "title". Annotation layers can be referenced too, which
|
||||||
makes them available in the find element. Adding a key with "annotations"
|
makes them available in the find element. Adding a key with "annotations"
|
||||||
|
|
|
@ -52,6 +52,8 @@
|
||||||
"canEditUsers": {"staff": true, "admin": true},
|
"canEditUsers": {"staff": true, "admin": true},
|
||||||
"canExportAnnotations": {"member": true, "researcher": true, "staff": true, "admin": true},
|
"canExportAnnotations": {"member": true, "researcher": true, "staff": true, "admin": true},
|
||||||
"canImportAnnotations": {"researcher": true, "staff": true, "admin": true},
|
"canImportAnnotations": {"researcher": true, "staff": true, "admin": true},
|
||||||
|
// import needs to handle itemRequiresVideo=false first
|
||||||
|
"canImportItems": {},
|
||||||
"canManageDocuments": {"member": true, "researcher": true, "staff": true, "admin": true},
|
"canManageDocuments": {"member": true, "researcher": true, "staff": true, "admin": true},
|
||||||
"canManageEntities": {"member": true, "researcher": true, "staff": true, "admin": true},
|
"canManageEntities": {"member": true, "researcher": true, "staff": true, "admin": true},
|
||||||
"canManagePlacesAndEvents": {"member": true, "researcher": true, "staff": true, "admin": true},
|
"canManagePlacesAndEvents": {"member": true, "researcher": true, "staff": true, "admin": true},
|
||||||
|
@ -137,6 +139,18 @@
|
||||||
{"id": "embeds", "title": "Embeds"}
|
{"id": "embeds", "title": "Embeds"}
|
||||||
],
|
],
|
||||||
/*
|
/*
|
||||||
|
"importMetadata" defines what fields (as defined in "itemKeys") will get
|
||||||
|
populated with imported metadata. There is metadata for "title",
|
||||||
|
"description", "uploader", "date", "tags", "id", "url", and the value must
|
||||||
|
be a format string (like "{title} ({id})"). The type of the itemKeys must
|
||||||
|
be "string", ["string"], "text", "date" or "year". The last two only work
|
||||||
|
with "{date}".
|
||||||
|
*/
|
||||||
|
"importMetadata": {
|
||||||
|
"summary": "{description}",
|
||||||
|
"title": "{title}"
|
||||||
|
},
|
||||||
|
/*
|
||||||
"itemKeys" defines the metadata associated with each item. Required keys
|
"itemKeys" defines the metadata associated with each item. Required keys
|
||||||
are "*", "id" and "title". Annotation layers can be referenced too, which
|
are "*", "id" and "title". Annotation layers can be referenced too, which
|
||||||
makes them available in the find element. Adding a key with "annotations"
|
makes them available in the find element. Adding a key with "annotations"
|
||||||
|
|
|
@ -51,6 +51,7 @@
|
||||||
"canEditUsers": {"admin": true},
|
"canEditUsers": {"admin": true},
|
||||||
"canExportAnnotations": {"member": true, "staff": true, "admin": true},
|
"canExportAnnotations": {"member": true, "staff": true, "admin": true},
|
||||||
"canImportAnnotations": {"member": true, "staff": true, "admin": true},
|
"canImportAnnotations": {"member": true, "staff": true, "admin": true},
|
||||||
|
"canImportItems": {"member": true, "staff": true, "admin": true},
|
||||||
"canManageDocuments": {"member": true, "staff": true, "admin": true},
|
"canManageDocuments": {"member": true, "staff": true, "admin": true},
|
||||||
"canManageEntities": {"member": true, "staff": true, "admin": true},
|
"canManageEntities": {"member": true, "staff": true, "admin": true},
|
||||||
"canManagePlacesAndEvents": {"member": true, "staff": true, "admin": true},
|
"canManagePlacesAndEvents": {"member": true, "staff": true, "admin": true},
|
||||||
|
@ -135,6 +136,14 @@
|
||||||
{"id": "texts", "title": "Texts"},
|
{"id": "texts", "title": "Texts"},
|
||||||
{"id": "embeds", "title": "Embeds"}
|
{"id": "embeds", "title": "Embeds"}
|
||||||
],
|
],
|
||||||
|
/*
|
||||||
|
"importMetadata" defines what fields (as defined in "itemKeys") will get
|
||||||
|
populated with imported metadata. There is metadata for "title",
|
||||||
|
"description", "uploader", "date", "tags", "id", "url", and the value must
|
||||||
|
be a format string (like "{title} ({id})"). The type of the itemKeys must
|
||||||
|
be "string", ["string"], "text", "date" or "year". The last two only work
|
||||||
|
with "{date}".
|
||||||
|
*/
|
||||||
"importMetadata": {
|
"importMetadata": {
|
||||||
"date": "{date}",
|
"date": "{date}",
|
||||||
"topic": "{tags}",
|
"topic": "{tags}",
|
||||||
|
|
|
@ -84,57 +84,57 @@ pandora.ui.importMediaDialog = function(options) {
|
||||||
|
|
||||||
function addMedia(url, callback) {
|
function addMedia(url, callback) {
|
||||||
pandora.api.getMediaUrlInfo({url: url}, function(result) {
|
pandora.api.getMediaUrlInfo({url: url}, function(result) {
|
||||||
result.data.items.forEach(function(info) {
|
// FIXME: support playlists / multiple items
|
||||||
var infoKeys = [
|
var info = result.data.items[0];
|
||||||
'date', 'description', 'id', 'tags',
|
var infoKeys = [
|
||||||
'title', 'uploader', 'url'
|
'date', 'description', 'id', 'tags',
|
||||||
];
|
'title', 'uploader', 'url'
|
||||||
var values = Ox.map(pandora.site.importMetadata, function(value, key) {
|
];
|
||||||
var isArray = Ox.isArray(
|
var values = Ox.map(pandora.site.importMetadata, function(value, key) {
|
||||||
Ox.getObjectById(pandora.site.itemKeys, key).type
|
var isArray = Ox.isArray(
|
||||||
);
|
Ox.getObjectById(pandora.site.itemKeys, key).type
|
||||||
if (isArray && value == '{tags}') {
|
);
|
||||||
value = info.tags;
|
if (isArray && value == '{tags}') {
|
||||||
} else {
|
value = info.tags;
|
||||||
infoKeys.forEach(function(infoKey) {
|
} else {
|
||||||
var infoValue = info[infoKey];
|
infoKeys.forEach(function(infoKey) {
|
||||||
if (key == 'year' && infoKey == 'date') {
|
var infoValue = info[infoKey] || '';
|
||||||
infoValue = infoValue.substr(0, 4);
|
if (key == 'year' && infoKey == 'date') {
|
||||||
}
|
infoValue = infoValue.substr(0, 4);
|
||||||
if (infoKey == 'tags') {
|
|
||||||
infoValue = infoValue.join(', ');
|
|
||||||
}
|
|
||||||
value = value.replace(
|
|
||||||
new RegExp('\{' + infoKey + '\}', 'g'), infoValue
|
|
||||||
);
|
|
||||||
});
|
|
||||||
// For example: director -> uploader
|
|
||||||
if (isArray) {
|
|
||||||
value = [value];
|
|
||||||
}
|
}
|
||||||
|
if (infoKey == 'tags') {
|
||||||
|
infoValue = infoValue.join(', ');
|
||||||
|
}
|
||||||
|
value = value.replace(
|
||||||
|
new RegExp('\{' + infoKey + '\}', 'g'), infoValue
|
||||||
|
);
|
||||||
|
});
|
||||||
|
// For example: director -> uploader
|
||||||
|
if (isArray) {
|
||||||
|
value = [value];
|
||||||
}
|
}
|
||||||
return value;
|
}
|
||||||
});
|
return value;
|
||||||
pandora.api.add({title: values.title || info.title}, function(result) {
|
});
|
||||||
var edit = Ox.extend(
|
pandora.api.add({title: values.title || info.title}, function(result) {
|
||||||
Ox.filter(values, function(value, key) {
|
var edit = Ox.extend(
|
||||||
return key != 'title';
|
Ox.filter(values, function(value, key) {
|
||||||
}),
|
return key != 'title';
|
||||||
{'id': result.data.id}
|
}),
|
||||||
);
|
{'id': result.data.id}
|
||||||
pandora.api.edit(edit, function(result) {
|
);
|
||||||
pandora.api.addMediaUrl({
|
pandora.api.edit(edit, function(result) {
|
||||||
url: info.url,
|
pandora.api.addMediaUrl({
|
||||||
item: edit.id
|
url: info.url,
|
||||||
}, function(result) {
|
item: edit.id
|
||||||
if (result.data.taskId) {
|
}, function(result) {
|
||||||
pandora.wait(result.data.taskId, function(result) {
|
if (result.data.taskId) {
|
||||||
callback(edit.id);
|
pandora.wait(result.data.taskId, function(result) {
|
||||||
});
|
|
||||||
} else {
|
|
||||||
callback(edit.id);
|
callback(edit.id);
|
||||||
}
|
});
|
||||||
});
|
} else {
|
||||||
|
callback(edit.id);
|
||||||
|
}
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@ -183,7 +183,7 @@ pandora.ui.importMediaDialog = function(options) {
|
||||||
if (items.length) {
|
if (items.length) {
|
||||||
// FIXME: support playlists / multiple items
|
// FIXME: support playlists / multiple items
|
||||||
var info = items[0];
|
var info = items[0];
|
||||||
$info.append($('<img>').css({
|
info.thumbnail && $info.append($('<img>').css({
|
||||||
position: 'absolute',
|
position: 'absolute',
|
||||||
width: '248px'
|
width: '248px'
|
||||||
}).attr('src', info.thumbnail));
|
}).attr('src', info.thumbnail));
|
||||||
|
@ -196,7 +196,7 @@ pandora.ui.importMediaDialog = function(options) {
|
||||||
width: '248px'
|
width: '248px'
|
||||||
}).html(
|
}).html(
|
||||||
'<span style="font-weight: bold">' + info.title
|
'<span style="font-weight: bold">' + info.title
|
||||||
+ '</span><br/><br/>' + info.description
|
+ '</span><br/><br/>' + (info.description || '')
|
||||||
));
|
));
|
||||||
that.enableButton('import');
|
that.enableButton('import');
|
||||||
} else {
|
} else {
|
||||||
|
|
Loading…
Reference in a new issue