Add ability for editors to set game support

This commit is contained in:
rubenwardy 2022-06-25 01:16:22 +01:00
parent 7f00b77db3
commit 42841896d1
7 changed files with 81 additions and 24 deletions

@ -36,6 +36,7 @@ from app.logic.LogicError import LogicError
from app.logic.packages import do_edit_package from app.logic.packages import do_edit_package
from app.models.packages import PackageProvides from app.models.packages import PackageProvides
from app.tasks.webhooktasks import post_discord_webhook from app.tasks.webhooktasks import post_discord_webhook
from ...logic.game_support import GameSupportResolver
@bp.route("/packages/") @bp.route("/packages/")
@ -626,16 +627,40 @@ def similar(package):
packages_modnames=packages_modnames, similar_topics=similar_topics) packages_modnames=packages_modnames, similar_topics=similar_topics)
@bp.route("/packages/<author>/<name>/support/") class GameSupportForm(FlaskForm):
supported = StringField(lazy_gettext("Supported games (Comma-separated)"), [Optional()])
unsupported = StringField(lazy_gettext("Unsupported games (Comma-separated)"), [Optional()])
submit = SubmitField(lazy_gettext("Save"))
@bp.route("/packages/<author>/<name>/support/", methods=["GET", "POST"])
@login_required @login_required
@is_package_page @is_package_page
def game_support(package): def game_support(package):
if package.type != PackageType.MOD: if package.type != PackageType.MOD:
abort(404) abort(404)
if not (package.checkPerm(current_user, Permission.EDIT_PACKAGE) or can_edit = package.checkPerm(current_user, Permission.EDIT_PACKAGE)
package.checkPerm(current_user, Permission.APPROVE_NEW)): if not (can_edit or package.checkPerm(current_user, Permission.APPROVE_NEW)):
abort(403) abort(403)
return render_template("packages/game_support.html", package=package, form = GameSupportForm() if can_edit else None
if request.method == "GET":
manual_supported_games = package.supported_games.filter_by(confidence=8).all()
form.supported.data = ", ".join([x.game.name for x in manual_supported_games if x.supports])
form.unsupported.data = ", ".join([x.game.name for x in manual_supported_games if not x.supports])
if form and form.validate_on_submit():
resolver = GameSupportResolver()
game_is_supported = []
for game in get_games_from_csv(form.supported.data or ""):
game_is_supported.append((game, True))
for game in get_games_from_csv(form.unsupported.data or ""):
game_is_supported.append((game, False))
resolver.set_supported(package, game_is_supported, 8)
db.session.commit()
return redirect(package.getURL("packages.game_support"))
return render_template("packages/game_support.html", package=package, form=form,
tabs=get_package_tabs(current_user, package), current_tab="game_support") tabs=get_package_tabs(current_user, package), current_tab="game_support")

@ -163,7 +163,7 @@ class GameSupportResolver:
for package in Package.query.filter(Package.type == PackageType.MOD, Package.state != PackageState.DELETED).all(): for package in Package.query.filter(Package.type == PackageType.MOD, Package.state != PackageState.DELETED).all():
retval = self.resolve(package, []) retval = self.resolve(package, [])
for game in retval: for game in retval:
support = PackageGameSupport(package, game, 1) support = PackageGameSupport(package, game, 1, True)
db.session.add(support) db.session.add(support)
""" """
@ -177,10 +177,15 @@ class GameSupportResolver:
db.session.merge(support.game) db.session.merge(support.game)
previous_supported[support.game.id] = support previous_supported[support.game.id] = support
seen_game = {}
for game, supports in game_is_supported: for game, supports in game_is_supported:
if seen_game.get(game.id):
continue
seen_game[game.id] = True
lookup = previous_supported.pop(game.id, None) lookup = previous_supported.pop(game.id, None)
if lookup is None: if lookup is None:
support = PackageGameSupport(package, game, confidence) support = PackageGameSupport(package, game, confidence, supports)
db.session.add(support) db.session.add(support)
elif lookup.confidence <= confidence: elif lookup.confidence <= confidence:
lookup.supports = supports lookup.supports = supports

@ -358,10 +358,11 @@ class PackageGameSupport(db.Model):
__table_args__ = (db.UniqueConstraint("game_id", "package_id", name="_package_game_support_uc"),) __table_args__ = (db.UniqueConstraint("game_id", "package_id", name="_package_game_support_uc"),)
def __init__(self, package, game, confidence): def __init__(self, package, game, confidence, supports):
self.package = package self.package = package
self.game = game self.game = game
self.confidence = confidence self.confidence = confidence
self.supports = supports
class Package(db.Model): class Package(db.Model):

