mirror of
https://github.com/minetest/contentdb.git
synced 2025-01-03 11:47:28 +01:00
Add option to filter packages by license
This commit is contained in:
parent
57ed2fc416
commit
380f009529
@ -39,7 +39,7 @@ def is_api_authd(f):
|
|||||||
if token is None:
|
if token is None:
|
||||||
error(403, "Unknown API token")
|
error(403, "Unknown API token")
|
||||||
else:
|
else:
|
||||||
abort(403, "Unsupported authentication method")
|
error(403, "Unsupported authentication method")
|
||||||
|
|
||||||
return f(token=token, *args, **kwargs)
|
return f(token=token, *args, **kwargs)
|
||||||
|
|
||||||
|
@ -187,22 +187,29 @@ Example:
|
|||||||
|
|
||||||
/api/packages/?type=mod&type=game&q=mobs+fun&hide=nonfree&hide=gore
|
/api/packages/?type=mod&type=game&q=mobs+fun&hide=nonfree&hide=gore
|
||||||
|
|
||||||
Supported query parameters:
|
Filter query parameters:
|
||||||
|
|
||||||
* `type`: Package types (`mod`, `game`, `txp`).
|
* `type`: Filter by package type (`mod`, `game`, `txp`). Multiple types are OR-ed together.
|
||||||
* `q`: Query string.
|
* `q`: Query string.
|
||||||
* `author`: Filter by author.
|
* `author`: Filter by author.
|
||||||
* `tag`: Filter by tags.
|
* `tag`: Filter by tags. Multiple tags are AND-ed together.
|
||||||
* `flag`: Filter to show packages with [Content Flags](/help/content_flags/).
|
* `flag`: Filter to show packages with [Content Flags](/help/content_flags/).
|
||||||
|
* `hide`: Hide content based on [Content Flags](/help/content_flags/).
|
||||||
|
* `license`: Filter by [license name](#licenses). Multiple licenses are OR-ed together, ie: `&license=MIT&license=LGPL-2.1-only`
|
||||||
* `game`: Filter by [Game Support](/help/game_support/), ex: `Wuzzy/mineclone2`. (experimental, doesn't show items that support every game currently).
|
* `game`: Filter by [Game Support](/help/game_support/), ex: `Wuzzy/mineclone2`. (experimental, doesn't show items that support every game currently).
|
||||||
* `lang`: Filter by translation support, eg: `en`/`de`/`ja`/`zh_TW`.
|
* `lang`: Filter by translation support, eg: `en`/`de`/`ja`/`zh_TW`.
|
||||||
* `random`: When present, enable random ordering and ignore `sort`.
|
|
||||||
* `limit`: Return at most `limit` packages.
|
|
||||||
* `hide`: Hide content based on [Content Flags](/help/content_flags/).
|
|
||||||
* `sort`: Sort by (`name`, `title`, `score`, `reviews`, `downloads`, `created_at`, `approved_at`, `last_release`).
|
|
||||||
* `order`: Sort ascending (`asc`) or descending (`desc`).
|
|
||||||
* `protocol_version`: Only show packages supported by this Minetest protocol version.
|
* `protocol_version`: Only show packages supported by this Minetest protocol version.
|
||||||
* `engine_version`: Only show packages supported by this Minetest engine version, eg: `5.3.0`.
|
* `engine_version`: Only show packages supported by this Minetest engine version, eg: `5.3.0`.
|
||||||
|
|
||||||
|
Sorting query parameters:
|
||||||
|
|
||||||
|
* `sort`: Sort by (`name`, `title`, `score`, `reviews`, `downloads`, `created_at`, `approved_at`, `last_release`).
|
||||||
|
* `order`: Sort ascending (`asc`) or descending (`desc`).
|
||||||
|
* `random`: When present, enable random ordering and ignore `sort`.
|
||||||
|
|
||||||
|
Format query parameters:
|
||||||
|
|
||||||
|
* `limit`: Return at most `limit` packages.
|
||||||
* `fmt`: How the response is formatted.
|
* `fmt`: How the response is formatted.
|
||||||
* `keys`: author/name only.
|
* `keys`: author/name only.
|
||||||
* `short`: stuff needed for the Minetest client.
|
* `short`: stuff needed for the Minetest client.
|
||||||
|
@ -961,7 +961,7 @@ class MinetestRelease(db.Model):
|
|||||||
}
|
}
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def get(cls, version, protocol_num):
|
def get(cls, version: typing.Optional[str], protocol_num: typing.Optional[str]) -> typing.Optional["MinetestRelease"]:
|
||||||
if version:
|
if version:
|
||||||
parts = version.strip().split(".")
|
parts = version.strip().split(".")
|
||||||
if len(parts) >= 2:
|
if len(parts) >= 2:
|
||||||
|
@ -14,8 +14,8 @@
|
|||||||
# You should have received a copy of the GNU Affero General Public License
|
# You should have received a copy of the GNU Affero General Public License
|
||||||
# along with this program. If not, see <https://www.gnu.org/licenses/>.
|
# along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
from typing import Optional
|
from typing import Optional, List
|
||||||
from flask import abort, current_app, request
|
from flask import abort, current_app, request, make_response
|
||||||
from flask_babel import lazy_gettext, gettext, get_locale
|
from flask_babel import lazy_gettext, gettext, get_locale
|
||||||
from sqlalchemy import or_
|
from sqlalchemy import or_
|
||||||
from sqlalchemy.orm import subqueryload
|
from sqlalchemy.orm import subqueryload
|
||||||
@ -28,10 +28,27 @@ from .utils import is_yes, get_int_or_abort
|
|||||||
|
|
||||||
|
|
||||||
class QueryBuilder:
|
class QueryBuilder:
|
||||||
|
limit: Optional[int]
|
||||||
lang: str = "en"
|
lang: str = "en"
|
||||||
types = None
|
types: List[PackageType]
|
||||||
search = None
|
search: Optional[str] = None
|
||||||
only_approved = True
|
only_approved: bool = True
|
||||||
|
licenses: List[License]
|
||||||
|
tags: List[Tag]
|
||||||
|
game: Optional[Package]
|
||||||
|
author: Optional[str]
|
||||||
|
random: bool
|
||||||
|
lucky: bool
|
||||||
|
order_dir: str
|
||||||
|
order_by: Optional[str]
|
||||||
|
flags: set[str]
|
||||||
|
hide_flags: set[str]
|
||||||
|
hide_deprecated: bool
|
||||||
|
hide_wip: bool
|
||||||
|
hide_nonfree: bool
|
||||||
|
show_added: bool
|
||||||
|
version: Optional[MinetestRelease]
|
||||||
|
has_lang: Optional[str]
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def title(self):
|
def title(self):
|
||||||
@ -62,7 +79,7 @@ class QueryBuilder:
|
|||||||
return (self.search is not None or len(self.tags) > 1 or len(self.types) > 1 or len(self.hide_flags) > 0 or
|
return (self.search is not None or len(self.tags) > 1 or len(self.types) > 1 or len(self.hide_flags) > 0 or
|
||||||
self.random or self.lucky or self.author or self.version or self.game)
|
self.random or self.lucky or self.author or self.version or self.game)
|
||||||
|
|
||||||
def __init__(self, args, cookies: bool = False, lang: Optional[str] = None):
|
def __init__(self, args, cookies: bool = False, lang: Optional[str] = None, emit_http_errors: bool = True):
|
||||||
if lang is None:
|
if lang is None:
|
||||||
locale = get_locale()
|
locale = get_locale()
|
||||||
if locale:
|
if locale:
|
||||||
@ -86,6 +103,11 @@ class QueryBuilder:
|
|||||||
# Show flags
|
# Show flags
|
||||||
self.flags = set(args.getlist("flag"))
|
self.flags = set(args.getlist("flag"))
|
||||||
|
|
||||||
|
# License
|
||||||
|
self.licenses = [License.query.filter(func.lower(License.name) == name).first() for name in args.getlist("license")]
|
||||||
|
if emit_http_errors and any(map(lambda x: x is None, self.licenses)):
|
||||||
|
abort(make_response("Unknown license"), 400)
|
||||||
|
|
||||||
self.types = types
|
self.types = types
|
||||||
self.tags = tags
|
self.tags = tags
|
||||||
|
|
||||||
@ -234,6 +256,11 @@ class QueryBuilder:
|
|||||||
if warning:
|
if warning:
|
||||||
query = query.filter(Package.content_warnings.any(ContentWarning.id == warning.id))
|
query = query.filter(Package.content_warnings.any(ContentWarning.id == warning.id))
|
||||||
|
|
||||||
|
licenses = [Package.license_id == license.id for license in self.licenses if license is not None]
|
||||||
|
licenses.extend([Package.media_license_id == license.id for license in self.licenses if license is not None])
|
||||||
|
if len(licenses) > 0:
|
||||||
|
query = query.filter(or_(*licenses))
|
||||||
|
|
||||||
if self.hide_nonfree:
|
if self.hide_nonfree:
|
||||||
query = query.filter(Package.license.has(License.is_foss == True))
|
query = query.filter(Package.license.has(License.is_foss == True))
|
||||||
query = query.filter(Package.media_license.has(License.is_foss == True))
|
query = query.filter(Package.media_license.has(License.is_foss == True))
|
||||||
|
@ -115,7 +115,7 @@ def url_set_query(**kwargs):
|
|||||||
return url_for(request.endpoint, **dargs)
|
return url_for(request.endpoint, **dargs)
|
||||||
|
|
||||||
|
|
||||||
def get_int_or_abort(v, default=None):
|
def get_int_or_abort(v, default=None) -> typing.Optional[int]:
|
||||||
if v is None:
|
if v is None:
|
||||||
return default
|
return default
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user