From 1b4691b2c8903e71ffbef23f723b1400d8f09c30 Mon Sep 17 00:00:00 2001 From: djs Date: Sun, 21 Sep 2025 10:42:41 +0200 Subject: [PATCH 1/3] Basic implementation of storing platform for activity --- oblivionis/bot.py | 39 +++++++++++++++++++++++++++++++-------- oblivionis/storage.py | 1 + 2 files changed, 32 insertions(+), 8 deletions(-) diff --git a/oblivionis/bot.py b/oblivionis/bot.py index d9567f4..7aeb006 100644 --- a/oblivionis/bot.py +++ b/oblivionis/bot.py @@ -29,6 +29,13 @@ def are_activities_equal(a, b) -> bool: return x.name == y.name and x.application_id == y.application_id return False +def application_id_from_activity(activity) -> str: + """Returns application_id if present. Fallsback to name if not.""" + if hasattr(activity, "application_id"): + return activity.application_id + # ps5 games seem to be missing application_id + logger.warning("Activity %s does not have application_id, using name instead...", activity.name) + return activity.name def game_from_activity(activity) -> str: if activity.name == "Steam Deck": @@ -47,10 +54,19 @@ def get_game_activity(activities): def get_stored_activity(member, activity) -> dict | None: """Get an applicable activity from the in-memory storage.""" stored = activities.pop(member.id, None) - if stored and stored["application_id"] == activity.application_id: + if stored and stored["application_id"] == application_id_from_activity(activity): return stored return None +def platform_from_activity(activity) -> str: + """Get the platform from the activity. Fallbacks to pc.""" + if activity.name == "Steam Deck": + return "steamdeck" + platform = activity.platform or "pc" + if platform == "desktop": + # some games say "desktop" apparently + platform = "pc" + return platform @bot.event async def on_guild_available(guild): @@ -87,10 +103,14 @@ async def on_presence_update(before, after): duration = datetime.datetime.now(datetime.UTC) - start duration_seconds = round(duration.total_seconds()) + game_name = game_from_activity(activity) + platform_name = platform_from_activity(activity) + logger.info( - "Member %s has stopped playing %s after %s seconds", + "Member %s has stopped playing %s (%s) after %s seconds", after, - game_from_activity(activity), + game_name, + platform_name, duration_seconds, ) user, user_created = storage.User.get_or_create( @@ -100,26 +120,29 @@ async def on_presence_update(before, after): logger.info("Added new user '%s' to database", before.name) game, game_created = storage.Game.get_or_create( - name=game_from_activity(activity) + name=game_name ) if game_created: logger.info("Added new game '%s' to database", game.name) - storage.Activity.create(user=user, game=game, seconds=duration_seconds) + storage.Activity.create(user=user, game=game, seconds=duration_seconds, platform=platform_name) elif after_activity is not None: + application_id = application_id_from_activity(after_activity) if ( after.id not in activities - or activities[after.id]["application_id"] != after_activity.application_id + or activities[after.id]["application_id"] != application_id ): activities[after.id] = { - "application_id": after_activity.application_id, + "application_id": application_id, "name": after_activity.name, "start": after_activity.start, "timestamp": datetime.datetime.now(datetime.UTC), } + logger.info( - "Member %s has started playing %s", + "Member %s has started playing %s (%s)", after, game_from_activity(after_activity), + platform_from_activity(after_activity), ) diff --git a/oblivionis/storage.py b/oblivionis/storage.py index 6d61a97..0f7cb55 100644 --- a/oblivionis/storage.py +++ b/oblivionis/storage.py @@ -37,6 +37,7 @@ class Activity(BaseModel): user = ForeignKeyField(User) game = ForeignKeyField(Game) seconds = IntegerField() + platform = CharField(default="pc") def connect_db(): From d8a5574de4a84f84046ba36c83197957ca217c25 Mon Sep 17 00:00:00 2001 From: djs Date: Sun, 21 Sep 2025 11:05:03 +0200 Subject: [PATCH 2/3] Alter table to add platform column for existing databases --- oblivionis/storage.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/oblivionis/storage.py b/oblivionis/storage.py index 0f7cb55..5d2d6ec 100644 --- a/oblivionis/storage.py +++ b/oblivionis/storage.py @@ -43,3 +43,5 @@ class Activity(BaseModel): def connect_db(): db.connect() db.create_tables([User, Game, Activity]) + # add platform column to activity table if it does not exist + db.execute_sql("ALTER TABLE activity ADD COLUMN IF NOT EXISTS platform VARCHAR DEFAULT 'pc'") \ No newline at end of file From 983e135beeafc8cdbcd5406da11fef9edc7154bf Mon Sep 17 00:00:00 2001 From: djs Date: Sun, 21 Sep 2025 11:14:54 +0200 Subject: [PATCH 3/3] Changelog --- CHANGELOG.md | 6 ++++++ oblivionis/bot.py | 6 ++++-- 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 7887773..b2f0a1f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,11 @@ # Changelog +## [X.X.X] - 202X-XX-XX + +### Added + +- Storing platform from Discord's `activity.platform` field (or a special case for Steam Deck). Defaults to `pc` if not specified. Existing activity will have `pc` set as their platform. + ## [0.2.0] - 2025-04-23 ### Added diff --git a/oblivionis/bot.py b/oblivionis/bot.py index 7aeb006..21e9275 100644 --- a/oblivionis/bot.py +++ b/oblivionis/bot.py @@ -33,7 +33,7 @@ def application_id_from_activity(activity) -> str: """Returns application_id if present. Fallsback to name if not.""" if hasattr(activity, "application_id"): return activity.application_id - # ps5 games seem to be missing application_id + # When playing on PS5, application_id seems to be missing logger.warning("Activity %s does not have application_id, using name instead...", activity.name) return activity.name @@ -61,10 +61,12 @@ def get_stored_activity(member, activity) -> dict | None: def platform_from_activity(activity) -> str: """Get the platform from the activity. Fallbacks to pc.""" if activity.name == "Steam Deck": + # Decky Discord Status plugin will sometimes say game name is "Steam Deck", + # and put actual game name in description (see game_from_activity()) return "steamdeck" platform = activity.platform or "pc" if platform == "desktop": - # some games say "desktop" apparently + # Some games say "desktop", lets just lump it together with "pc" platform = "pc" return platform