Add API to get all package stats

This commit is contained in:
rubenwardy 2022-11-15 01:51:21 +00:00
parent 292b4f5483
commit 01bc519b86
3 changed files with 43 additions and 11 deletions

@ -15,6 +15,7 @@
# along with this program. If not, see <https://www.gnu.org/licenses/>.
import math
from functools import wraps
from typing import List
import flask_sqlalchemy
@ -24,17 +25,16 @@ from sqlalchemy.orm import joinedload
from sqlalchemy.sql.expression import func
from app import csrf
from app.logic.graphs import get_package_stats, get_package_stats_for_user, get_all_package_stats
from app.markdown import render_markdown
from app.models import Tag, PackageState, PackageType, Package, db, PackageRelease, Permission, ForumTopic, \
MinetestRelease, APIToken, PackageScreenshot, License, ContentWarning, User, PackageReview, Thread
from app.querybuilder import QueryBuilder
from app.utils import is_package_page, get_int_or_abort, url_set_query, abs_url, isYes
from app.logic.graphs import get_package_stats, get_package_stats_for_user
from . import bp
from .auth import is_api_authd
from .support import error, api_create_vcs_release, api_create_zip_release, api_create_screenshot, \
api_order_screenshots, api_edit_package, api_set_cover_image
from functools import wraps
def cors_allowed(f):
@ -441,6 +441,12 @@ def package_stats(package: Package):
return jsonify(get_package_stats(package))
@bp.route("/api/package_stats/")
@cors_allowed
def all_package_stats():
return jsonify(get_all_package_stats())
@bp.route("/api/scores/")
@cors_allowed
def package_scores():

@ -112,14 +112,20 @@ Tokens can be attained by visiting [Settings > API Tokens](/user/tokens/).
* Returns daily stats for package, or null if there is no data.
* Daily date is done based on the UTC timezone.
* EXPERIMENTAL. This API may change without warning.
* A table with the following keys:
* `from`: start date, inclusive. Ex: 2022-10-22.
* An object with the following keys:
* `start`: start date, inclusive. Ex: 2022-10-22.
* `end`: end date, inclusive. Ex: 2022-11-05.
* `platform_minetest`: list of integers per day.
* `platform_other`: list of integers per day.
* `reason_new`: list of integers per day.
* `reason_dependency`: list of integers per day.
* `reason_update`: list of integers per day.
* GET `/api/package_stats/`
* Returns last 30 days of daily stats for _all_ packages.
* An object with the following keys:
* `start`: start date, inclusive. Ex: 2022-10-22.
* `end`: end date, inclusive. Ex: 2022-11-05.
* `package_downloads`: map from package key to list of download integers.
You can download a package by building one of the two URLs:

@ -1,5 +1,7 @@
import datetime
from datetime import timedelta
from typing import Optional
from app.models import User, Package, PackageDailyStats, db, PackageState
from sqlalchemy import func
@ -68,11 +70,16 @@ def get_package_stats_for_user(user: User):
return results
def get_package_overview_for_user(user: User, start_date: datetime.date, end_date: datetime.date):
stats = db.session \
def get_package_overview_for_user(user: Optional[User], start_date: datetime.date, end_date: datetime.date):
query = db.session \
.query(PackageDailyStats.package_id, PackageDailyStats.date,
(PackageDailyStats.platform_minetest + PackageDailyStats.platform_other).label("downloads")) \
.filter(PackageDailyStats.package.has(author_id=user.id, state=PackageState.APPROVED)) \
(PackageDailyStats.platform_minetest + PackageDailyStats.platform_other).label("downloads"))
if user:
query = query.filter(PackageDailyStats.package.has(author_id=user.id))
stats = query \
.filter(PackageDailyStats.package.has(state=PackageState.APPROVED)) \
.order_by(db.asc(PackageDailyStats.package_id), db.asc(PackageDailyStats.date)) \
.all()
@ -84,8 +91,12 @@ def get_package_overview_for_user(user: User, start_date: datetime.date, end_dat
bucket.append(stat)
package_title_by_id = {}
for package in user.packages.filter_by(state=PackageState.APPROVED).all():
package_title_by_id[package.id] = package.title
pkg_query = user.packages if user else Package.query
for package in pkg_query.filter_by(state=PackageState.APPROVED).all():
if user:
package_title_by_id[package.id] = package.title
else:
package_title_by_id[package.id] = package.getId()
result = {}
@ -105,5 +116,14 @@ def get_package_overview_for_user(user: User, start_date: datetime.date, end_dat
else:
row.append(0)
return result
def get_all_package_stats():
end_date = datetime.datetime.utcnow().date()
start_date = (datetime.datetime.utcnow() - datetime.timedelta(days=29)).date()
return {
"start": start_date.isoformat(),
"end": end_date.isoformat(),
"package_downloads": get_package_overview_for_user(None, start_date, end_date),
}