From 2e3a84b9ff11bca1e4b29ee8c2cdf274f92ef8e3 Mon Sep 17 00:00:00 2001 From: James O'Claire Date: Wed, 22 Jan 2025 15:48:12 +0800 Subject: [PATCH] Match multiple developer ids, sometimes will work for both ios and android --- backend/api_app/controllers/apps.py | 43 ++++++++++++++++--- backend/api_app/models.py | 14 +++++- backend/dbcon/queries.py | 13 +++++- backend/dbcon/sql/query_single_developer.sql | 26 +++++------ .../developers/[developer]/+page.server.ts | 4 +- .../developers/[developer]/+page.svelte | 33 +++++++++++--- frontend/src/types.ts | 14 +++++- 7 files changed, 115 insertions(+), 32 deletions(-) diff --git a/backend/api_app/controllers/apps.py b/backend/api_app/controllers/apps.py index 03c4b73..ad238fd 100644 --- a/backend/api_app/controllers/apps.py +++ b/backend/api_app/controllers/apps.py @@ -27,6 +27,7 @@ Category, Collection, DeveloperApps, + PlatformDeveloper, SDKsDetails, ) from config import get_logger @@ -467,18 +468,50 @@ async def get_developer_apps(self: Self, developer_id: str) -> DeveloperApps: apps_df = get_single_developer(developer_id) if apps_df.empty: - msg = f"Store ID not found: {developer_id!r}" + msg = f"Developer ID not found: {developer_id!r}" raise NotFoundException( msg, status_code=404, ) - developer_name = apps_df.to_dict(orient="records")[0]["developer_name"] - apps_dict = apps_df.to_dict(orient="records") + + developer_url = apps_df[apps_df["developer_url"].notna()].to_dict( + orient="records" + )[0]["developer_url"] + + ios_df = apps_df[apps_df["store"] == "Apple App Store"] + google_df = apps_df[apps_df["store"] == "Google Play"] + if not google_df.empty: + google_developer_name = google_df.to_dict(orient="records")[0][ + "developer_name" + ] + google_developer_id = google_df.to_dict(orient="records")[0]["developer_id"] + else: + google_developer_name = "Google developer not found" + google_developer_id = None + if not ios_df.empty: + apple_developer_name = ios_df.to_dict(orient="records")[0]["developer_name"] + apple_developer_id = ios_df.to_dict(orient="records")[0]["developer_id"] + else: + apple_developer_name = "Apple developer not found" + apple_developer_id = None + developer_name = google_developer_name or apple_developer_name + google_apps_dict = google_df.to_dict(orient="records") + apple_apps_dict = ios_df.to_dict(orient="records") developer_apps = DeveloperApps( - developer_id=developer_id, + google=PlatformDeveloper( + developer_id=google_developer_id, + developer_name=google_developer_name, + developer_url=developer_url, + apps=AppGroup(title="Google", apps=google_apps_dict), + ), + apple=PlatformDeveloper( + developer_id=apple_developer_id, + developer_name=apple_developer_name, + developer_url=developer_url, + apps=AppGroup(title="Apple", apps=apple_apps_dict), + ), title=developer_name, - apps=apps_dict, ) duration = round((time.perf_counter() * 1000 - start), 2) logger.info(f"{self.path}/developers/{developer_id} took {duration}ms") diff --git a/backend/api_app/models.py b/backend/api_app/models.py index b95928f..35da554 100644 --- a/backend/api_app/models.py +++ b/backend/api_app/models.py @@ -68,6 +68,16 @@ class Category: google: AppGroup +@dataclass +class PlatformDeveloper: + """Developer details for a specific platform.""" + + developer_id: str + developer_name: str + developer_url: str + apps: AppGroup + + @dataclass class DeveloperApps: """A developer's list of apps. @@ -75,9 +85,9 @@ class DeveloperApps: Note: This is platform specific. """ - developer_id: str + google: PlatformDeveloper + apple: PlatformDeveloper title: str - apps: list[AppDetail] @dataclass diff --git a/backend/dbcon/queries.py b/backend/dbcon/queries.py index b8c5124..c9c8ec1 100644 --- a/backend/dbcon/queries.py +++ b/backend/dbcon/queries.py @@ -421,7 +421,18 @@ def get_tag_source_totals() -> pd.DataFrame: def clean_app_df(df: pd.DataFrame) -> pd.DataFrame: - """Apply generic cleaning for a DF with app data from store_apps table.""" + """Apply generic cleaning for a DF with app data from store_apps table. + + Required columns: + - store + - store_id + - developer_id + - installs + - review_count + - rating_count + - rating + + """ df["store"] = df["store"].replace({1: "Google Play", 2: "Apple App Store"}) string_nums = ["installs", "review_count", "rating_count"] for col in string_nums: diff --git a/backend/dbcon/sql/query_single_developer.sql b/backend/dbcon/sql/query_single_developer.sql index d156c75..c92c057 100644 --- a/backend/dbcon/sql/query_single_developer.sql +++ b/backend/dbcon/sql/query_single_developer.sql @@ -1,18 +1,12 @@ -SELECT - sa.*, - d.name AS developer_name, - pd.url AS developer_url, - d.store AS developer_store +SELECT * FROM - app_urls_map AS aum -LEFT JOIN pub_domains AS pd - ON - aum.pub_domain = pd.id -LEFT JOIN store_apps AS sa - ON - aum.store_app = sa.id -LEFT JOIN developers AS d - ON - sa.developer = d.id + developer_store_apps WHERE - d.developer_id = :developer_id; + developer_id = :developer_id + OR domain_id IN ( + SELECT DISTINCT dd.domain_id + FROM + developer_store_apps AS dd + WHERE + dd.developer_id = :developer_id + ); diff --git a/frontend/src/routes/developers/[developer]/+page.server.ts b/frontend/src/routes/developers/[developer]/+page.server.ts index b558065..235c500 100644 --- a/frontend/src/routes/developers/[developer]/+page.server.ts +++ b/frontend/src/routes/developers/[developer]/+page.server.ts @@ -9,7 +9,7 @@ export const load: PageServerLoad = async ({ params, locals }) => { console.log(`load started developer=${developerValue}`); try { return { - results: res + devs: res .then((resp) => { if (resp.status === 200) { return resp.json(); @@ -32,7 +32,7 @@ export const load: PageServerLoad = async ({ params, locals }) => { } catch (error) { console.error('Failed to load data:', error); return { - results: {}, + devs: {}, status: 500, error: 'Failed to load trending apps' }; diff --git a/frontend/src/routes/developers/[developer]/+page.svelte b/frontend/src/routes/developers/[developer]/+page.svelte index 9b73682..f7a3b7d 100644 --- a/frontend/src/routes/developers/[developer]/+page.svelte +++ b/frontend/src/routes/developers/[developer]/+page.svelte @@ -11,7 +11,7 @@ - {#await data.results then dev} + {#await data.devs then dev} {dev.title} Android Trends | {page.params.developer} | AppGoblin Developer Data
- {#await data.results} + {#await data.devs}
Loading...
@@ -60,9 +60,32 @@ {#if typeof devs == 'string'} Failed to load developer {:else} -

Apps: {devs.title}

- -

+

{devs.title}

+

Google Apps: {devs.google.developer_name}

+

+ Matched Developer ID: {devs.google.developer_id} +
+ Matched Developer URL: + + {devs.google.developer_url} + +

+ +
+

Apple Apps: {devs.apple.developer_name}

+

+ Matched Developer ID: {devs.apple.developer_id} +
+ Matched Developer URL: + + {devs.apple.developer_url} + +

+ {/if} {:catch error}

{error.message}

diff --git a/frontend/src/types.ts b/frontend/src/types.ts index 9aab42e..222a791 100644 --- a/frontend/src/types.ts +++ b/frontend/src/types.ts @@ -32,8 +32,20 @@ export interface CategoryResponse { error?: string; } +export interface PlatformDeveloper { + title: string; + developer_id: string; + developer_name: string; + developer_url: string; + apps: AppGroup; +} + export interface DeveloperResponse { - results: AppGroup; + devs: { + title: string; + google: PlatformDeveloper; + apple: PlatformDeveloper; + }; status?: number; error?: string; }