diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index f82e5c0..ce90de1 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -26,7 +26,7 @@ jobs: - uses: actions/setup-python@v2 with: - python-version: "3.9" + python-version: "3.10" - uses: actions/cache@v2 with: diff --git a/Dockerfile b/Dockerfile index b0d3402..0cb459c 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,24 +1,26 @@ -FROM python:3.9 as builder +FROM python:3.10 as builder RUN apt-get update && \ apt-get install -y --no-install-recommends \ - build-essential libcairo2-dev libgirepository1.0-dev \ - gir1.2-ostree-1.0 flatpak + build-essential libcairo2-dev libgirepository1.0-dev \ + gir1.2-ostree-1.0 flatpak ADD requirements.txt /requirements.txt RUN python -m venv /venv && \ /venv/bin/pip install -r requirements.txt \ && rm -f /requirements.txt -FROM python:3.9-slim +FROM python:3.10-slim EXPOSE 8000 RUN apt-get update && \ apt-get install -y --no-install-recommends \ - libcairo2 gir1.2-ostree-1.0 flatpak && \ + libcairo2 gir1.2-ostree-1.0 flatpak && \ apt-get clean && rm -rf /var/lib/apt/lists/* && \ - flatpak --user remote-add flathub https://flathub.org/repo/flathub.flatpakrepo + flatpak --user remote-add flathub https://flathub.org/repo/flathub.flatpakrepo && \ + flatpak --user remote-add flathub-beta https://flathub.org/beta-repo/flathub-beta.flatpakrepo + COPY ./app /app COPY ./data /data diff --git a/app/apps.py b/app/apps.py index 7928052..867cb16 100644 --- a/app/apps.py +++ b/app/apps.py @@ -6,43 +6,55 @@ def load_appstream(): - apps = utils.appstream2dict("repo") + apps_stable = utils.appstream2dict("repo") + apps_beta = utils.appstream2dict("beta-repo") - current_apps = {app[5:] for app in db.redis_conn.smembers("apps:index")} + apps = merge_apps(apps_beta, apps_stable) + + current_apps = db.get_apps("stable") + current_apps_beta = db.get_apps("beta") current_categories = db.redis_conn.smembers("categories:index") + current_developers = db.redis_conn.smembers("developers:index") db.initialize() with db.redis_conn.pipeline() as p: p.delete("categories:index", *current_categories) + p.delete("developers:index", *current_developers) for appid in apps: redis_key = f"apps:{appid}" clean_html_re = re.compile("<.*?>") - search_description = re.sub(clean_html_re, "", apps[appid]["description"]) - - if search_keywords := apps[appid].get("keywords"): - search_keywords = " ".join(search_keywords) - else: - search_keywords = "" - - fts = { - "id": appid, - "name": apps[appid]["name"], - "summary": apps[appid]["summary"], - "description": search_description, - "keywords": search_keywords, - } + if "stable" in apps[appid]: + search_description = re.sub( + clean_html_re, "", apps[appid]["stable"]["description"] + ) + + if search_keywords := apps[appid]["stable"].get("keywords"): + search_keywords = " ".join(search_keywords) + else: + search_keywords = "" + + fts = { + "id": appid, + "name": apps[appid]["stable"]["name"], + "summary": apps[appid]["stable"]["summary"], + "description": search_description, + "keywords": search_keywords, + } + p.hset(f"fts:{appid}", mapping=fts) + if categories := apps[appid]["stable"].get("categories"): + for category in categories: + p.sadd("categories:index", category) + p.sadd(f"categories:{category}", redis_key) + + if developer_name := apps[appid]["stable"].get("developer_name"): + p.sadd("developers:index", developer_name) + p.sadd(f"developers:{developer_name}", redis_key) p.set(f"apps:{appid}", json.dumps(apps[appid])) - p.hset(f"fts:{appid}", mapping=fts) - - if categories := apps[appid].get("categories"): - for category in categories: - p.sadd("categories:index", category) - p.sadd(f"categories:{category}", redis_key) - for appid in current_apps - set(apps): + for appid in current_apps - set(apps_stable): p.delete( f"apps:{appid}", f"fts:{appid}", @@ -51,51 +63,85 @@ def load_appstream(): ) db.redis_search.delete_document(f"fts:{appid}") - new_apps = set(apps) - current_apps + new_apps = set(apps_stable) - current_apps if not len(new_apps): new_apps = None + new_apps_beta = set(apps_beta) - current_apps_beta + if not len(new_apps_beta): + new_apps_beta = None + p.delete("apps:index") - p.sadd("apps:index", *[f"apps:{appid}" for appid in apps]) + p.sadd("apps:index", *[f"apps:{appid}" for appid in apps_stable]) + p.delete("apps:index_beta") + p.sadd("apps:index_beta", *[f"apps:{appid}" for appid in apps_beta]) p.execute() - return new_apps + return new_apps, new_apps_beta + + +def merge_apps(apps_beta, apps_stable): + apps = {} + for appid in apps_stable: + apps[appid] = {"stable": apps_stable[appid]} + + for appid in apps_beta: + if appid not in apps: + apps[appid] = {"beta": apps_beta[appid]} + else: + apps[appid] = {"stable": apps_stable[appid], "beta": apps_beta[appid]} + + return apps def list_appstream(repo: str = "stable"): - apps = {app[5:] for app in db.redis_conn.smembers("apps:index")} - return sorted(apps) + return sorted(db.get_apps(repo)) + +def get_recently_updated(limit: int = 100, repo: str = "stable"): + if repo == "stable": + zset = db.redis_conn.zrevrange("recently_updated_zset", 0, limit - 1) + if repo == "beta": + zset = db.redis_conn.zrevrange("recently_updated_beta_zset", 0, limit - 1) -def get_recently_updated(limit: int = 100): - zset = db.redis_conn.zrevrange("recently_updated_zset", 0, limit - 1) return [appid for appid in zset if db.redis_conn.exists(f"apps:{appid}")] -def get_category(category: str): +def get_category(category: str, repo: str = "stable"): if index := db.redis_conn.smembers(f"categories:{category}"): json_appdata = db.redis_conn.mget(index) appdata = [json.loads(app) for app in json_appdata] - return [(app["id"]) for app in appdata] + return [(app[repo]["id"]) for app in appdata if repo in app] + else: + return None + + +def get_developer(developer: str, repo: str = "stable"): + if index := db.redis_conn.smembers(f"developers:{developer}"): + json_appdata = db.redis_conn.mget(index) + appdata = [json.loads(app) for app in json_appdata] + + return [(app[repo]["id"]) for app in appdata if repo in app] else: - return [] + return None -def search(query: str): +def search(query: str, repo: str = "stable"): if results := db.search(query): appids = tuple(doc_id.replace("fts", "apps") for doc_id in results) apps = [json.loads(x) for x in db.redis_conn.mget(appids)] ret = [] for app in apps: - entry = { - "id": app["id"], - "name": app["name"], - "summary": app["summary"], - "icon": app.get("icon"), - } - ret.append(entry) + if repo in app: + entry = { + "id": app[repo]["id"], + "name": app[repo]["name"], + "summary": app[repo]["summary"], + "icon": app[repo].get("icon"), + } + ret.append(entry) return ret diff --git a/app/db.py b/app/db.py index 3e23dd5..4948bce 100644 --- a/app/db.py +++ b/app/db.py @@ -126,5 +126,27 @@ def get_json_key(key: str): return None -def get_app_count(): - return redis_conn.scard("apps:index") +def get_app_count(repo: str = "stable") -> int: + if repo == "stable_and_beta": + return len(get_apps(repo)) + if repo == "stable": + return redis_conn.scard("apps:index") + if repo == "beta": + return redis_conn.scard("apps:index_beta") + + +def get_apps(repo: str = "stable"): + if repo == "stable_and_beta": + apps = {app[5:] for app in redis_conn.smembers("apps:index")} + apps_beta = {app[5:] for app in redis_conn.smembers("apps:index_beta")} + return apps | apps_beta + elif repo == "stable": + apps = {app[5:] for app in redis_conn.smembers("apps:index")} + return apps + elif repo == "beta": + apps = {app[5:] for app in redis_conn.smembers("apps:index_beta")} + return apps + + +def get_developers(): + return {developer for developer in redis_conn.smembers("developers:index")} diff --git a/app/feeds.py b/app/feeds.py index 54ec8ed..5bc695d 100644 --- a/app/feeds.py +++ b/app/feeds.py @@ -4,17 +4,27 @@ from . import db -def generate_feed(key: str, title: str, description: str, link: str): +def generate_feed( + key: str, + title: str, + description: str, + link: str, + repo: str, +): feed = FeedGenerator() feed.title(title) feed.description(description) feed.link(href=link) feed.language("en") - appids = db.redis_conn.zrevrange(key, 0, 10, withscores=True) - apps = [(db.get_json_key(f"apps:{appid[0]}"), appid[1]) for appid in appids] + # get 15, as we might have some that don't exist, due to summary knowing about consale-applications + appids = db.redis_conn.zrevrange(key, 0, 15, withscores=True) + app_score_tuple = [ + (db.get_json_key(f"apps:{appid[0]}"), appid[1]) for appid in appids + ] + apps = [(item[0][repo], item[1]) for item in app_score_tuple if item[0] is not None] - for app, timestamp in reversed(apps): + for app, timestamp in reversed(apps[:10]): if not app.get("name"): continue @@ -29,9 +39,7 @@ def generate_feed(key: str, title: str, description: str, link: str): entry.pubDate(f"{entry_date} UTC") content = [ - ''.format( - app["id"] - ), + ''.format(app["icon"]), f"

{app['summary']}

", f"

{app['description']}

", "

Additional information:

", @@ -63,19 +71,21 @@ def generate_feed(key: str, title: str, description: str, link: str): return feed.rss_str() -def get_recently_updated_apps_feed(): +def get_recently_updated_apps_feed(repo: str = "stable"): return generate_feed( - "recently_updated_zset", + "recently_updated_zset" if repo == "stable" else "recently_updated_beta_zset", "Flathub – recently updated applications", "Recently updated applications published on Flathub", "https://flathub.org/apps/collection/recently-updated", + repo, ) -def get_new_apps_feed(): +def get_new_apps_feed(repo: str = "stable"): return generate_feed( - "new_apps_zset", + "new_apps_zset" if repo == "stable" else "new_apps_beta_zset", "Flathub – recently added applications", "Applications recently published on Flathub", "https://flathub.org/apps/collection/new", + repo, ) diff --git a/app/main.py b/app/main.py index 207d577..df2b82d 100644 --- a/app/main.py +++ b/app/main.py @@ -22,7 +22,7 @@ def startup_event(): @app.post("/update") def update(): - new_apps = apps.load_appstream() + new_apps, new_apps_beta = apps.load_appstream() summary.update() picks.update() stats.update() @@ -31,14 +31,25 @@ def update(): new_apps_zset = {} for appid in new_apps: if metadata := db.get_json_key(f"summary:{appid}"): - new_apps_zset[appid] = metadata.get("timestamp", 0) + if "stable" in metadata: + new_apps_zset[appid] = metadata["stable"].get("timestamp", 0) db.redis_conn.zadd("new_apps_zset", new_apps_zset) + if new_apps_beta: + new_apps_beta_zset = {} + for appid in new_apps_beta: + if metadata := db.get_json_key(f"summary:{appid}"): + if "beta" in metadata: + new_apps_beta_zset[appid] = metadata["beta"].get("timestamp", 0) + db.redis_conn.zadd("new_apps_beta_zset", new_apps_beta_zset) + get_recently_updated.cache_clear() @app.get("/category/{category}") -def get_category(category: schemas.Category): +def get_category( + category: schemas.Category, +): ids = apps.get_category(category) downloads = stats.get_downloads_by_ids(ids) @@ -53,13 +64,44 @@ def get_category(category: schemas.Category): return sorted_ids +@app.get("/developer/") +def get_developers(): + return db.get_developers() + + +@app.get("/developer/{developer}") +def get_developer( + developer: str, + response: Response, +): + ids = apps.get_developer(developer) + + if not ids: + response.status_code = 404 + return response + + downloads = stats.get_downloads_by_ids(ids) + sorted_ids = sorted( + ids, + key=lambda appid: downloads.get(appid, {"downloads_last_month": 0}).get( + "downloads_last_month", 0 + ), + reverse=True, + ) + + return sorted_ids + + @app.get("/appstream") -def list_appstream(): - return apps.list_appstream() +def list_appstream(type: schemas.AppstreamType = "stable"): + return apps.list_appstream(type) @app.get("/appstream/{appid}", status_code=200) -def get_appstream(appid: str, response: Response): +def get_appstream( + appid: str, + response: Response, +): if value := db.get_json_key(f"apps:{appid}"): return value @@ -75,8 +117,8 @@ def search(userquery: str): @app.get("/collection/recently-updated") @app.get("/collection/recently-updated/{limit}") @lru_cache() -def get_recently_updated(limit: int = 100): - return apps.get_recently_updated(limit) +def get_recently_updated(limit: int = 100, type: schemas.AppstreamType = "stable"): + return apps.get_recently_updated(limit, type) @app.get("/picks/{pick}") @@ -98,15 +140,18 @@ def get_popular_days(days: int): @app.get("/feed/recently-updated") -def get_recently_updated_apps_feed(): +def get_recently_updated_apps_feed(type: schemas.AppstreamType = "stable"): return Response( - content=feeds.get_recently_updated_apps_feed(), media_type="application/rss+xml" + content=feeds.get_recently_updated_apps_feed(type), + media_type="application/rss+xml", ) @app.get("/feed/new") -def get_new_apps_feed(): - return Response(content=feeds.get_new_apps_feed(), media_type="application/rss+xml") +def get_new_apps_feed(type: schemas.AppstreamType = "stable"): + return Response( + content=feeds.get_new_apps_feed(type), media_type="application/rss+xml" + ) @app.get("/status", status_code=200) diff --git a/app/schemas.py b/app/schemas.py index 516256b..971b5ea 100644 --- a/app/schemas.py +++ b/app/schemas.py @@ -14,3 +14,9 @@ class Category(str, Enum): Science = "Science" System = "System" Utility = "Utility" + + +class AppstreamType(str, Enum): + Stable = "stable" + Beta = "beta" + Stable_And_Beta = "stable_and_beta" diff --git a/app/summary.py b/app/summary.py index 4ecc669..17932c1 100644 --- a/app/summary.py +++ b/app/summary.py @@ -25,7 +25,7 @@ def validate_ref(ref: str, enforce_arch=True): if enforce_arch and arch != "x86_64": return False - if branch != "stable": + if branch != "stable" and branch != "beta": return False return True @@ -91,18 +91,39 @@ def parse_metadata(ini: str): def update(): - summary_dict = defaultdict(lambda: {"arches": []}) - recently_updated_zset = {} + data = get_summary_data("flathub") + data_beta = get_summary_data("flathub-beta") + + summary_dict, recently_updated_zset = parse_summary_data(data) + summary_dict_beta, recently_updated_beta_zset = parse_summary_data(data_beta) + summary = merge_summary(summary_dict_beta, summary_dict) + + db.redis_conn.zadd("recently_updated_zset", recently_updated_zset) + db.redis_conn.zadd("recently_updated_beta_zset", recently_updated_beta_zset) + db.redis_conn.mset( + {f"summary:{appid}": json.dumps(summary[appid]) for appid in summary} + ) + + return len(recently_updated_zset), len(recently_updated_beta_zset) + +def get_summary_data(remote_name): repo_file = Gio.File.new_for_path(f"{config.settings.flatpak_user_dir}/repo") repo = OSTree.Repo.new(repo_file) repo.open(None) - status, summary, signatures = repo.remote_fetch_summary("flathub", None) + status, summary, signatures = repo.remote_fetch_summary(remote_name, None) data = GLib.Variant.new_from_bytes( GLib.VariantType.new(OSTree.SUMMARY_GVARIANT_STRING), summary, True ) + return data + + +def parse_summary_data(data): + summary_dict = defaultdict(lambda: {"arches": []}) + recently_updated_zset = {} + refs, metadata = data.unpack() xa_cache = metadata["xa.cache"] @@ -143,9 +164,21 @@ def update(): summary_dict[appid]["arches"].append(arch) - db.redis_conn.zadd("recently_updated_zset", recently_updated_zset) - db.redis_conn.mset( - {f"summary:{appid}": json.dumps(summary_dict[appid]) for appid in summary_dict} - ) + return summary_dict, recently_updated_zset + + +def merge_summary(summary_beta, summary_stable): + summary = {} + for appid in summary_stable: + summary[appid] = {"stable": summary_stable[appid]} + + for appid in summary_beta: + if appid not in summary: + summary[appid] = {"beta": summary_beta[appid]} + else: + summary[appid] = { + "stable": summary_stable[appid], + "beta": summary_beta[appid], + } - return len(recently_updated_zset) + return summary diff --git a/app/utils.py b/app/utils.py index 59afb0e..f10ccf2 100644 --- a/app/utils.py +++ b/app/utils.py @@ -7,11 +7,11 @@ from . import config -def appstream2dict(reponame: str): +def appstream2dict(repo_name: str) -> dict[str, object]: if config.settings.appstream_repos is not None: appstream_path = os.path.join( config.settings.appstream_repos, - reponame, + repo_name, "appstream", "x86_64", "appstream.xml", @@ -23,7 +23,7 @@ def appstream2dict(reponame: str): appstream = file.read() else: appstream_url = ( - f"https://hub.flathub.org/{reponame}/appstream/x86_64/appstream.xml.gz" + f"https://hub.flathub.org/{repo_name}/appstream/x86_64/appstream.xml.gz" ) r = requests.get(appstream_url, stream=True) appstream = gzip.decompress(r.raw.data) diff --git a/tests/appstream/beta-repo/appstream/x86_64/appstream.xml b/tests/appstream/beta-repo/appstream/x86_64/appstream.xml new file mode 100644 index 0000000..9648a39 --- /dev/null +++ b/tests/appstream/beta-repo/appstream/x86_64/appstream.xml @@ -0,0 +1,223 @@ + + + + org.sugarlabs.Maze + org.sugarlabs.Maze + Maze + A simple maze game, but this is the beta version + Sugar Labs Community +

Good at finding your way out of hard situations? Let's see! Try to make your way through an increasingly difficult path.

+ org.sugarlabs.Maze.png + org.sugarlabs.Maze.png + + Game + + + HiDpiIcon + + GPL-3.0-or-later + https://github.com/sugarlabs/maze-activity + https://github.com/sugarlabs/maze-activity + + + https://i.imgur.com/imoTbzP.png + https://dl.flathub.org/repo/screenshots/org.sugarlabs.Maze-stable/624x351/org.sugarlabs.Maze-0cf71487936dec29c5b092662909f125.png + https://dl.flathub.org/repo/screenshots/org.sugarlabs.Maze-stable/112x63/org.sugarlabs.Maze-0cf71487936dec29c5b092662909f125.png + https://dl.flathub.org/repo/screenshots/org.sugarlabs.Maze-stable/224x126/org.sugarlabs.Maze-0cf71487936dec29c5b092662909f125.png + https://dl.flathub.org/repo/screenshots/org.sugarlabs.Maze-stable/752x423/org.sugarlabs.Maze-0cf71487936dec29c5b092662909f125.png + + + https://i.imgur.com/GO11pbh.png + https://dl.flathub.org/repo/screenshots/org.sugarlabs.Maze-stable/624x351/org.sugarlabs.Maze-4308958995b5f213eac85c7053e01a33.png + https://dl.flathub.org/repo/screenshots/org.sugarlabs.Maze-stable/112x63/org.sugarlabs.Maze-4308958995b5f213eac85c7053e01a33.png + https://dl.flathub.org/repo/screenshots/org.sugarlabs.Maze-stable/224x126/org.sugarlabs.Maze-4308958995b5f213eac85c7053e01a33.png + https://dl.flathub.org/repo/screenshots/org.sugarlabs.Maze-stable/752x423/org.sugarlabs.Maze-4308958995b5f213eac85c7053e01a33.png + + + https://i.imgur.com/RH1koq6.png + https://dl.flathub.org/repo/screenshots/org.sugarlabs.Maze-stable/624x351/org.sugarlabs.Maze-5d288daae5069cde2ffe86ab4a9285a7.png + https://dl.flathub.org/repo/screenshots/org.sugarlabs.Maze-stable/112x63/org.sugarlabs.Maze-5d288daae5069cde2ffe86ab4a9285a7.png + https://dl.flathub.org/repo/screenshots/org.sugarlabs.Maze-stable/224x126/org.sugarlabs.Maze-5d288daae5069cde2ffe86ab4a9285a7.png + https://dl.flathub.org/repo/screenshots/org.sugarlabs.Maze-stable/752x423/org.sugarlabs.Maze-5d288daae5069cde2ffe86ab4a9285a7.png + + + + + + + org.sugarlabs.Maze.desktop + + ach + am + an + ar + ayc + aym + ca + cs + da + de + el + en + en_GB + en_US + es + fa + fi + fr + gn + gug + he + hi + hu + hus + hy + id + it + ja + kab + km + ko + lt + mg + mi + ml + mn + ms + nah + ne + nl + pap + pbs + pl + pt + pt_BR + ro + ru + sk + sl + son + sq + sr + sv + sw + ta + te + th + uk + vi + zh_CN + zh_TW + + app/org.sugarlabs.Maze/x86_64/stable +
+ + com.only.in.beta.Repo + com.only.in.beta.Repo + Beta app + A simple beta test app + Developer +

Developers, Developers, Developers, Developers

+ com.only.in.beta.Repo.png + com.only.in.beta.Repo.png + + Game + + + HiDpiIcon + + GPL-3.0-or-later + + + https://i.imgur.com/imoTbzP.png + https://dl.flathub.org/repo/screenshots/com.only.in.beta.Repo-stable/624x351/com.only.in.beta.Repo-0cf71487936dec29c5b092662909f125.png + https://dl.flathub.org/repo/screenshots/com.only.in.beta.Repo-stable/112x63/com.only.in.beta.Repo-0cf71487936dec29c5b092662909f125.png + https://dl.flathub.org/repo/screenshots/com.only.in.beta.Repo-stable/224x126/com.only.in.beta.Repo-0cf71487936dec29c5b092662909f125.png + https://dl.flathub.org/repo/screenshots/com.only.in.beta.Repo-stable/752x423/com.only.in.beta.Repo-0cf71487936dec29c5b092662909f125.png + + + https://i.imgur.com/GO11pbh.png + https://dl.flathub.org/repo/screenshots/com.only.in.beta.Repo-stable/624x351/com.only.in.beta.Repo-4308958995b5f213eac85c7053e01a33.png + https://dl.flathub.org/repo/screenshots/com.only.in.beta.Repo-stable/112x63/com.only.in.beta.Repo-4308958995b5f213eac85c7053e01a33.png + https://dl.flathub.org/repo/screenshots/com.only.in.beta.Repo-stable/224x126/com.only.in.beta.Repo-4308958995b5f213eac85c7053e01a33.png + https://dl.flathub.org/repo/screenshots/com.only.in.beta.Repo-stable/752x423/com.only.in.beta.Repo-4308958995b5f213eac85c7053e01a33.png + + + https://i.imgur.com/RH1koq6.png + https://dl.flathub.org/repo/screenshots/com.only.in.beta.Repo-stable/624x351/com.only.in.beta.Repo-5d288daae5069cde2ffe86ab4a9285a7.png + https://dl.flathub.org/repo/screenshots/com.only.in.beta.Repo-stable/112x63/com.only.in.beta.Repo-5d288daae5069cde2ffe86ab4a9285a7.png + https://dl.flathub.org/repo/screenshots/com.only.in.beta.Repo-stable/224x126/com.only.in.beta.Repo-5d288daae5069cde2ffe86ab4a9285a7.png + https://dl.flathub.org/repo/screenshots/com.only.in.beta.Repo-stable/752x423/com.only.in.beta.Repo-5d288daae5069cde2ffe86ab4a9285a7.png + + + + + + + com.only.in.beta.Repo.desktop + + ach + am + an + ar + ayc + aym + ca + cs + da + de + el + en + en_GB + en_US + es + fa + fi + fr + gn + gug + he + hi + hu + hus + hy + id + it + ja + kab + km + ko + lt + mg + mi + ml + mn + ms + nah + ne + nl + pap + pbs + pl + pt + pt_BR + ro + ru + sk + sl + son + sq + sr + sv + sw + ta + te + th + uk + vi + zh_CN + zh_TW + + app/com.only.in.beta.Repo/x86_64/stable +
+
diff --git a/tests/main.py b/tests/main.py index 125c5f9..bc48320 100644 --- a/tests/main.py +++ b/tests/main.py @@ -49,6 +49,7 @@ def setup_module(): repo.create(OSTree.RepoMode.BARE, None) remote_path = os.path.join(os.getcwd(), "tests/ostree/repo") repo.remote_add("flathub", f"file://{remote_path}") + repo.remote_add("flathub-beta", f"file://{remote_path}") for i, test_stats_json in enumerate( sorted(glob.glob("tests/stats/*.json"), reverse=True) @@ -91,12 +92,39 @@ def test_apps_by_non_existent_category(): assert response.status_code == 422 +def test_apps_by_developer(): + response = client.get("/developer/Sugar Labs Community") + assert response.status_code == 200 + assert response.json() == _get_expected_json_result("test_apps_by_developer") + + +def test_apps_by_non_existent_developer(): + response = client.get("/developer/NonExistent") + assert response.status_code == 404 + + def test_appstream_by_appid(): response = client.get("/appstream/org.sugarlabs.Maze") assert response.status_code == 200 assert response.json() == _get_expected_json_result("test_appstream_by_appid") +def test_appstream_by_appid_stable_only(): + response = client.get("/appstream/com.anydesk.Anydesk") + assert response.status_code == 200 + assert response.json() == _get_expected_json_result( + "test_appstream_by_appid_stable_only" + ) + + +def test_appstream_by_appid_beta_only(): + response = client.get("/appstream/com.only.in.beta.Repo") + assert response.status_code == 200 + assert response.json() == _get_expected_json_result( + "test_appstream_by_appid_beta_only" + ) + + def test_appstream_by_non_existent_appid(): response = client.get("/appstream/NonExistent") assert response.status_code == 404 @@ -217,12 +245,48 @@ def test_list_appstream(): assert response.json() == _get_expected_json_result("test_list_appstream") -def test_summary_by_id(): +def test_list_appstream_explicit_stable(): + response = client.get("/appstream?type=stable") + assert response.status_code == 200 + assert response.json() == _get_expected_json_result("test_list_appstream") + + +def test_list_appstream_beta(): + response = client.get("/appstream?type=beta") + assert response.status_code == 200 + assert response.json() == _get_expected_json_result("test_list_appstream_beta") + + +def test_list_appstream_beta(): + response = client.get("/appstream?type=stable_and_beta") + assert response.status_code == 200 + assert response.json() == _get_expected_json_result( + "test_list_appstream_stable_and_beta" + ) + + +def test_summary_by_appid(): response = client.get("/summary/org.sugarlabs.Maze") assert response.status_code == 200 assert response.json() == _get_expected_json_result("test_summary_by_appid") +def test_summary_by_appid_stable_only(): + response = client.get("/summary/com.anydesk.Anydesk") + assert response.status_code == 200 + assert response.json() == _get_expected_json_result( + "test_summary_by_appid_stable_only" + ) + + +def test_summary_by_appid_beta_only(): + response = client.get("/summary/com.only.in.beta.Repo") + assert response.status_code == 200 + assert response.json() == _get_expected_json_result( + "test_summary_by_appid_beta_only" + ) + + def test_summary_by_non_existent_id(): response = client.get("/summary/does.not.exist") assert response.status_code == 404 diff --git a/tests/results/test_apps_by_developer.json b/tests/results/test_apps_by_developer.json new file mode 100644 index 0000000..f57fe20 --- /dev/null +++ b/tests/results/test_apps_by_developer.json @@ -0,0 +1,3 @@ +[ + "org.sugarlabs.Maze" +] diff --git a/tests/results/test_appstream_by_appid.json b/tests/results/test_appstream_by_appid.json index ca55ff1..244bec8 100644 --- a/tests/results/test_appstream_by_appid.json +++ b/tests/results/test_appstream_by_appid.json @@ -1,58 +1,118 @@ { - "description": "

Good at finding your way out of hard situations? Let's see! Try to make your way through an increasingly difficult path.

", - "screenshots": [ - { - "624x351": "https://dl.flathub.org/repo/screenshots/org.sugarlabs.Maze-stable/624x351/org.sugarlabs.Maze-4308958995b5f213eac85c7053e01a33.png", - "112x63": "https://dl.flathub.org/repo/screenshots/org.sugarlabs.Maze-stable/112x63/org.sugarlabs.Maze-4308958995b5f213eac85c7053e01a33.png", - "224x126": "https://dl.flathub.org/repo/screenshots/org.sugarlabs.Maze-stable/224x126/org.sugarlabs.Maze-4308958995b5f213eac85c7053e01a33.png", - "752x423": "https://dl.flathub.org/repo/screenshots/org.sugarlabs.Maze-stable/752x423/org.sugarlabs.Maze-4308958995b5f213eac85c7053e01a33.png" - }, - { - "624x351": "https://dl.flathub.org/repo/screenshots/org.sugarlabs.Maze-stable/624x351/org.sugarlabs.Maze-0cf71487936dec29c5b092662909f125.png", - "112x63": "https://dl.flathub.org/repo/screenshots/org.sugarlabs.Maze-stable/112x63/org.sugarlabs.Maze-0cf71487936dec29c5b092662909f125.png", - "224x126": "https://dl.flathub.org/repo/screenshots/org.sugarlabs.Maze-stable/224x126/org.sugarlabs.Maze-0cf71487936dec29c5b092662909f125.png", - "752x423": "https://dl.flathub.org/repo/screenshots/org.sugarlabs.Maze-stable/752x423/org.sugarlabs.Maze-0cf71487936dec29c5b092662909f125.png" - }, - { - "624x351": "https://dl.flathub.org/repo/screenshots/org.sugarlabs.Maze-stable/624x351/org.sugarlabs.Maze-5d288daae5069cde2ffe86ab4a9285a7.png", - "112x63": "https://dl.flathub.org/repo/screenshots/org.sugarlabs.Maze-stable/112x63/org.sugarlabs.Maze-5d288daae5069cde2ffe86ab4a9285a7.png", - "224x126": "https://dl.flathub.org/repo/screenshots/org.sugarlabs.Maze-stable/224x126/org.sugarlabs.Maze-5d288daae5069cde2ffe86ab4a9285a7.png", - "752x423": "https://dl.flathub.org/repo/screenshots/org.sugarlabs.Maze-stable/752x423/org.sugarlabs.Maze-5d288daae5069cde2ffe86ab4a9285a7.png" - } - ], - "releases": [ - { - "timestamp": "1582070400", - "version": "30" + "beta": { + "description": "

Good at finding your way out of hard situations? Let's see! Try to make your way through an increasingly difficult path.

", + "screenshots": [ + { + "624x351": "https://dl.flathub.org/repo/screenshots/org.sugarlabs.Maze-stable/624x351/org.sugarlabs.Maze-4308958995b5f213eac85c7053e01a33.png", + "112x63": "https://dl.flathub.org/repo/screenshots/org.sugarlabs.Maze-stable/112x63/org.sugarlabs.Maze-4308958995b5f213eac85c7053e01a33.png", + "224x126": "https://dl.flathub.org/repo/screenshots/org.sugarlabs.Maze-stable/224x126/org.sugarlabs.Maze-4308958995b5f213eac85c7053e01a33.png", + "752x423": "https://dl.flathub.org/repo/screenshots/org.sugarlabs.Maze-stable/752x423/org.sugarlabs.Maze-4308958995b5f213eac85c7053e01a33.png" + }, + { + "624x351": "https://dl.flathub.org/repo/screenshots/org.sugarlabs.Maze-stable/624x351/org.sugarlabs.Maze-0cf71487936dec29c5b092662909f125.png", + "112x63": "https://dl.flathub.org/repo/screenshots/org.sugarlabs.Maze-stable/112x63/org.sugarlabs.Maze-0cf71487936dec29c5b092662909f125.png", + "224x126": "https://dl.flathub.org/repo/screenshots/org.sugarlabs.Maze-stable/224x126/org.sugarlabs.Maze-0cf71487936dec29c5b092662909f125.png", + "752x423": "https://dl.flathub.org/repo/screenshots/org.sugarlabs.Maze-stable/752x423/org.sugarlabs.Maze-0cf71487936dec29c5b092662909f125.png" + }, + { + "624x351": "https://dl.flathub.org/repo/screenshots/org.sugarlabs.Maze-stable/624x351/org.sugarlabs.Maze-5d288daae5069cde2ffe86ab4a9285a7.png", + "112x63": "https://dl.flathub.org/repo/screenshots/org.sugarlabs.Maze-stable/112x63/org.sugarlabs.Maze-5d288daae5069cde2ffe86ab4a9285a7.png", + "224x126": "https://dl.flathub.org/repo/screenshots/org.sugarlabs.Maze-stable/224x126/org.sugarlabs.Maze-5d288daae5069cde2ffe86ab4a9285a7.png", + "752x423": "https://dl.flathub.org/repo/screenshots/org.sugarlabs.Maze-stable/752x423/org.sugarlabs.Maze-5d288daae5069cde2ffe86ab4a9285a7.png" + } + ], + "releases": [ + { + "timestamp": "1582070400", + "version": "30" + } + ], + "content_rating": { + "type": "oars-1.1" + }, + "urls": { + "bugtracker": "https://github.com/sugarlabs/maze-activity", + "homepage": "https://github.com/sugarlabs/maze-activity" + }, + "icon": "https://dl.flathub.org/repo/appstream/x86_64/icons/128x128/org.sugarlabs.Maze.png", + "id": "org.sugarlabs.Maze", + "translation": { + "value": "org.sugarlabs.Maze", + "type": "gettext" + }, + "name": "Maze", + "summary": "A simple maze game, but this is the beta version", + "developer_name": "Sugar Labs Community", + "categories": ["Game"], + "kudos": ["HiDpiIcon"], + "project_license": "GPL-3.0-or-later", + "launchable": { + "value": "org.sugarlabs.Maze.desktop", + "type": "desktop-id" + }, + "bundle": { + "value": "app/org.sugarlabs.Maze/x86_64/stable", + "type": "flatpak", + "runtime": "org.gnome.Platform/x86_64/3.36", + "sdk": "org.gnome.Sdk/x86_64/3.36" } - ], - "content_rating": { - "type": "oars-1.1" - }, - "urls": { - "bugtracker": "https://github.com/sugarlabs/maze-activity", - "homepage": "https://github.com/sugarlabs/maze-activity" - }, - "icon": "https://dl.flathub.org/repo/appstream/x86_64/icons/128x128/org.sugarlabs.Maze.png", - "id": "org.sugarlabs.Maze", - "translation": { - "value": "org.sugarlabs.Maze", - "type": "gettext" }, - "name": "Maze", - "summary": "A simple maze game", - "developer_name": "Sugar Labs Community", - "categories": ["Game"], - "kudos": ["HiDpiIcon"], - "project_license": "GPL-3.0-or-later", - "launchable": { - "value": "org.sugarlabs.Maze.desktop", - "type": "desktop-id" - }, - "bundle": { - "value": "app/org.sugarlabs.Maze/x86_64/stable", - "type": "flatpak", - "runtime": "org.gnome.Platform/x86_64/3.36", - "sdk": "org.gnome.Sdk/x86_64/3.36" + "stable": { + "description": "

Good at finding your way out of hard situations? Let's see! Try to make your way through an increasingly difficult path.

", + "screenshots": [ + { + "624x351": "https://dl.flathub.org/repo/screenshots/org.sugarlabs.Maze-stable/624x351/org.sugarlabs.Maze-4308958995b5f213eac85c7053e01a33.png", + "112x63": "https://dl.flathub.org/repo/screenshots/org.sugarlabs.Maze-stable/112x63/org.sugarlabs.Maze-4308958995b5f213eac85c7053e01a33.png", + "224x126": "https://dl.flathub.org/repo/screenshots/org.sugarlabs.Maze-stable/224x126/org.sugarlabs.Maze-4308958995b5f213eac85c7053e01a33.png", + "752x423": "https://dl.flathub.org/repo/screenshots/org.sugarlabs.Maze-stable/752x423/org.sugarlabs.Maze-4308958995b5f213eac85c7053e01a33.png" + }, + { + "624x351": "https://dl.flathub.org/repo/screenshots/org.sugarlabs.Maze-stable/624x351/org.sugarlabs.Maze-0cf71487936dec29c5b092662909f125.png", + "112x63": "https://dl.flathub.org/repo/screenshots/org.sugarlabs.Maze-stable/112x63/org.sugarlabs.Maze-0cf71487936dec29c5b092662909f125.png", + "224x126": "https://dl.flathub.org/repo/screenshots/org.sugarlabs.Maze-stable/224x126/org.sugarlabs.Maze-0cf71487936dec29c5b092662909f125.png", + "752x423": "https://dl.flathub.org/repo/screenshots/org.sugarlabs.Maze-stable/752x423/org.sugarlabs.Maze-0cf71487936dec29c5b092662909f125.png" + }, + { + "624x351": "https://dl.flathub.org/repo/screenshots/org.sugarlabs.Maze-stable/624x351/org.sugarlabs.Maze-5d288daae5069cde2ffe86ab4a9285a7.png", + "112x63": "https://dl.flathub.org/repo/screenshots/org.sugarlabs.Maze-stable/112x63/org.sugarlabs.Maze-5d288daae5069cde2ffe86ab4a9285a7.png", + "224x126": "https://dl.flathub.org/repo/screenshots/org.sugarlabs.Maze-stable/224x126/org.sugarlabs.Maze-5d288daae5069cde2ffe86ab4a9285a7.png", + "752x423": "https://dl.flathub.org/repo/screenshots/org.sugarlabs.Maze-stable/752x423/org.sugarlabs.Maze-5d288daae5069cde2ffe86ab4a9285a7.png" + } + ], + "releases": [ + { + "timestamp": "1582070400", + "version": "30" + } + ], + "content_rating": { + "type": "oars-1.1" + }, + "urls": { + "bugtracker": "https://github.com/sugarlabs/maze-activity", + "homepage": "https://github.com/sugarlabs/maze-activity" + }, + "icon": "https://dl.flathub.org/repo/appstream/x86_64/icons/128x128/org.sugarlabs.Maze.png", + "id": "org.sugarlabs.Maze", + "translation": { + "value": "org.sugarlabs.Maze", + "type": "gettext" + }, + "name": "Maze", + "summary": "A simple maze game", + "developer_name": "Sugar Labs Community", + "categories": ["Game"], + "kudos": ["HiDpiIcon"], + "project_license": "GPL-3.0-or-later", + "launchable": { + "value": "org.sugarlabs.Maze.desktop", + "type": "desktop-id" + }, + "bundle": { + "value": "app/org.sugarlabs.Maze/x86_64/stable", + "type": "flatpak", + "runtime": "org.gnome.Platform/x86_64/3.36", + "sdk": "org.gnome.Sdk/x86_64/3.36" + } } } diff --git a/tests/results/test_appstream_by_appid_beta_only.json b/tests/results/test_appstream_by_appid_beta_only.json new file mode 100644 index 0000000..9a1d144 --- /dev/null +++ b/tests/results/test_appstream_by_appid_beta_only.json @@ -0,0 +1,60 @@ +{ + "beta": { + "description": "

Developers, Developers, Developers, Developers

", + "screenshots": [ + { + "624x351": "https://dl.flathub.org/repo/screenshots/com.only.in.beta.Repo-stable/624x351/com.only.in.beta.Repo-4308958995b5f213eac85c7053e01a33.png", + "112x63": "https://dl.flathub.org/repo/screenshots/com.only.in.beta.Repo-stable/112x63/com.only.in.beta.Repo-4308958995b5f213eac85c7053e01a33.png", + "224x126": "https://dl.flathub.org/repo/screenshots/com.only.in.beta.Repo-stable/224x126/com.only.in.beta.Repo-4308958995b5f213eac85c7053e01a33.png", + "752x423": "https://dl.flathub.org/repo/screenshots/com.only.in.beta.Repo-stable/752x423/com.only.in.beta.Repo-4308958995b5f213eac85c7053e01a33.png" + }, + { + "624x351": "https://dl.flathub.org/repo/screenshots/com.only.in.beta.Repo-stable/624x351/com.only.in.beta.Repo-0cf71487936dec29c5b092662909f125.png", + "112x63": "https://dl.flathub.org/repo/screenshots/com.only.in.beta.Repo-stable/112x63/com.only.in.beta.Repo-0cf71487936dec29c5b092662909f125.png", + "224x126": "https://dl.flathub.org/repo/screenshots/com.only.in.beta.Repo-stable/224x126/com.only.in.beta.Repo-0cf71487936dec29c5b092662909f125.png", + "752x423": "https://dl.flathub.org/repo/screenshots/com.only.in.beta.Repo-stable/752x423/com.only.in.beta.Repo-0cf71487936dec29c5b092662909f125.png" + }, + { + "624x351": "https://dl.flathub.org/repo/screenshots/com.only.in.beta.Repo-stable/624x351/com.only.in.beta.Repo-5d288daae5069cde2ffe86ab4a9285a7.png", + "112x63": "https://dl.flathub.org/repo/screenshots/com.only.in.beta.Repo-stable/112x63/com.only.in.beta.Repo-5d288daae5069cde2ffe86ab4a9285a7.png", + "224x126": "https://dl.flathub.org/repo/screenshots/com.only.in.beta.Repo-stable/224x126/com.only.in.beta.Repo-5d288daae5069cde2ffe86ab4a9285a7.png", + "752x423": "https://dl.flathub.org/repo/screenshots/com.only.in.beta.Repo-stable/752x423/com.only.in.beta.Repo-5d288daae5069cde2ffe86ab4a9285a7.png" + } + ], + "releases": [ + { + "timestamp": "1582070400", + "version": "30" + } + ], + "content_rating": { + "type": "oars-1.1" + }, + "icon": "https://dl.flathub.org/repo/appstream/x86_64/icons/128x128/com.only.in.beta.Repo.png", + "id": "com.only.in.beta.Repo", + "translation": { + "value": "com.only.in.beta.Repo", + "type": "gettext" + }, + "name": "Beta app", + "summary": "A simple beta test app", + "developer_name": "Developer", + "categories": [ + "Game" + ], + "kudos": [ + "HiDpiIcon" + ], + "project_license": "GPL-3.0-or-later", + "launchable": { + "value": "com.only.in.beta.Repo.desktop", + "type": "desktop-id" + }, + "bundle": { + "value": "app/com.only.in.beta.Repo/x86_64/stable", + "type": "flatpak", + "runtime": "org.gnome.Platform/x86_64/3.36", + "sdk": "org.gnome.Sdk/x86_64/3.36" + } + } +} \ No newline at end of file diff --git a/tests/results/test_appstream_by_appid_stable_only.json b/tests/results/test_appstream_by_appid_stable_only.json new file mode 100644 index 0000000..9e10bc8 --- /dev/null +++ b/tests/results/test_appstream_by_appid_stable_only.json @@ -0,0 +1,142 @@ +{ + "stable": { + "description": "

AnyDesk ensures secure and reliable remote desktop connections for IT professionals and on-the-go individuals alike.

NOTE: This wrapper is not verified by, affiliated with, or supported by AnyDesk.

", + "screenshots": [ + { + "624x351": "https://dl.flathub.org/repo/screenshots/com.anydesk.Anydesk-stable/624x351/com.anydesk.Anydesk-b8f4a58c33a1e1603bad8a835f244173.png", + "112x63": "https://dl.flathub.org/repo/screenshots/com.anydesk.Anydesk-stable/112x63/com.anydesk.Anydesk-b8f4a58c33a1e1603bad8a835f244173.png", + "224x126": "https://dl.flathub.org/repo/screenshots/com.anydesk.Anydesk-stable/224x126/com.anydesk.Anydesk-b8f4a58c33a1e1603bad8a835f244173.png", + "752x423": "https://dl.flathub.org/repo/screenshots/com.anydesk.Anydesk-stable/752x423/com.anydesk.Anydesk-b8f4a58c33a1e1603bad8a835f244173.png" + } + ], + "releases": [ + { + "timestamp": "1598313600", + "version": "6.0.1" + }, + { + "timestamp": "1595894400", + "version": "6.0.0" + }, + { + "timestamp": "1588896000", + "version": "5.5.6" + }, + { + "timestamp": "1587340800", + "version": "5.5.5" + }, + { + "timestamp": "1582588800", + "version": "5.5.4" + }, + { + "timestamp": "1582243200", + "version": "5.5.3" + }, + { + "timestamp": "1581897600", + "version": "5.5.2" + }, + { + "timestamp": "1575331200", + "version": "5.5.1" + }, + { + "timestamp": "1574035200", + "version": "5.5.0" + }, + { + "timestamp": "1572480000", + "version": "5.4.1" + }, + { + "timestamp": "1571875200", + "version": "5.4.0" + }, + { + "timestamp": "1566345600", + "version": "5.1.2" + }, + { + "timestamp": "1560384000", + "version": "5.1.1" + }, + { + "timestamp": "1541721600", + "version": "4.0.1" + }, + { + "timestamp": "1537142400", + "version": "4.0.0" + }, + { + "timestamp": "1528934400", + "version": "2.9.6" + }, + { + "timestamp": "1505347200", + "version": "2.9.5" + } + ], + "content_rating": { + "drugs-alcohol": "none", + "drugs-narcotics": "none", + "drugs-tobacco": "none", + "language-discrimination": "none", + "language-humor": "none", + "language-profanity": "none", + "money-gambling": "none", + "money-purchasing": "none", + "sex-adultery": "none", + "sex-appearance": "none", + "sex-homosexuality": "none", + "sex-nudity": "none", + "sex-prostitution": "none", + "sex-themes": "none", + "social-audio": "none", + "social-chat": "intense", + "social-contacts": "none", + "social-info": "none", + "social-location": "none", + "type": "oars-1.1", + "violence-bloodshed": "none", + "violence-cartoon": "none", + "violence-desecration": "none", + "violence-fantasy": "none", + "violence-realistic": "none", + "violence-sexual": "none", + "violence-slavery": "none", + "violence-worship": "none" + }, + "urls": { + "bugtracker": "https://github.com/flathub/com.anydesk.Anydesk/issues", + "homepage": "https://www.anydesk.com" + }, + "icon": "https://dl.flathub.org/repo/appstream/x86_64/icons/128x128/com.anydesk.Anydesk.png", + "id": "com.anydesk.Anydesk", + "name": "AnyDesk", + "summary": "Connect to a computer remotely", + "developer_name": "AnyDesk Software GmbH", + "categories": [ + "Network" + ], + "kudos": [ + "HiDpiIcon" + ], + "project_license": "LicenseRef-proprietary", + "launchable": { + "value": "com.anydesk.Anydesk.desktop", + "type": "desktop-id" + }, + "bundle": { + "value": "app/com.anydesk.Anydesk/x86_64/stable", + "type": "flatpak", + "runtime": "org.freedesktop.Platform/x86_64/20.08", + "sdk": "org.freedesktop.Sdk/x86_64/20.08" + }, + "metadata": { + "X-Flatpak-Tags": "proprietary" + } + } +} \ No newline at end of file diff --git a/tests/results/test_feed_by_new.xml b/tests/results/test_feed_by_new.xml index 68aa7ba..1bb7ebc 100644 --- a/tests/results/test_feed_by_new.xml +++ b/tests/results/test_feed_by_new.xml @@ -1,2 +1,2 @@ -Flathub – recently added applicationshttps://flathub.org/apps/collection/newApplications recently published on Flathubhttp://www.rssboard.org/rss-specificationpython-feedgenenWed, 27 Jan 2021 16:25:03 +0000AnyDeskhttps://flathub.org/apps/details/com.anydesk.Anydesk<img src="https://dl.flathub.org/repo/appstream/x86_64/icons/128x128/com.anydesk.Anydesk.png"><p>Connect to a computer remotely</p><p><p>AnyDesk ensures secure and reliable remote desktop connections for IT professionals and on-the-go individuals alike.</p><p>NOTE: This wrapper is not verified by, affiliated with, or supported by AnyDesk.</p></p><h3>Additional information:</h3><ul><li>Developer: AnyDesk Software GmbH</li><li>Version: 6.0.1</ul><img src="https://dl.flathub.org/repo/screenshots/com.anydesk.Anydesk-stable/624x351/com.anydesk.Anydesk-b8f4a58c33a1e1603bad8a835f244173.png">Mon, 18 Jan 2021 12:43:10 +0000WPS Officehttps://flathub.org/apps/details/com.wps.Office<img src="https://dl.flathub.org/repo/appstream/x86_64/icons/128x128/com.wps.Office.png"><p>WPS Office Suite</p><p><p>WPS Office including Writer, Presentation and Spreadsheets, is a powerful office suite, which is able to process word file, produce wonderful slides, and analyze data as well. It is deeply compatible with all of the latest Microsoft Office file formats. It can easily open and read the documents created with Microsoft Office.</p><p>NOTE: This wrapper is not verified by, affiliated with, or supported by Kingsoft Office Corporation</p></p><h3>Additional information:</h3><ul><li>Developer: Kingsoft Office Corporation</li><li>Version: 11.1.0.9719</ul><img src="https://dl.flathub.org/repo/screenshots/com.wps.Office-stable/624x351/com.wps.Office-3f78a399034d6606d866e875e6938d51.png"><img src="https://dl.flathub.org/repo/screenshots/com.wps.Office-stable/624x351/com.wps.Office-32f9654272b966cb0be4a4cd14e8d072.png"><img src="https://dl.flathub.org/repo/screenshots/com.wps.Office-stable/624x351/com.wps.Office-f25c528d533cf5a62d3093a0d4656007.png">Mon, 18 Jan 2021 12:42:48 +0000Mazehttps://flathub.org/apps/details/org.sugarlabs.Maze<img src="https://dl.flathub.org/repo/appstream/x86_64/icons/128x128/org.sugarlabs.Maze.png"><p>A simple maze game</p><p><p>Good at finding your way out of hard situations? Let's see! Try to make your way through an increasingly difficult path.</p></p><h3>Additional information:</h3><ul><li>Developer: Sugar Labs Community</li><li>Version: 30</ul><img src="https://dl.flathub.org/repo/screenshots/org.sugarlabs.Maze-stable/624x351/org.sugarlabs.Maze-4308958995b5f213eac85c7053e01a33.png"><img src="https://dl.flathub.org/repo/screenshots/org.sugarlabs.Maze-stable/624x351/org.sugarlabs.Maze-0cf71487936dec29c5b092662909f125.png"><img src="https://dl.flathub.org/repo/screenshots/org.sugarlabs.Maze-stable/624x351/org.sugarlabs.Maze-5d288daae5069cde2ffe86ab4a9285a7.png">Mon, 18 Jan 2021 12:41:20 +0000 +Flathub – recently added applicationshttps://flathub.org/apps/collection/newApplications recently published on Flathubhttp://www.rssboard.org/rss-specificationpython-feedgenenWed, 27 Jan 2021 16:25:03 +0000AnyDeskhttps://flathub.org/apps/details/com.anydesk.Anydesk<img src="https://dl.flathub.org/repo/appstream/x86_64/icons/128x128/com.anydesk.Anydesk.png"><p>Connect to a computer remotely</p><p><p>AnyDesk ensures secure and reliable remote desktop connections for IT professionals and on-the-go individuals alike.</p><p>NOTE: This wrapper is not verified by, affiliated with, or supported by AnyDesk.</p></p><h3>Additional information:</h3><ul><li>Developer: AnyDesk Software GmbH</li><li>Version: 6.0.1</ul><img src="https://dl.flathub.org/repo/screenshots/com.anydesk.Anydesk-stable/624x351/com.anydesk.Anydesk-b8f4a58c33a1e1603bad8a835f244173.png">Mon, 18 Jan 2021 12:43:10 +0000WPS Officehttps://flathub.org/apps/details/com.wps.Office<img src="https://www.wps.com/assets/mediahub/WPS-Office-Mobile.png"><p>WPS Office Suite</p><p><p>WPS Office including Writer, Presentation and Spreadsheets, is a powerful office suite, which is able to process word file, produce wonderful slides, and analyze data as well. It is deeply compatible with all of the latest Microsoft Office file formats. It can easily open and read the documents created with Microsoft Office.</p><p>NOTE: This wrapper is not verified by, affiliated with, or supported by Kingsoft Office Corporation</p></p><h3>Additional information:</h3><ul><li>Developer: Kingsoft Office Corporation</li><li>Version: 11.1.0.9719</ul><img src="https://dl.flathub.org/repo/screenshots/com.wps.Office-stable/624x351/com.wps.Office-3f78a399034d6606d866e875e6938d51.png"><img src="https://dl.flathub.org/repo/screenshots/com.wps.Office-stable/624x351/com.wps.Office-32f9654272b966cb0be4a4cd14e8d072.png"><img src="https://dl.flathub.org/repo/screenshots/com.wps.Office-stable/624x351/com.wps.Office-f25c528d533cf5a62d3093a0d4656007.png">Mon, 18 Jan 2021 12:42:48 +0000Mazehttps://flathub.org/apps/details/org.sugarlabs.Maze<img src="https://dl.flathub.org/repo/appstream/x86_64/icons/128x128/org.sugarlabs.Maze.png"><p>A simple maze game</p><p><p>Good at finding your way out of hard situations? Let's see! Try to make your way through an increasingly difficult path.</p></p><h3>Additional information:</h3><ul><li>Developer: Sugar Labs Community</li><li>Version: 30</ul><img src="https://dl.flathub.org/repo/screenshots/org.sugarlabs.Maze-stable/624x351/org.sugarlabs.Maze-4308958995b5f213eac85c7053e01a33.png"><img src="https://dl.flathub.org/repo/screenshots/org.sugarlabs.Maze-stable/624x351/org.sugarlabs.Maze-0cf71487936dec29c5b092662909f125.png"><img src="https://dl.flathub.org/repo/screenshots/org.sugarlabs.Maze-stable/624x351/org.sugarlabs.Maze-5d288daae5069cde2ffe86ab4a9285a7.png">Mon, 18 Jan 2021 12:41:20 +0000 diff --git a/tests/results/test_feed_by_recently_updated.xml b/tests/results/test_feed_by_recently_updated.xml index e65752f..cc61d9c 100644 --- a/tests/results/test_feed_by_recently_updated.xml +++ b/tests/results/test_feed_by_recently_updated.xml @@ -1,2 +1,2 @@ -Flathub – recently updated applicationshttps://flathub.org/apps/collection/recently-updatedRecently updated applications published on Flathubhttp://www.rssboard.org/rss-specificationpython-feedgenenMon, 18 Jan 2021 13:42:57 +0000AnyDeskhttps://flathub.org/apps/details/com.anydesk.Anydesk<img src="https://dl.flathub.org/repo/appstream/x86_64/icons/128x128/com.anydesk.Anydesk.png"><p>Connect to a computer remotely</p><p><p>AnyDesk ensures secure and reliable remote desktop connections for IT professionals and on-the-go individuals alike.</p><p>NOTE: This wrapper is not verified by, affiliated with, or supported by AnyDesk.</p></p><h3>Additional information:</h3><ul><li>Developer: AnyDesk Software GmbH</li><li>Version: 6.0.1</ul><img src="https://dl.flathub.org/repo/screenshots/com.anydesk.Anydesk-stable/624x351/com.anydesk.Anydesk-b8f4a58c33a1e1603bad8a835f244173.png">Mon, 18 Jan 2021 12:43:10 +0000WPS Officehttps://flathub.org/apps/details/com.wps.Office<img src="https://dl.flathub.org/repo/appstream/x86_64/icons/128x128/com.wps.Office.png"><p>WPS Office Suite</p><p><p>WPS Office including Writer, Presentation and Spreadsheets, is a powerful office suite, which is able to process word file, produce wonderful slides, and analyze data as well. It is deeply compatible with all of the latest Microsoft Office file formats. It can easily open and read the documents created with Microsoft Office.</p><p>NOTE: This wrapper is not verified by, affiliated with, or supported by Kingsoft Office Corporation</p></p><h3>Additional information:</h3><ul><li>Developer: Kingsoft Office Corporation</li><li>Version: 11.1.0.9719</ul><img src="https://dl.flathub.org/repo/screenshots/com.wps.Office-stable/624x351/com.wps.Office-3f78a399034d6606d866e875e6938d51.png"><img src="https://dl.flathub.org/repo/screenshots/com.wps.Office-stable/624x351/com.wps.Office-32f9654272b966cb0be4a4cd14e8d072.png"><img src="https://dl.flathub.org/repo/screenshots/com.wps.Office-stable/624x351/com.wps.Office-f25c528d533cf5a62d3093a0d4656007.png">Mon, 18 Jan 2021 12:42:48 +0000Mazehttps://flathub.org/apps/details/org.sugarlabs.Maze<img src="https://dl.flathub.org/repo/appstream/x86_64/icons/128x128/org.sugarlabs.Maze.png"><p>A simple maze game</p><p><p>Good at finding your way out of hard situations? Let's see! Try to make your way through an increasingly difficult path.</p></p><h3>Additional information:</h3><ul><li>Developer: Sugar Labs Community</li><li>Version: 30</ul><img src="https://dl.flathub.org/repo/screenshots/org.sugarlabs.Maze-stable/624x351/org.sugarlabs.Maze-4308958995b5f213eac85c7053e01a33.png"><img src="https://dl.flathub.org/repo/screenshots/org.sugarlabs.Maze-stable/624x351/org.sugarlabs.Maze-0cf71487936dec29c5b092662909f125.png"><img src="https://dl.flathub.org/repo/screenshots/org.sugarlabs.Maze-stable/624x351/org.sugarlabs.Maze-5d288daae5069cde2ffe86ab4a9285a7.png">Mon, 18 Jan 2021 12:41:20 +0000 +Flathub – recently updated applicationshttps://flathub.org/apps/collection/recently-updatedRecently updated applications published on Flathubhttp://www.rssboard.org/rss-specificationpython-feedgenenMon, 18 Jan 2021 13:42:57 +0000AnyDeskhttps://flathub.org/apps/details/com.anydesk.Anydesk<img src="https://dl.flathub.org/repo/appstream/x86_64/icons/128x128/com.anydesk.Anydesk.png"><p>Connect to a computer remotely</p><p><p>AnyDesk ensures secure and reliable remote desktop connections for IT professionals and on-the-go individuals alike.</p><p>NOTE: This wrapper is not verified by, affiliated with, or supported by AnyDesk.</p></p><h3>Additional information:</h3><ul><li>Developer: AnyDesk Software GmbH</li><li>Version: 6.0.1</ul><img src="https://dl.flathub.org/repo/screenshots/com.anydesk.Anydesk-stable/624x351/com.anydesk.Anydesk-b8f4a58c33a1e1603bad8a835f244173.png">Mon, 18 Jan 2021 12:43:10 +0000WPS Officehttps://flathub.org/apps/details/com.wps.Office<img src="https://www.wps.com/assets/mediahub/WPS-Office-Mobile.png"><p>WPS Office Suite</p><p><p>WPS Office including Writer, Presentation and Spreadsheets, is a powerful office suite, which is able to process word file, produce wonderful slides, and analyze data as well. It is deeply compatible with all of the latest Microsoft Office file formats. It can easily open and read the documents created with Microsoft Office.</p><p>NOTE: This wrapper is not verified by, affiliated with, or supported by Kingsoft Office Corporation</p></p><h3>Additional information:</h3><ul><li>Developer: Kingsoft Office Corporation</li><li>Version: 11.1.0.9719</ul><img src="https://dl.flathub.org/repo/screenshots/com.wps.Office-stable/624x351/com.wps.Office-3f78a399034d6606d866e875e6938d51.png"><img src="https://dl.flathub.org/repo/screenshots/com.wps.Office-stable/624x351/com.wps.Office-32f9654272b966cb0be4a4cd14e8d072.png"><img src="https://dl.flathub.org/repo/screenshots/com.wps.Office-stable/624x351/com.wps.Office-f25c528d533cf5a62d3093a0d4656007.png">Mon, 18 Jan 2021 12:42:48 +0000Mazehttps://flathub.org/apps/details/org.sugarlabs.Maze<img src="https://dl.flathub.org/repo/appstream/x86_64/icons/128x128/org.sugarlabs.Maze.png"><p>A simple maze game</p><p><p>Good at finding your way out of hard situations? Let's see! Try to make your way through an increasingly difficult path.</p></p><h3>Additional information:</h3><ul><li>Developer: Sugar Labs Community</li><li>Version: 30</ul><img src="https://dl.flathub.org/repo/screenshots/org.sugarlabs.Maze-stable/624x351/org.sugarlabs.Maze-4308958995b5f213eac85c7053e01a33.png"><img src="https://dl.flathub.org/repo/screenshots/org.sugarlabs.Maze-stable/624x351/org.sugarlabs.Maze-0cf71487936dec29c5b092662909f125.png"><img src="https://dl.flathub.org/repo/screenshots/org.sugarlabs.Maze-stable/624x351/org.sugarlabs.Maze-5d288daae5069cde2ffe86ab4a9285a7.png">Mon, 18 Jan 2021 12:41:20 +0000 \ No newline at end of file diff --git a/tests/results/test_list_appstream_beta.json b/tests/results/test_list_appstream_beta.json new file mode 100644 index 0000000..82fa84d --- /dev/null +++ b/tests/results/test_list_appstream_beta.json @@ -0,0 +1 @@ +["org.sugarlabs.Maze"] diff --git a/tests/results/test_list_appstream_stable_and_beta.json b/tests/results/test_list_appstream_stable_and_beta.json new file mode 100644 index 0000000..f7b7026 --- /dev/null +++ b/tests/results/test_list_appstream_stable_and_beta.json @@ -0,0 +1,6 @@ +[ + "com.anydesk.Anydesk", + "com.only.in.beta.Repo", + "com.wps.Office", + "org.sugarlabs.Maze" +] diff --git a/tests/results/test_summary_by_appid.json b/tests/results/test_summary_by_appid.json index a9d1ba4..af0796a 100644 --- a/tests/results/test_summary_by_appid.json +++ b/tests/results/test_summary_by_appid.json @@ -1,14 +1,26 @@ { - "arches": [ - "x86_64" - ], - "timestamp": 1610973680, - "download_size": 1024, - "installed_size": 371, - "metadata": { - "name": "org.sugarlabs.Maze", - "runtime": "org.freedesktop.Platform/x86_64/20.08", - "sdk": "org.freedesktop.Sdk/x86_64/20.08", - "permissions": {} + "beta": { + "arches": ["x86_64"], + "timestamp": 1610973680, + "download_size": 1024, + "installed_size": 371, + "metadata": { + "name": "org.sugarlabs.Maze", + "runtime": "org.freedesktop.Platform/x86_64/20.08", + "sdk": "org.freedesktop.Sdk/x86_64/20.08", + "permissions": {} + } + }, + "stable": { + "arches": ["x86_64"], + "timestamp": 1610973680, + "download_size": 1024, + "installed_size": 371, + "metadata": { + "name": "org.sugarlabs.Maze", + "runtime": "org.freedesktop.Platform/x86_64/20.08", + "sdk": "org.freedesktop.Sdk/x86_64/20.08", + "permissions": {} + } } } diff --git a/tests/results/test_summary_by_appid_beta_only.json b/tests/results/test_summary_by_appid_beta_only.json new file mode 100644 index 0000000..0ecb4a6 --- /dev/null +++ b/tests/results/test_summary_by_appid_beta_only.json @@ -0,0 +1,14 @@ +{ + "beta": { + "arches": ["x86_64"], + "timestamp": 1610973680, + "download_size": 1024, + "installed_size": 371, + "metadata": { + "name": "com.only.in.beta.Repo", + "runtime": "org.freedesktop.Platform/x86_64/20.08", + "sdk": "org.freedesktop.Sdk/x86_64/20.08", + "permissions": {} + } + } +} diff --git a/tests/results/test_summary_by_appid_stable_only.json b/tests/results/test_summary_by_appid_stable_only.json new file mode 100644 index 0000000..4d5a966 --- /dev/null +++ b/tests/results/test_summary_by_appid_stable_only.json @@ -0,0 +1,16 @@ +{ + "stable": { + "arches": [ + "x86_64" + ], + "timestamp": 1610973790, + "download_size": 1024, + "installed_size": 371, + "metadata": { + "name": "com.anydesk.Anydesk", + "runtime": "org.freedesktop.Platform/x86_64/20.08", + "sdk": "org.freedesktop.Sdk/x86_64/20.08", + "permissions": {} + } + } +} \ No newline at end of file