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 d9567f4..21e9275 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 + # 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 def game_from_activity(activity) -> str: if activity.name == "Steam Deck": @@ -47,10 +54,21 @@ 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": + # 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", lets just lump it together with "pc" + platform = "pc" + return platform @bot.event async def on_guild_available(guild): @@ -87,10 +105,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 +122,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..5d2d6ec 100644 --- a/oblivionis/storage.py +++ b/oblivionis/storage.py @@ -37,8 +37,11 @@ class Activity(BaseModel): user = ForeignKeyField(User) game = ForeignKeyField(Game) seconds = IntegerField() + platform = CharField(default="pc") 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