mirror of
https://github.com/omaha-consulting/winget.pro.git
synced 2026-10-24 12:52:26 +00:00
134 lines
5.3 KiB
Python
134 lines
5.3 KiB
Python
from django.core.exceptions import ObjectDoesNotExist
|
|
from django.db.models import Q
|
|
from django.http import HttpResponse
|
|
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.4.0', '1.5.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)
|
|
inclusions_query = Q()
|
|
for inclusion in data.get('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
|
|
for filter_ in data.get('Filters', []):
|
|
field = filter_['PackageMatchField']
|
|
keyword = filter_['RequestMatch']['KeyWord']
|
|
if field == 'PackageIdentifier':
|
|
db_query &= Q(identifier__icontains=keyword)
|
|
return [
|
|
{
|
|
'PackageIdentifier': package.identifier,
|
|
'PackageName': package.name,
|
|
'Publisher': package.publisher,
|
|
'Versions': [
|
|
{'PackageVersion': version.version}
|
|
for version in package.version_set.all()
|
|
]
|
|
}
|
|
for package in Package.objects.filter(db_query)
|
|
if package.version_set.exists()
|
|
]
|
|
|
|
@require_GET
|
|
@load_tenant
|
|
def packageManifests(request, tenant, identifier):
|
|
try:
|
|
package = Package.objects.get(tenant=tenant, identifier=identifier)
|
|
except ObjectDoesNotExist:
|
|
# This is a peculiarity / inconsistency of the winget client. The API
|
|
# design docs say that packageManifests should return 404 when a package
|
|
# does not exist. But winget doesn't gracefully handle this case.
|
|
# Instead, it expects HTTP 204.
|
|
# See: https://github.com/microsoft/winget-cli-restsource/issues/170
|
|
return HttpResponse(status=204)
|
|
return _packageManifests(request, package)
|
|
|
|
@return_jsonresponse
|
|
def _packageManifests(request, package):
|
|
result = {
|
|
'PackageIdentifier': package.identifier
|
|
}
|
|
for version in package.version_set.all():
|
|
installers = []
|
|
for installer in version.installer_set.all():
|
|
for scope in installer.scopes:
|
|
installer_json = {
|
|
'Architecture': installer.architecture,
|
|
'InstallerType': installer.type,
|
|
'InstallerUrl':
|
|
request.build_absolute_uri(installer.file.url),
|
|
'InstallerSha256': installer.sha256,
|
|
'Scope': scope
|
|
}
|
|
if installer.nested_installer:
|
|
# NestedInstallerFiles needs to be a list even though at
|
|
# least winget 1.6.2771 does not support more than one.
|
|
installer_json['NestedInstallerFiles'] = [{
|
|
'RelativeFilePath': installer.nested_installer
|
|
}]
|
|
if installer.nested_installer_type:
|
|
installer_json['NestedInstallerType'] = \
|
|
installer.nested_installer_type
|
|
switches = {
|
|
'Silent': installer.silent_switch,
|
|
'SilentWithProgress': installer.silent_progress_switch,
|
|
'Interactive': installer.interactive_switch,
|
|
'InstallLocation': installer.install_location_switch,
|
|
'Log': installer.log_switch,
|
|
'Upgrade': installer.upgrade_switch,
|
|
'Custom': installer.custom_switch
|
|
}
|
|
nonempty_switches = {k: v for k, v in switches.items() if v}
|
|
if nonempty_switches:
|
|
installer_json['InstallerSwitches'] = nonempty_switches
|
|
installers.append(installer_json)
|
|
version_json = {
|
|
'PackageVersion': version.version,
|
|
'DefaultLocale': {
|
|
'PackageLocale': 'en-us',
|
|
'Publisher': package.publisher,
|
|
'PackageName': package.name,
|
|
'ShortDescription': package.description
|
|
},
|
|
'Installers': installers
|
|
}
|
|
result.setdefault('Versions', []).append(version_json)
|
|
return result |