From 380bf520ae2f6b1668830f3c72d2823691c30f2e Mon Sep 17 00:00:00 2001 From: Paul Hebble Date: Mon, 29 Nov 2021 15:30:03 +0000 Subject: [PATCH] Downloads: Don't count from bots, send HTML to Discord --- KerbalStuff/blueprints/mods.py | 53 ++++++++++++++++++---------------- requirements-backend.txt | 1 + 2 files changed, 29 insertions(+), 25 deletions(-) diff --git a/KerbalStuff/blueprints/mods.py b/KerbalStuff/blueprints/mods.py index 163739bd..c1c28339 100644 --- a/KerbalStuff/blueprints/mods.py +++ b/KerbalStuff/blueprints/mods.py @@ -12,6 +12,7 @@ import dns.resolver import requests import werkzeug.wrappers +import user_agents from flask import Blueprint, render_template, send_file, make_response, url_for, abort, session, \ redirect, request @@ -564,31 +565,33 @@ def download(mod_id: int, mod_name: Optional[str], version: Optional[str]) -> Op else next(filter(lambda v: v.friendly_version == version, mod.versions), None) if not mod_version: abort(404, 'Unfortunately we couldn\'t find the requested mod version. Maybe it got deleted?') - # Events are aggregated hourly - an_hour_ago = datetime.now() - timedelta(hours=1) - download = DownloadEvent.query\ - .filter(DownloadEvent.version_id == mod_version.id, DownloadEvent.created > an_hour_ago)\ - .order_by(desc(DownloadEvent.created))\ - .first() - storage = _cfg('storage') - if not storage: - abort(404) - - if 'Range' not in request.headers: - if not download: - download = DownloadEvent() - download.mod = mod - download.version = mod_version - download.downloads = 1 - db.add(download) - db.flush() - db.commit() - mod.downloads.append(download) - else: - download.downloads += 1 - mod.download_count += 1 - mod_version.download_count += 1 - mod.score = get_mod_score(mod) + ua = user_agents.parse(request.user_agent.string) + # Only count download events from non-bots + if not ua.is_bot: + # Events are aggregated hourly + an_hour_ago = datetime.now() - timedelta(hours=1) + download = DownloadEvent.query\ + .filter(DownloadEvent.version_id == mod_version.id, DownloadEvent.created > an_hour_ago)\ + .order_by(desc(DownloadEvent.created))\ + .first() + if 'Range' not in request.headers: + if not download: + download = DownloadEvent() + download.mod = mod + download.version = mod_version + download.downloads = 1 + db.add(download) + db.flush() + db.commit() + mod.downloads.append(download) + else: + download.downloads += 1 + mod.download_count += 1 + mod_version.download_count += 1 + mod.score = get_mod_score(mod) + elif 'discord'.casefold() in ua.browser.family.casefold(): + # Send HTML to Discord so it can see the OpenGraph tags + return redirect(url_for("mods.mod", mod_id=mod.id, mod_name=mod.name)) protocol = _cfg("protocol") cdn_domain = _cfg("cdn-domain") diff --git a/requirements-backend.txt b/requirements-backend.txt index 0ee03a0e..65b15863 100644 --- a/requirements-backend.txt +++ b/requirements-backend.txt @@ -28,4 +28,5 @@ requests-oauthlib SQLAlchemy>=1.4,<2 # 1.4 shows deprecation warnings for 2.0, 2.0 would break our backend as of now SQLAlchemy-Utils urllib3 +user_agents Werkzeug