backup for Phase 2.5
This commit is contained in:
+107
-10
@@ -30,7 +30,7 @@ from .models import (
|
||||
slugify_tag,
|
||||
)
|
||||
from .storage import delete_file_index, move_file_index, store_temp_file
|
||||
from .zips import parse_mods_manifest, read_pack_mcmeta
|
||||
from .zips import parse_mods_manifest, read_animation_manifest, read_pack_mcmeta
|
||||
|
||||
|
||||
def _open_indexed_file(file_index):
|
||||
@@ -316,10 +316,24 @@ def project_detail(request, slug):
|
||||
can_edit = project.can_edit(request.user)
|
||||
|
||||
guide_docs = []
|
||||
if project.category == 'guide':
|
||||
latest = versions.first()
|
||||
if latest is not None:
|
||||
guide_docs = [vf for vf in latest.files.all() if vf.is_markdown]
|
||||
animation_manifest = None
|
||||
anim_stats = None
|
||||
latest = versions.first()
|
||||
if project.category == 'guide' and latest is not None:
|
||||
guide_docs = [vf for vf in latest.files.all() if vf.is_markdown]
|
||||
if latest is not None and latest.animation_manifest:
|
||||
animation_manifest = latest.animation_manifest
|
||||
anims = animation_manifest.get('animations') or []
|
||||
entity_count = sum(1 for a in anims if a.get('type') == 'Entity x Player')
|
||||
solo_count = sum(1 for a in anims if a.get('type') == 'Solo')
|
||||
anim_stats = {
|
||||
'total': len(anims),
|
||||
'entity': entity_count,
|
||||
'player': len(anims) - entity_count - solo_count,
|
||||
'solo': solo_count,
|
||||
'flagged': sum(1 for a in anims if a.get('problem_tags')),
|
||||
'tags': sorted({t for a in anims for t in (a.get('content_tags') or [])}),
|
||||
}
|
||||
|
||||
context = {
|
||||
'project': project,
|
||||
@@ -328,10 +342,43 @@ def project_detail(request, slug):
|
||||
'tags': tags,
|
||||
'can_edit': can_edit,
|
||||
'guide_docs': guide_docs,
|
||||
'animation_manifest': animation_manifest,
|
||||
'anim_stats': anim_stats,
|
||||
}
|
||||
return render(request, 'library/project_detail.html', context)
|
||||
|
||||
|
||||
@login_required
|
||||
def api_packs_latest(request, namespace, pack_id):
|
||||
"""Auto-updater endpoint: newest version for a NoN pack id (namespace:pack_id)."""
|
||||
animation_id = f'{namespace}:{pack_id}'
|
||||
version = (
|
||||
Version.objects.filter(animation_id=animation_id)
|
||||
.select_related('project').prefetch_related('files__file')
|
||||
.order_by('-created_at').first()
|
||||
)
|
||||
if version is None:
|
||||
return JsonResponse({'detail': 'Not found'}, status=404)
|
||||
release = next(
|
||||
(vf for vf in version.files.all() if vf.kind == 'release'),
|
||||
version.files.first(),
|
||||
)
|
||||
if release is None:
|
||||
return JsonResponse({'detail': 'No file'}, status=404)
|
||||
download_url = request.build_absolute_uri(
|
||||
reverse('library:file_request', args=[release.file.uuid]) + '?download=1'
|
||||
)
|
||||
return JsonResponse({
|
||||
'namespace': namespace,
|
||||
'pack_id': pack_id,
|
||||
'name': version.project.title,
|
||||
'version': version.version_name,
|
||||
'pack_format': version.pack_format,
|
||||
'created_at': version.created_at.isoformat(),
|
||||
'download_url': download_url,
|
||||
})
|
||||
|
||||
|
||||
def guide_doc(request, slug, version_id, file_uuid):
|
||||
"""Render one markdown guide document server-side (used by the switcher)."""
|
||||
version = get_object_or_404(
|
||||
@@ -410,9 +457,34 @@ def _stored_path(file_index):
|
||||
return Path(settings.MEDIA_ROOT) / file_index.stored_path
|
||||
|
||||
|
||||
def _finalize_version(project, version_name, changelog, temp_uploads):
|
||||
ANIMATION_API_WARNING = (
|
||||
'Warning: your pack is incompatible with the update-check API endpoint and '
|
||||
'may not work with applications that check for updates. Add an '
|
||||
"'animationframework' block to pack.mcmeta, e.g.: "
|
||||
'{"pack":{"pack_format":64},"animationframework":{"id":"yourname:yourpack",'
|
||||
'"name":"Your Pack","author":"You","version":"1.0.0","description":"..."}}'
|
||||
)
|
||||
|
||||
|
||||
def _apply_content_tags(project, tag_names, actor):
|
||||
"""Auto-create a content:<tag> for every distinct animation content tag."""
|
||||
content_cat = TagCategory.objects.filter(slug='content').first()
|
||||
if content_cat is None:
|
||||
return
|
||||
for name in tag_names:
|
||||
name = slugify_tag(name)
|
||||
if not name:
|
||||
continue
|
||||
tag, _ = Tag.objects.get_or_create(
|
||||
name=name, category=content_cat, defaults={'created_by': actor},
|
||||
)
|
||||
TagList.objects.get_or_create(project=project, tag=tag, defaults={'added_by': actor})
|
||||
|
||||
|
||||
def _finalize_version(project, version_name, changelog, temp_uploads, actor):
|
||||
"""Adopt pending 'version' temp uploads into a new Version as VersionFiles,
|
||||
capturing category-specific metadata (pack.mcmeta / mods manifest)."""
|
||||
capturing category-specific metadata (pack.mcmeta / mods manifest / animation
|
||||
manifest). Returns (version, missing_animation_id)."""
|
||||
version = Version.objects.create(
|
||||
project=project,
|
||||
version_name=version_name,
|
||||
@@ -421,6 +493,8 @@ def _finalize_version(project, version_name, changelog, temp_uploads):
|
||||
pack_format = None
|
||||
pack_description = ''
|
||||
mods_manifest = {}
|
||||
animation_manifest = None
|
||||
missing_animation_id = False
|
||||
|
||||
for temp in temp_uploads:
|
||||
index = _adopt_temp(temp, project.pk, 'versions', 'version')
|
||||
@@ -442,6 +516,12 @@ def _finalize_version(project, version_name, changelog, temp_uploads):
|
||||
manifest = parse_mods_manifest(_stored_path(index), index.original_filename)
|
||||
if manifest.get('files'):
|
||||
mods_manifest = manifest
|
||||
if is_zip and animation_manifest is None:
|
||||
manifest = read_animation_manifest(_stored_path(index))
|
||||
if manifest is not None:
|
||||
animation_manifest = manifest
|
||||
if not manifest.get('animation_id'):
|
||||
missing_animation_id = True
|
||||
|
||||
update_fields = []
|
||||
if pack_format is not None:
|
||||
@@ -451,9 +531,20 @@ def _finalize_version(project, version_name, changelog, temp_uploads):
|
||||
if mods_manifest:
|
||||
version.mods_manifest = mods_manifest
|
||||
update_fields.append('mods_manifest')
|
||||
if animation_manifest is not None:
|
||||
version.animation_manifest = animation_manifest
|
||||
update_fields.append('animation_manifest')
|
||||
if animation_manifest.get('animation_id'):
|
||||
version.animation_id = animation_manifest['animation_id']
|
||||
update_fields.append('animation_id')
|
||||
if update_fields:
|
||||
version.save(update_fields=update_fields)
|
||||
return version
|
||||
|
||||
if animation_manifest is not None:
|
||||
_apply_content_tags(
|
||||
project, animation_manifest.get('content_tags') or [], actor,
|
||||
)
|
||||
return version, missing_animation_id
|
||||
|
||||
|
||||
def _form_values(*forms):
|
||||
@@ -494,12 +585,15 @@ def project_create(request):
|
||||
thumb.save(update_fields=['status'])
|
||||
project.save(update_fields=['thumbnail'])
|
||||
|
||||
_finalize_version(
|
||||
_, missing_animation_id = _finalize_version(
|
||||
project,
|
||||
version_form.cleaned_data['version_name'],
|
||||
version_form.cleaned_data['changelog'],
|
||||
version_files,
|
||||
request.user,
|
||||
)
|
||||
if missing_animation_id:
|
||||
messages.warning(request, ANIMATION_API_WARNING)
|
||||
|
||||
for temp in TempUpload.objects.filter(
|
||||
user=request.user, status='pending', kind='media',
|
||||
@@ -631,12 +725,15 @@ def version_upload(request, slug):
|
||||
if not version_files:
|
||||
form.add_error('version_name', 'Upload at least one version file before uploading.')
|
||||
else:
|
||||
_finalize_version(
|
||||
_, missing_animation_id = _finalize_version(
|
||||
project,
|
||||
form.cleaned_data['version_name'],
|
||||
form.cleaned_data['changelog'],
|
||||
version_files,
|
||||
request.user,
|
||||
)
|
||||
if missing_animation_id:
|
||||
messages.warning(request, ANIMATION_API_WARNING)
|
||||
messages.success(request, f'Version {form.cleaned_data["version_name"]} uploaded.')
|
||||
return redirect('library:project_detail', slug=project.slug)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user