mirror of
https://github.com/minetest/contentdb.git
synced 2024-11-08 08:33:45 +01:00
Add option to disable game support detection
This commit is contained in:
parent
42841896d1
commit
d9e65f7c3a
@ -328,7 +328,7 @@ def update_screenshot_sizes():
|
||||
|
||||
@action("Detect game support")
|
||||
def detect_game_support():
|
||||
resolver = GameSupportResolver()
|
||||
resolver = GameSupportResolver(db.session)
|
||||
resolver.update_all()
|
||||
db.session.commit()
|
||||
|
||||
|
@ -17,11 +17,11 @@ import typing
|
||||
from urllib.parse import quote as urlescape
|
||||
|
||||
from flask import render_template
|
||||
from flask_babel import lazy_gettext, gettext
|
||||
from celery import uuid
|
||||
from flask_wtf import FlaskForm
|
||||
from flask_login import login_required
|
||||
from jinja2 import Markup
|
||||
from sqlalchemy import or_, func, and_
|
||||
from sqlalchemy import func
|
||||
from sqlalchemy.orm import joinedload, subqueryload
|
||||
from wtforms import *
|
||||
from wtforms_sqlalchemy.fields import QuerySelectField, QuerySelectMultipleField
|
||||
@ -29,7 +29,7 @@ from wtforms.validators import *
|
||||
|
||||
from app.querybuilder import QueryBuilder
|
||||
from app.rediscache import has_key, set_key
|
||||
from app.tasks.importtasks import importRepoScreenshot
|
||||
from app.tasks.importtasks import importRepoScreenshot, checkZipRelease
|
||||
from app.utils import *
|
||||
from . import bp, get_package_tabs
|
||||
from app.logic.LogicError import LogicError
|
||||
@ -628,6 +628,7 @@ def similar(package):
|
||||
|
||||
|
||||
class GameSupportForm(FlaskForm):
|
||||
enable_support_detection = BooleanField(lazy_gettext("Enable support detection based on dependencies"))
|
||||
supported = StringField(lazy_gettext("Supported games (Comma-separated)"), [Optional()])
|
||||
unsupported = StringField(lazy_gettext("Unsupported games (Comma-separated)"), [Optional()])
|
||||
submit = SubmitField(lazy_gettext("Save"))
|
||||
@ -646,21 +647,38 @@ def game_support(package):
|
||||
|
||||
form = GameSupportForm() if can_edit else None
|
||||
if request.method == "GET":
|
||||
form.enable_support_detection.data = package.enable_game_support_detection
|
||||
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()
|
||||
resolver = GameSupportResolver(db.session)
|
||||
|
||||
return redirect(package.getURL("packages.game_support"))
|
||||
game_is_supported = {}
|
||||
for game in get_games_from_csv(db.session, form.supported.data or ""):
|
||||
game_is_supported[game.id] = True
|
||||
for game in get_games_from_csv(db.session, form.unsupported.data or ""):
|
||||
game_is_supported[game.id] = False
|
||||
resolver.set_supported(package, game_is_supported, 8)
|
||||
|
||||
next_url = package.getURL("packages.game_support")
|
||||
|
||||
if form.enable_support_detection.data != package.enable_game_support_detection:
|
||||
package.enable_game_support_detection = form.enable_support_detection.data
|
||||
if package.enable_game_support_detection:
|
||||
db.session.commit()
|
||||
|
||||
release = package.releases.first()
|
||||
if release:
|
||||
task_id = uuid()
|
||||
checkZipRelease.apply_async((release.id, release.file_path), task_id=task_id)
|
||||
next_url = url_for("tasks.check", id=task_id, r=next_url)
|
||||
else:
|
||||
package.supported_games.filter_by(confidence=1).delete()
|
||||
db.session.commit()
|
||||
|
||||
return redirect(next_url)
|
||||
|
||||
return render_template("packages/game_support.html", package=package, form=form,
|
||||
tabs=get_package_tabs(current_user, package), current_tab="game_support")
|
||||
|
@ -16,11 +16,12 @@
|
||||
|
||||
|
||||
import sys
|
||||
from typing import List, Dict, Optional, Iterable
|
||||
|
||||
from typing import List, Dict, Optional, Iterator, Iterable, Tuple
|
||||
import sqlalchemy.orm
|
||||
|
||||
from app.logic.LogicError import LogicError
|
||||
from app.models import Package, MetaPackage, PackageType, PackageState, PackageGameSupport, db
|
||||
from app.models import Package, MetaPackage, PackageType, PackageState, PackageGameSupport
|
||||
|
||||
"""
|
||||
get_game_support(package):
|
||||
@ -82,11 +83,15 @@ class PackageSet:
|
||||
|
||||
|
||||
class GameSupportResolver:
|
||||
session: sqlalchemy.orm.Session
|
||||
checked_packages = set()
|
||||
checked_metapackages = set()
|
||||
resolved_packages: Dict[str, PackageSet] = {}
|
||||
resolved_metapackages: Dict[str, PackageSet] = {}
|
||||
|
||||
def __init__(self, session):
|
||||
self.session = session
|
||||
|
||||
def resolve_for_meta_package(self, meta: MetaPackage, history: List[str]) -> PackageSet:
|
||||
print(f"Resolving for {meta.name}", file=sys.stderr)
|
||||
|
||||
@ -120,8 +125,6 @@ class GameSupportResolver:
|
||||
return retval
|
||||
|
||||
def resolve(self, package: Package, history: List[str]) -> PackageSet:
|
||||
db.session.merge(package)
|
||||
|
||||
key = package.getId()
|
||||
print(f"Resolving for {key}", file=sys.stderr)
|
||||
|
||||
@ -160,47 +163,41 @@ class GameSupportResolver:
|
||||
return retval
|
||||
|
||||
def update_all(self) -> None:
|
||||
for package in Package.query.filter(Package.type == PackageType.MOD, Package.state != PackageState.DELETED).all():
|
||||
for package in self.session.query(Package).filter(Package.type == PackageType.MOD, Package.state != PackageState.DELETED).all():
|
||||
retval = self.resolve(package, [])
|
||||
for game in retval:
|
||||
support = PackageGameSupport(package, game, 1, True)
|
||||
db.session.add(support)
|
||||
self.session.add(support)
|
||||
|
||||
"""
|
||||
Update game supported package on a package, given the confidence.
|
||||
|
||||
Higher confidences outweigh lower ones.
|
||||
"""
|
||||
def set_supported(self, package: Package, game_is_supported: List[Tuple[Package, bool]], confidence: int):
|
||||
def set_supported(self, package: Package, game_is_supported: Dict[int, bool], confidence: int):
|
||||
previous_supported: Dict[int, PackageGameSupport] = {}
|
||||
for support in package.supported_games.all():
|
||||
db.session.merge(support.game)
|
||||
previous_supported[support.game.id] = support
|
||||
|
||||
seen_game = {}
|
||||
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)
|
||||
for game_id, supports in game_is_supported.items():
|
||||
game = self.session.query(Package).get(game_id)
|
||||
lookup = previous_supported.pop(game_id, None)
|
||||
if lookup is None:
|
||||
support = PackageGameSupport(package, game, confidence, supports)
|
||||
db.session.add(support)
|
||||
self.session.add(support)
|
||||
elif lookup.confidence <= confidence:
|
||||
lookup.supports = supports
|
||||
lookup.confidence = confidence
|
||||
db.session.merge(lookup)
|
||||
|
||||
for game, support in previous_supported.items():
|
||||
if support.confidence == confidence:
|
||||
db.session.delete(support)
|
||||
self.session.delete(support)
|
||||
|
||||
def update(self, package: Package) -> None:
|
||||
retval = self.resolve(package, [])
|
||||
|
||||
game_is_supported = []
|
||||
for game in retval:
|
||||
game_is_supported.append((game, True))
|
||||
game_is_supported = {}
|
||||
if package.enable_game_support_detection:
|
||||
retval = self.resolve(package, [])
|
||||
for game in retval:
|
||||
game_is_supported[game.id] = True
|
||||
|
||||
self.set_supported(package, game_is_supported, 1)
|
||||
|
@ -414,6 +414,8 @@ class Package(db.Model):
|
||||
forums = db.Column(db.Integer, nullable=True)
|
||||
video_url = db.Column(db.String(200), nullable=True, default=None)
|
||||
|
||||
enable_game_support_detection = db.Column(db.Boolean, nullable=False, default=True)
|
||||
|
||||
provides = db.relationship("MetaPackage", secondary=PackageProvides, order_by=db.asc("name"), back_populates="packages")
|
||||
|
||||
dependencies = db.relationship("Dependency", back_populates="depender", lazy="dynamic", foreign_keys=[Dependency.depender_id])
|
||||
|
@ -14,9 +14,12 @@
|
||||
# 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/>.
|
||||
|
||||
import gitdb
|
||||
import json
|
||||
import os, shutil, gitdb
|
||||
import os
|
||||
import shutil
|
||||
from zipfile import ZipFile
|
||||
|
||||
from git import GitCommandError
|
||||
from git_archive_all import GitArchiver
|
||||
from kombu import uuid
|
||||
@ -27,7 +30,7 @@ from app.utils import randomString, post_bot_message, addSystemNotification, add
|
||||
from app.utils.git import clone_repo, get_latest_tag, get_latest_commit, get_temp_dir
|
||||
from .minetestcheck import build_tree, MinetestCheckError, ContentType
|
||||
from ..logic.LogicError import LogicError
|
||||
from ..logic.game_support import GameSupportResolver, PackageSet
|
||||
from ..logic.game_support import GameSupportResolver
|
||||
from ..logic.packages import do_edit_package, ALIASES
|
||||
from ..utils.image import get_image_size
|
||||
|
||||
@ -73,6 +76,25 @@ def getMeta(urlstr, author):
|
||||
return result
|
||||
|
||||
|
||||
@celery.task()
|
||||
def releaseUpdateGameSupport(package_id: int, supported_games, unsupported_games):
|
||||
with db.create_session({})() as session:
|
||||
package = session.query(Package).get(package_id)
|
||||
resolver = GameSupportResolver(session)
|
||||
|
||||
game_is_supported = {}
|
||||
if supported_games:
|
||||
for game in get_games_from_csv(session, supported_games):
|
||||
game_is_supported[game.id] = True
|
||||
if unsupported_games:
|
||||
for game in get_games_from_csv(session, unsupported_games):
|
||||
game_is_supported[game.id] = False
|
||||
|
||||
resolver.set_supported(package, game_is_supported, 10)
|
||||
resolver.update(package)
|
||||
session.commit()
|
||||
|
||||
|
||||
def postReleaseCheckUpdate(self, release: PackageRelease, path):
|
||||
try:
|
||||
tree = build_tree(path, expected_type=ContentType[release.package.type.name],
|
||||
@ -115,20 +137,6 @@ def postReleaseCheckUpdate(self, release: PackageRelease, path):
|
||||
for meta in getMetaPackages(optional_depends):
|
||||
db.session.add(Dependency(package, meta=meta, optional=True))
|
||||
|
||||
# Update game supports
|
||||
if package.type == PackageType.MOD:
|
||||
resolver = GameSupportResolver()
|
||||
game_is_supported = []
|
||||
if "supported_games" in tree.meta:
|
||||
for game in get_games_from_csv(tree.meta["supported_games"]):
|
||||
game_is_supported.append((game, True))
|
||||
if "unsupported_games" in tree.meta:
|
||||
for game in get_games_from_csv(tree.meta["unsupported_games"]):
|
||||
game_is_supported.append((game, False))
|
||||
|
||||
resolver.set_supported(package, game_is_supported, 10)
|
||||
resolver.update(package)
|
||||
|
||||
# Update min/max
|
||||
if tree.meta.get("min_minetest_version"):
|
||||
release.min_rel = MinetestRelease.get(tree.meta["min_minetest_version"], None)
|
||||
@ -145,6 +153,10 @@ def postReleaseCheckUpdate(self, release: PackageRelease, path):
|
||||
except IOError:
|
||||
pass
|
||||
|
||||
# Update game support
|
||||
if package.type == PackageType.MOD:
|
||||
releaseUpdateGameSupport.delay(package.id, tree.meta.get("supported_games"), tree.meta.get("unsupported_games"))
|
||||
|
||||
return tree
|
||||
|
||||
except MinetestCheckError as err:
|
||||
|
@ -68,18 +68,23 @@
|
||||
</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>
|
||||
{% if form %}
|
||||
<h2>Options</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_checkbox_field(form.enable_support_detection) }}
|
||||
|
||||
{% if package.checkPerm(current_user, "EDIT_PACKAGE") and current_user not in package.maintainers %}
|
||||
<h3>
|
||||
{{ _("Added by Editor") }}
|
||||
<i class="ml-2 fas fa-user-edit"></i>
|
||||
</h3>
|
||||
{{ render_field(form.supported) }}
|
||||
{{ render_field(form.unsupported) }}
|
||||
{% endif %}
|
||||
|
||||
{{ render_submit_field(form.submit, class_="mt-4 btn btn-primary") }}
|
||||
</form>
|
||||
|
@ -18,6 +18,7 @@
|
||||
from functools import wraps
|
||||
from typing import List
|
||||
|
||||
import sqlalchemy.orm
|
||||
from flask import abort, redirect, url_for, request
|
||||
from flask_login import current_user
|
||||
from sqlalchemy import or_, and_
|
||||
@ -136,14 +137,14 @@ def post_bot_message(package: Package, title: str, message: str):
|
||||
thread.replies.append(reply)
|
||||
|
||||
|
||||
def get_games_from_csv(csv: str) -> List[Package]:
|
||||
def get_games_from_csv(session: sqlalchemy.orm.Session, 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,
|
||||
games = session.query(Package).filter(and_(Package.state==PackageState.APPROVED, Package.type==PackageType.GAME,
|
||||
or_(Package.name==game_name, Package.name==game_name + "_game"))).all()
|
||||
retval.extend(games)
|
||||
|
||||
|
24
migrations/versions/8425c06b7d77_.py
Normal file
24
migrations/versions/8425c06b7d77_.py
Normal file
@ -0,0 +1,24 @@
|
||||
"""empty message
|
||||
|
||||
Revision ID: 8425c06b7d77
|
||||
Revises: 8807a5279793
|
||||
Create Date: 2022-06-25 00:26:29.841145
|
||||
|
||||
"""
|
||||
from alembic import op
|
||||
import sqlalchemy as sa
|
||||
from sqlalchemy.dialects import postgresql
|
||||
|
||||
# revision identifiers, used by Alembic.
|
||||
revision = '8425c06b7d77'
|
||||
down_revision = '8807a5279793'
|
||||
branch_labels = None
|
||||
depends_on = None
|
||||
|
||||
|
||||
def upgrade():
|
||||
op.add_column('package', sa.Column('enable_game_support_detection', sa.Boolean(), nullable=False, server_default="true"))
|
||||
|
||||
|
||||
def downgrade():
|
||||
op.drop_column('package', 'enable_game_support_detection')
|
Loading…
Reference in New Issue
Block a user