From 73a88db42c067344a39871ab7bec4da5d6538725 Mon Sep 17 00:00:00 2001 From: Mariotaku Date: Mon, 17 Apr 2023 16:39:25 +0900 Subject: [PATCH] updating schemas --- content/.gitignore | 4 +- content/schemas/api/PackageInfo.json | 59 +++++++++++++ content/schemas/api/PackageManifest.json | 82 +++++++++++++++++++ content/schemas/api/PackagesPage.json | 16 ++++ content/schemas/packages/Category.json | 32 ++++++++ content/schemas/packages/PackageInfo.json | 71 ++++++++++++++++ ...com.github.k4zmu2a.space-cadet-pinball.yml | 3 +- packages/com.limelight.webos.yml | 2 +- packages/com.retroarch.yml | 3 +- packages/org.chocolate-doom.demo.yml | 3 +- packages/org.jellyfin.webos.yml | 1 + packages/org.mariotaku.ihsplay.yml | 2 +- packages/org.webosbrew.custom-screensaver.yml | 3 +- packages/org.webosbrew.inputhook.yml | 2 +- packages/org.webosbrew.piccap.yml | 2 +- packages/org.webosbrew.streamkatze.yml | 1 + packages/org.webosbrew.vncserver.yml | 2 +- packages/ui30.yml | 2 +- packages/youtube.leanback.v4.yml | 3 +- pelicanconf.py | 4 +- repogen/lintpkg.py | 4 +- repogen/pkg_info.py | 24 +++--- repogen/validators.py | 30 +++++++ requirements.txt | 1 + 24 files changed, 325 insertions(+), 31 deletions(-) create mode 100644 content/schemas/api/PackageInfo.json create mode 100644 content/schemas/api/PackageManifest.json create mode 100644 content/schemas/api/PackagesPage.json create mode 100644 content/schemas/packages/Category.json create mode 100644 content/schemas/packages/PackageInfo.json create mode 100644 repogen/validators.py diff --git a/content/.gitignore b/content/.gitignore index 95b56f0..e65b7f1 100644 --- a/content/.gitignore +++ b/content/.gitignore @@ -1,2 +1,2 @@ -api/ -apps/ \ No newline at end of file +/api +/apps \ No newline at end of file diff --git a/content/schemas/api/PackageInfo.json b/content/schemas/api/PackageInfo.json new file mode 100644 index 0000000..3a000b1 --- /dev/null +++ b/content/schemas/api/PackageInfo.json @@ -0,0 +1,59 @@ +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "$id": "https://webosbrew.org/schema/HomebrewRepository.schema", + "title": "HomebrewPackageInfo", + "description": "Homebrew Package Information", + "type": "object", + "properties": { + "id": { + "type": "string", + "description": "Application ID, e.g., \"com.newco.app.myApp\" . Every application has a unique ID, created from reverse DNS naming conventions." + }, + "title": { + "type": "string", + "description": "The title of the application as it shows in the Launcher and the app window. The application title is unique, set once." + }, + "shortDescription": { + "type": "string", + "description": "Short description for your app." + }, + "fullDescriptionUrl": { + "type": "string", + "description": "URL to full description page in HTML. Client may apply appropriate stylesheet to it." + }, + "iconUri": { + "type": "string", + "description": "Image displayed for your app. This is a URL to an image, or data: encoded URI" + }, + "manifestUrl": { + "type": "string", + "description": "Link to manifest, should be pointed to an URL can always provide latest version" + }, + "manifest": { + "$ref": "PackageManifest.json" + } + }, + "allOf": [ + { + "required": [ + "id", + "title", + "iconUri" + ] + }, + { + "oneOf": [ + { + "required": [ + "manifestUrl" + ] + }, + { + "required": [ + "manifest" + ] + } + ] + } + ] +} \ No newline at end of file diff --git a/content/schemas/api/PackageManifest.json b/content/schemas/api/PackageManifest.json new file mode 100644 index 0000000..091eca0 --- /dev/null +++ b/content/schemas/api/PackageManifest.json @@ -0,0 +1,82 @@ +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "$id": "https://repo.webosbrew.org/schemas/api/PackageManifest.schema", + "title": "PackageManifest", + "description": "Package manifest for webOS homebrew package", + "type": "object", + "properties": { + "id": { + "type": "string", + "description": "Application ID, e.g., \"com.newco.app.myApp\" . Every application has a unique ID, created from reverse DNS naming conventions." + }, + "version": { + "type": "string", + "description": "The application version number, in the dot-notation format, e.g., 3.0.2500" + }, + "type": { + "type": "string", + "enum": [ + "web", + "stub", + "native", + "native_builtin", + "native_appshell", + "qml" + ], + "description": "Identifies the application type" + }, + "title": { + "type": "string", + "description": "The title of the application as it shows in the Launcher and the app window. The application title is unique, set once." + }, + "appDescription": { + "type": "string", + "description": "The description of the application shown in the application details page." + }, + "iconUri": { + "type": "string", + "description": "Image displayed for your app. This is a URL to an image, or data: encoded URI" + }, + "sourceUrl": { + "type": "string", + "description": "Link to source code repository, or project homepage etc" + }, + "rootRequired": { + "type": [ + "boolean", + "string" + ], + "enum": [ + true, + false, + "optional" + ], + "description": "Whether this app require a rooted/jailbroken TV to work, or optional." + }, + "ipkUrl": { + "type": "string", + "description": "URL to package file" + }, + "ipkHash": { + "type": "object", + "properties": { + "sha256": { + "type": "string", + "description": "Hex encoded hash" + } + }, + "minProperties": 1, + "additionalProperties": false, + "description": "URL to package file" + } + }, + "required": [ + "id", + "version", + "type", + "title", + "iconUri", + "ipkUrl", + "ipkHash" + ] +} \ No newline at end of file diff --git a/content/schemas/api/PackagesPage.json b/content/schemas/api/PackagesPage.json new file mode 100644 index 0000000..a4db9ba --- /dev/null +++ b/content/schemas/api/PackagesPage.json @@ -0,0 +1,16 @@ +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "$id": "https://repo.webosbrew.org/schemas/PackagesPage.json", + "title": "HomebrewRepository", + "description": "Repository information for webOS homebrew packages", + "type": "object", + "properties": { + "packages": { + "type": "array", + "items": { + "$ref": "PackageInfo.json" + } + } + }, + "additionalProperties": false +} \ No newline at end of file diff --git a/content/schemas/packages/Category.json b/content/schemas/packages/Category.json new file mode 100644 index 0000000..d46d295 --- /dev/null +++ b/content/schemas/packages/Category.json @@ -0,0 +1,32 @@ +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "$id": "https://repo.webosbrew.org/schemas/packages/Category.json", + "title": "PackageCategory", + "type": "string", + "anyOf": [ + { + "const": "multimedia", + "description": "Application for presenting, creating, or processing multimedia (audio/video)" + }, + { + "const": "game", + "description": "A game" + }, + { + "const": "system", + "description": "System application, \"System Tools\" such as say a log viewer or network monitor" + }, + { + "const": "utility", + "description": "Small utility application, \"Accessories\"" + }, + { + "const": "screensaver", + "description": "A screen saver" + }, + { + "const": "launcher", + "description": "A launcher (home screen) alternative" + } + ] +} \ No newline at end of file diff --git a/content/schemas/packages/PackageInfo.json b/content/schemas/packages/PackageInfo.json new file mode 100644 index 0000000..22450bb --- /dev/null +++ b/content/schemas/packages/PackageInfo.json @@ -0,0 +1,71 @@ +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "$id": "https://repo.webosbrew.org/schemas/packages/PackageInfo.json", + "title": "PackageInfo", + "type": "object", + "properties": { + "title": { + "type": "string", + "maxLength": 30, + "description": "The title of the application as it shows in the Launcher and the app window. The application title is unique, set once." + }, + "iconUri": { + "type": "string", + "description": "Image displayed for your app. This is a URL to an image, or data: encoded URI" + }, + "manifestUrl": { + "type": "string", + "description": "Link to manifest, should be pointed to an URL can always provide latest version" + }, + "manifestUrlBeta": { + "type": "string", + "description": "Link to manifest, should be pointed to an URL can always provide latest version" + }, + "category": { + "$ref": "Category.json" + }, + "description": { + "type": "string", + "description": "Markdown/HTML formatted description" + }, + "detailIconUri": { + "type": "string", + "description": "Icon uri for application detail page, in higher resolution" + }, + "pool": { + "type": "string", + "anyOf": [ + { + "const": "main", + "description": "Main pool - Must be open-source" + }, + { + "const": "non-free", + "description": "Non-free pool - Can be closed-source" + } + ] + }, + "funding": { + "type": "object", + "description": "Funding information", + "properties": { + "github": { + "type": "array", + "items": { + "type": "string", + "description": "GitHub username" + } + } + } + } + }, + "required": [ + "title", + "iconUri", + "manifestUrl", + "category", + "pool", + "description" + ], + "additionalProperties": false +} \ No newline at end of file diff --git a/packages/com.github.k4zmu2a.space-cadet-pinball.yml b/packages/com.github.k4zmu2a.space-cadet-pinball.yml index 4da3ddf..53f4289 100644 --- a/packages/com.github.k4zmu2a.space-cadet-pinball.yml +++ b/packages/com.github.k4zmu2a.space-cadet-pinball.yml @@ -1,7 +1,8 @@ title: 3D Pinball – Space Cadet iconUri: https://raw.githubusercontent.com/webosbrew/SpaceCadetPinball/webos/webos/icon.png manifestUrl: https://github.com/webosbrew/SpaceCadetPinball/releases/latest/download/webosbrew.manifest.json -category: games +category: game +pool: main description: | ## Summary diff --git a/packages/com.limelight.webos.yml b/packages/com.limelight.webos.yml index e94605d..22918c1 100644 --- a/packages/com.limelight.webos.yml +++ b/packages/com.limelight.webos.yml @@ -2,7 +2,7 @@ title: Moonlight iconUri: https://raw.githubusercontent.com/mariotaku/moonlight-tv/main/deploy/webos/icon_large.png detailIconUri: https://raw.githubusercontent.com/mariotaku/moonlight-tv/main/res/moonlight_320.png manifestUrl: https://github.com/mariotaku/moonlight-tv/releases/latest/download/com.limelight.webos.manifest.json -category: games +category: game pool: main description: | Moonlight TV is a community version of [Moonlight GameStream Client](https://moonlight-stream.org/), made for large diff --git a/packages/com.retroarch.yml b/packages/com.retroarch.yml index dc7e029..d8ce416 100644 --- a/packages/com.retroarch.yml +++ b/packages/com.retroarch.yml @@ -1,7 +1,8 @@ title: RetroArch iconUri: https://raw.githubusercontent.com/webosbrew/RetroArch/webos-tv-support/webos/icon160.png manifestUrl: https://github.com/webosbrew/RetroArch/releases/latest/download/com.retroarch.manifest.json -category: games +category: game +pool: main description: | RetroArch is the reference frontend for the libretro API. Popular examples of implementations for this API includes video game system emulators and game engines as well as diff --git a/packages/org.chocolate-doom.demo.yml b/packages/org.chocolate-doom.demo.yml index 7e1b292..eee4ad3 100644 --- a/packages/org.chocolate-doom.demo.yml +++ b/packages/org.chocolate-doom.demo.yml @@ -1,7 +1,8 @@ title: Chocolate Doom Demo iconUri: https://raw.githubusercontent.com/webosbrew/chocolate-doom/webos-tv/data/doom.png manifestUrl: https://github.com/webosbrew/chocolate-doom/releases/latest/download/org.chocolate-doom.demo.manifest.json -category: games +category: game +pool: main description: | ** This Technical Demo Contains [Shareware version of Doom](https://doomwiki.org/wiki/DOOM1.WAD) ** diff --git a/packages/org.jellyfin.webos.yml b/packages/org.jellyfin.webos.yml index 436aaef..169d98b 100644 --- a/packages/org.jellyfin.webos.yml +++ b/packages/org.jellyfin.webos.yml @@ -2,5 +2,6 @@ title: Jellyfin iconUri: https://raw.githubusercontent.com/jellyfin/jellyfin-webos/master/frontend/assets/icon-130.png manifestUrl: https://github.com/jellyfin/jellyfin-webos/releases/latest/download/org.jellyfin.webos.manifest.json category: multimedia +pool: main description: | Wrapper around [Jellyfin](https://jellyfin.org) Web project diff --git a/packages/org.mariotaku.ihsplay.yml b/packages/org.mariotaku.ihsplay.yml index 93ee1da..27ededa 100644 --- a/packages/org.mariotaku.ihsplay.yml +++ b/packages/org.mariotaku.ihsplay.yml @@ -2,7 +2,7 @@ title: IHSplay - App for Steam Link iconUri: https://raw.githubusercontent.com/mariotaku/ihsplay/master/deploy/webos/largeIcon.png detailIconUri: https://raw.githubusercontent.com/mariotaku/ihsplay/master/deploy/webos/largeIcon.png manifestUrl: https://github.com/mariotaku/ihsplay/releases/latest/download/org.mariotaku.ihsplay.manifest.json -category: games +category: game pool: main description: | # Early Beta! diff --git a/packages/org.webosbrew.custom-screensaver.yml b/packages/org.webosbrew.custom-screensaver.yml index 01ef387..00218ea 100644 --- a/packages/org.webosbrew.custom-screensaver.yml +++ b/packages/org.webosbrew.custom-screensaver.yml @@ -1,7 +1,8 @@ title: Custom Screensaver iconUri: https://raw.githubusercontent.com/webosbrew/custom-screensaver/main/assets/icon130.png manifestUrl: https://github.com/webosbrew/custom-screensaver/releases/latest/download/org.webosbrew.custom-screensaver.manifest.json -category: entertainment +category: screensaver +pool: main description: | Probably the only custom screensaver you'll ever need on webOS TV. diff --git a/packages/org.webosbrew.inputhook.yml b/packages/org.webosbrew.inputhook.yml index bde90f0..046069f 100644 --- a/packages/org.webosbrew.inputhook.yml +++ b/packages/org.webosbrew.inputhook.yml @@ -1,7 +1,7 @@ title: LG Input Hook iconUri: https://raw.githubusercontent.com/Simon34545/lginputhook/main/assets/largeIcon.png manifestUrl: https://github.com/Simon34545/lginputhook/releases/latest/download/org.webosbrew.inputhook.manifest.json -category: tools +category: utility pool: main description: | # LG Input Hook diff --git a/packages/org.webosbrew.piccap.yml b/packages/org.webosbrew.piccap.yml index 1ca972e..2f9254a 100644 --- a/packages/org.webosbrew.piccap.yml +++ b/packages/org.webosbrew.piccap.yml @@ -1,7 +1,7 @@ title: PicCap - Hyperion Sender App iconUri: https://raw.githubusercontent.com/TBSniller/piccap/main/frontend/assets/logo_big.png manifestUrl: https://github.com/TBSniller/piccap/releases/latest/download/org.webosbrew.piccap.manifest.json -category: tools +category: utility pool: main description: | ## PicCap - Hyperion Sender App diff --git a/packages/org.webosbrew.streamkatze.yml b/packages/org.webosbrew.streamkatze.yml index 86e7315..418dc50 100644 --- a/packages/org.webosbrew.streamkatze.yml +++ b/packages/org.webosbrew.streamkatze.yml @@ -2,6 +2,7 @@ title: streamkatze iconUri: https://raw.githubusercontent.com/informatic/streamkatze/main/assets/icon130.png manifestUrl: https://github.com/informatic/streamkatze/releases/latest/download/org.webosbrew.streamkatze.manifest.json category: multimedia +pool: main description: | Experimental webOS [streaming.media.ccc.de](https://streaming.media.ccc.de) live stream player. diff --git a/packages/org.webosbrew.vncserver.yml b/packages/org.webosbrew.vncserver.yml index 3ff6877..f9886e5 100644 --- a/packages/org.webosbrew.vncserver.yml +++ b/packages/org.webosbrew.vncserver.yml @@ -1,7 +1,7 @@ title: VNCServer iconUri: https://github.com/Informatic/webos-vncserver/raw/main/assets/largeIcon.png manifestUrl: https://github.com/Informatic/webos-vncserver/releases/latest/download/org.webosbrew.vncserver.manifest.json -category: tools +category: utility pool: main description: | Minimal webOS VNC server. Supports mouse and keyboard/remote control. diff --git a/packages/ui30.yml b/packages/ui30.yml index a93caf2..a9b4426 100644 --- a/packages/ui30.yml +++ b/packages/ui30.yml @@ -1,7 +1,7 @@ title: Piccap On/Off Remote iconUri: https://raw.githubusercontent.com/Bahoue/OnOff-Remote/master/app/largeIcon.png manifestUrl: https://github.com/Bahoue/OnOff-Remote/releases/latest/download/ui30.manifest.json -category: multimedia +category: utility pool: main description: | Binds the Rakuten button on the remote control to the action of pausing/resuming PicCap. diff --git a/packages/youtube.leanback.v4.yml b/packages/youtube.leanback.v4.yml index 5d0ef1d..8fc0807 100644 --- a/packages/youtube.leanback.v4.yml +++ b/packages/youtube.leanback.v4.yml @@ -1,7 +1,8 @@ title: YouTube AdFree iconUri: https://raw.githubusercontent.com/webosbrew/youtube-webos/main/assets/largeIcon.png manifestUrl: https://github.com/webosbrew/youtube-webos/releases/latest/download/youtube.leanback.v4.manifest.json -category: entertainment +category: multimedia +pool: main description: | **BE SURE TO UNINSTALL THE OFFICIAL YOUTUBE TV APP BEFORE INSTALLING** diff --git a/pelicanconf.py b/pelicanconf.py index cbb858d..ffb39ca 100644 --- a/pelicanconf.py +++ b/pelicanconf.py @@ -23,13 +23,13 @@ PATH = 'content' -STATIC_PATHS = ['extra/CNAME', 'extra/favicon.ico'] +STATIC_PATHS = ['extra/CNAME', 'extra/favicon.ico', 'schemas'] ARTICLE_EXCLUDES = ['api'] PAGE_PATHS = ['pages', 'apps', '../packages'] EXTRA_PATH_METADATA = { 'extra/CNAME': {'path': 'CNAME'}, - 'extra/favicon.ico': {'path': 'favicon.ico'} + 'extra/favicon.ico': {'path': 'favicon.ico'}, } MARKDOWN = { diff --git a/repogen/lintpkg.py b/repogen/lintpkg.py index d507caf..7822a11 100644 --- a/repogen/lintpkg.py +++ b/repogen/lintpkg.py @@ -35,9 +35,7 @@ def lint(self, info: PackageInfo) -> [str]: errors: [str] = [] # Pool property - if info.get('nopool', False): - errors.append('pool property is required (`main` or `non-free`)') - elif info['pool'] not in ['main', 'non-free']: + if info['pool'] not in ['main', 'non-free']: errors.append('pool property must be `main` or `non-free`') # Process icon diff --git a/repogen/pkg_info.py b/repogen/pkg_info.py index 68dd1a1..d71f031 100644 --- a/repogen/pkg_info.py +++ b/repogen/pkg_info.py @@ -1,15 +1,19 @@ +import json import locale import sys from datetime import datetime from pathlib import Path -from typing import TypedDict, Optional, List, NotRequired +from typing import TypedDict, Optional, List, NotRequired, Type import nh3 +from repogen import validators from repogen.common import url_fixup from repogen.pkg_manifest import obtain_manifest, PackageManifest from repogen.pkg_registery import PackageRegistry, parse_yml_package, load_py_package +import jsonschema + locale.setlocale(locale.LC_TIME, '') @@ -24,7 +28,6 @@ class PackageInfo(TypedDict): detailIconUri: NotRequired[str] funding: NotRequired[dict] pool: str - nopool: NotRequired[bool] manifest: PackageManifest manifestBeta: NotRequired[PackageManifest] lastmodified: datetime @@ -41,8 +44,8 @@ def from_package_info_file(info_path: Path, offline=False) -> Optional[PackageIn pkgid, content = load_py_package(info_path) else: raise ValueError(f'Unrecognized info format {extension}') - if not ('title' in content and 'iconUri' in content and 'manifestUrl' in content): - return None + validator = validators.for_schema('packages/PackageInfo.json') + validator.validate(content) return from_package_info(pkgid, content, offline) @@ -81,15 +84,10 @@ def from_package_info(pkgid: str, content: PackageRegistry, offline=False): pkginfo['detailIconUri'] = content['detailIconUri'] if 'funding' in content: pkginfo['funding'] = content['funding'] - if 'pool' in content: - try: - pkginfo['pool'] = valid_pool(content['pool']) - except ValueError: - return None - else: - # This is for compatibility, new submissions requires this field - pkginfo['pool'] = 'main' - pkginfo['nopool'] = True + try: + pkginfo['pool'] = valid_pool(content['pool']) + except ValueError: + return None manifest, lastmodified_r = obtain_manifest(pkgid, 'release', manifest_url, offline) if manifest: pkginfo['manifest'] = manifest diff --git a/repogen/validators.py b/repogen/validators.py new file mode 100644 index 0000000..2584bed --- /dev/null +++ b/repogen/validators.py @@ -0,0 +1,30 @@ +import json +import urllib.parse +from pathlib import Path +from typing import Any, Type + +import jsonschema +from jsonschema.protocols import Validator +from jsonschema.validators import RefResolver + + +def schemas_dir() -> Path: + return Path('content/schemas').resolve() + + +assert Path(__file__, '../../content/schemas').samefile(schemas_dir()) + + +def for_schema(rel_path: str) -> Validator: + def schema_handler(uri: str) -> Any: + with schemas_dir().joinpath(urllib.parse.urlparse(uri).path.removeprefix('/schemas/')).open() as rf: + return json.load(rf) + + schema_path = schemas_dir().joinpath(rel_path) + with schema_path.open() as f: + schema = json.load(f) + resolver = RefResolver(base_uri=schema_path.as_uri(), referrer=schema, handlers={'https': schema_handler}) + validator_cls: Type[jsonschema.Validator] = jsonschema.validators.validator_for(schema) + validator = validator_cls(resolver=resolver, schema=schema) + jsonschema.validate(schema, validator_cls.META_SCHEMA) + return validator diff --git a/requirements.txt b/requirements.txt index e028e77..90492b8 100644 --- a/requirements.txt +++ b/requirements.txt @@ -12,5 +12,6 @@ cssmin~=0.2.0 livereload~=2.6.3 invoke~=2.0.0 ar~=0.3.2 +jsonschema~=4.17.3 git+https://github.com/Kronuz/pyScss.git@60414f5d573315a8458b5fbcdf69e5c648c44a9a#egg=pyscss git+https://github.com/webosbrew/pelican-theme-webosbrew.git@v1.0.4#egg=pelican-theme-webosbrew \ No newline at end of file