@ -20,11 +20,10 @@ from zipfile import ZipFile
from git import GitCommandError from git import GitCommandError
from git_archive_all import GitArchiver from git_archive_all import GitArchiver
from kombu import uuid from kombu import uuid
from sqlalchemy import or_, and_
from app.models import * from app.models import *
from app.tasks import celery, TaskError from app.tasks import celery, TaskError
from app.utils import randomString, post_bot_message, addSystemNotification, addSystemAuditLog from app.utils import randomString, post_bot_message, addSystemNotification, addSystemAuditLog, get_games_from_csv
from app.utils.git import clone_repo, get_latest_tag, get_latest_commit, get_temp_dir from app.utils.git import clone_repo, get_latest_tag, get_latest_commit, get_temp_dir
from .minetestcheck import build_tree, MinetestCheckError, ContentType from .minetestcheck import build_tree, MinetestCheckError, ContentType
from ..logic.LogicError import LogicError from ..logic.LogicError import LogicError
@ -74,20 +73,6 @@ def getMeta(urlstr, author):
return result return result
def get_games_from_csv(csv: str) -> List[Package]:
retval = []
supported_games_raw = csv.split(",")
for game_name in supported_games_raw:
game_name = game_name.strip()
if game_name.endswith("_game"):
game_name = game_name[:-5]
games = Package.query.filter(and_(Package.state==PackageState.APPROVED, Package.type==PackageType.GAME,
or_(Package.name==game_name, Package.name==game_name + "_game"))).all()
retval.extend(games)
return retval
def postReleaseCheckUpdate(self, release: PackageRelease, path): def postReleaseCheckUpdate(self, release: PackageRelease, path):
try: try:
tree = build_tree(path, expected_type=ContentType[release.package.type.name], tree = build_tree(path, expected_type=ContentType[release.package.type.name],

@ -117,7 +117,7 @@
{% if not label %}{% set label=field.label.text %}{% endif %} {% if not label %}{% set label=field.label.text %}{% endif %}
<div class="checkbox {{ kwargs.pop('class_', '') }}"> <div class="checkbox {{ kwargs.pop('class_', '') }}">
<label> <label>
{{ field(type='checkbox', **kwargs) }} {{ label }} {{ field(type='checkbox', class_="mr-2", **kwargs) }} {{ label }}
</label> </label>
</div> </div>
{%- endmacro %} {%- endmacro %}

@ -7,6 +7,9 @@
{% block content %} {% block content %}
<h2 class="mt-0">{{ self.title() }}</h2> <h2 class="mt-0">{{ self.title() }}</h2>
<p class="alert alert-warning">
This feature is experimental
</p>
<p class="alert alert-info"> <p class="alert alert-info">
<a class="float-right btn btn-sm" href="{{ url_for('flatpage', path='help/game_support') }}"> <a class="float-right btn btn-sm" href="{{ url_for('flatpage', path='help/game_support') }}">
{{ _("Read more") }} {{ _("Read more") }}
@ -40,6 +43,8 @@
<span class="col-5"> <span class="col-5">
{% if support.confidence == 1 %} {% if support.confidence == 1 %}
{{ _("Detected from dependencies") }} {{ _("Detected from dependencies") }}
{% elif support.confidence == 8 %}
{{ _("Added by Editor") }}
{% elif support.confidence == 10 %} {% elif support.confidence == 10 %}
{{ _("mod.conf") }} {{ _("mod.conf") }}
{% else %} {% else %}
@ -61,4 +66,22 @@
</div> </div>
{% endfor %} {% endfor %}
</div> </div>
{% if form and package.checkPerm(current_user, "EDIT_PACKAGE") and current_user not in package.maintainers %}
<h2>
{{ _("Added by Editor") }}
<i class="ml-2 fas fa-user-edit"></i>
</h2>
{% from "macros/forms.html" import render_field, render_checkbox_field, render_submit_field %}
<form method="POST" action="" class="tableform">
{{ form.hidden_tag() }}
{{ render_field(form.supported) }}
{{ render_field(form.unsupported) }}
{{ render_submit_field(form.submit, class_="mt-4 btn btn-primary") }}
</form>
{% endif %}
{% endblock %} {% endblock %}

@ -16,8 +16,12 @@
from functools import wraps from functools import wraps
from typing import List
from flask import abort, redirect, url_for, request from flask import abort, redirect, url_for, request
from flask_login import current_user from flask_login import current_user
from sqlalchemy import or_, and_
from app.models import User, NotificationType, Package, UserRank, Notification, db, AuditSeverity, AuditLogEntry, ThreadReply, Thread, PackageState, PackageType, PackageAlias from app.models import User, NotificationType, Package, UserRank, Notification, db, AuditSeverity, AuditLogEntry, ThreadReply, Thread, PackageState, PackageType, PackageAlias
@ -130,3 +134,17 @@ def post_bot_message(package: Package, title: str, message: str):
title, thread.getViewURL(), thread.package) title, thread.getViewURL(), thread.package)
thread.replies.append(reply) thread.replies.append(reply)
def get_games_from_csv(csv: str) -> List[Package]:
retval = []
supported_games_raw = csv.split(",")
for game_name in supported_games_raw:
game_name = game_name.strip()
if game_name.endswith("_game"):
game_name = game_name[:-5]
games = Package.query.filter(and_(Package.state==PackageState.APPROVED, Package.type==PackageType.GAME,
or_(Package.name==game_name, Package.name==game_name + "_game"))).all()
retval.extend(games)
return retval