Files
winget.pro/winget/views.py
2023-01-23 17:43:08 +01:00

117 lines
4.0 KiB
Python

from collections import defaultdict
from django.db.models import Q
from django.http import HttpResponse
from django.shortcuts import get_object_or_404
from django.views.decorators.csrf import csrf_exempt
from django.views.decorators.http import require_GET, require_POST
from .models import Package
from .util import load_tenant, return_jsonresponse, parse_jsonrequest
@require_GET
@load_tenant
def index(*_):
# The sole motivation for this view is that we want to be able to
# reverse('winget:index') in instructions for setting up the winget source.
return HttpResponse("Please log in at /admin for instructions.")
@require_GET
@load_tenant
@return_jsonresponse
def information(*_):
return {
'SourceIdentifier': 'api.winget.pro',
'ServerSupportedVersions': ['1.1.0']
}
@require_POST
@csrf_exempt
@load_tenant
@parse_jsonrequest
@return_jsonresponse
def manifestSearch(_, data, tenant):
db_query = Q(tenant=tenant)
if 'Query' in data:
keyword = data['Query']['KeyWord']
db_query &= Q(name__icontains=keyword)
if 'Inclusions' in data:
inclusions_query = Q()
for inclusion in data['Inclusions']:
field = inclusion['PackageMatchField']
if field == 'PackageName':
keyword = inclusion['RequestMatch']['KeyWord']
inclusions_query |= Q(name__icontains=keyword)
elif field == 'ProductCode':
keyword = inclusion['RequestMatch']['KeyWord']
# We don't have a ProductCode. Use the identifier instead.
inclusions_query |= Q(identifier__icontains=keyword)
elif field == 'PackageFamilyName':
keyword = inclusion['RequestMatch']['KeyWord']
# We don't have family name. Use the name instead.
inclusions_query |= Q(name__icontains=keyword)
db_query &= inclusions_query
return [
{
'PackageIdentifier': package.identifier,
'PackageName': package.name,
'Publisher': package.publisher,
'Versions': [
{'PackageVersion': version}
for version in set(
package.installer_set.values_list('version', flat=True)
)
]
}
for package in Package.objects.filter(db_query)
]
@require_GET
@load_tenant
@return_jsonresponse
def packageManifests(request, tenant, identifier):
package = get_object_or_404(Package, tenant=tenant, identifier=identifier)
versions = defaultdict(list)
for installer in package.installer_set.all():
local_deps = []
for local_dep in installer.localdependency_set.all():
local_dep_dict = {
'PackageIdentifier': local_dep.installer.package.identifier
}
if local_dep.minimum_version:
local_dep_dict['MinimumVersion'] = local_dep.minimum_version
local_deps.append(local_dep_dict)
for scope in installer.scopes:
versions[installer.version].append(
{
'Architecture': installer.architecture,
'InstallerType': installer.type,
'InstallerUrl':
request.build_absolute_uri(installer.file.url),
'InstallerSha256': installer.sha256,
'Scope': scope,
'Dependencies': {
'PackageDependencies': local_deps
}
}
)
return {
'PackageIdentifier': package.identifier,
'Versions': [
{
'PackageVersion': version,
'DefaultLocale': {
'PackageLocale': 'en-us',
'Publisher': package.publisher,
'PackageName': package.name,
'ShortDescription': package.description
},
'Installers': installers
}
for version, installers in versions.items()
]
}