# # This file is part of FreedomBox. # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU Affero General Public License as # published by the Free Software Foundation, either version 3 of the # License, or (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU Affero General Public License for more details. # # You should have received a copy of the GNU Affero General Public License # along with this program. If not, see . # """ Utility methods for providing client information. """ from django.utils.functional import Promise from enum import Enum class Desktop_OS(Enum): GNU_LINUX = 'gnu-linux' MAC_OS = 'macos' WINDOWS = 'windows' class Mobile_OS(Enum): ANDROID = 'android' IOS = 'ios' class Store(Enum): APP_STORE = 'app-store' F_DROID = 'f-droid' GOOGLE_PLAY = 'google-play' class Package(Enum): DEB = 'deb' HOMEBREW = 'brew' RPM = 'rpm' def enum_values(enum): return [option.value for option in list(enum)] def _check(client, condition): """Check if any of a list of clients satisfies the given condition""" return any(platform for platform in client['platforms'] if condition(platform)) def _client_has_desktop(client): """Filter to find out whether an application has desktop clients""" return _check( client, lambda platform: platform.get('os') in enum_values(Desktop_OS)) def _client_has_mobile(client): """Filter to find out whether an application has mobile clients""" return _check( client, lambda platform: platform.get('os') in enum_values(Mobile_OS)) def _client_has_web(client): """Filter to find out whether an application has web clients""" return _check(client, lambda platform: platform['type'] == 'web') def _client_has_package(client): """Filter to find out whether an application has web clients""" return _check(client, lambda platform: platform['type'] == 'package') def of_type(clients, client_type): """Filter and get clients of a particular type""" filters = { 'mobile': _client_has_mobile, 'desktop': _client_has_desktop, 'web': _client_has_web, 'package': _client_has_package, } return list(filter(filters[client_type], clients)) def store_url(store, package_id): """Return a full App store URL given package id and type of store.""" stores = { 'google-play': 'https://play.google.com/store/apps/details?id={}', 'f-droid': 'https://f-droid.org/packages/{}' } return stores[store].format(package_id) def validate(clients): """Validate the clients' information schema.""" assert isinstance(clients, list) for client in clients: _validate_client(client) return clients def _validate_client(client): """Validate a single client's information schema.""" assert isinstance(client, dict) assert 'name' in client assert isinstance(client['platforms'], list) for platform in client['platforms']: _validate_platform(platform) def _validate_platform(platform): """Validate a single platform's schema.""" assert platform['type'] in ('package', 'download', 'store', 'web') validate_method = globals()['_validate_platform_' + platform['type']] validate_method(platform) def _validate_platform_package(platform): """Validate a platform of type package.""" assert platform['format'] in enum_values(Package) assert isinstance(platform['name'], (str, Promise)) def _validate_platform_download(platform): """Validate a platform of type download.""" assert platform['os'] in enum_values(Desktop_OS) assert isinstance(platform['url'], (str, Promise)) def _validate_platform_store(platform): """Validate a platform of type store.""" assert platform['os'] in enum_values(Mobile_OS) assert platform['store_name'] in enum_values(Store) assert isinstance(platform['url'], (str, Promise)) def _validate_platform_web(platform): """Validate a platform of type web.""" assert isinstance(platform['url'], (str, Promise))