Support Flatpak and Snap Discord; keep the timer when a game changes process
Look for discord-ipc sockets in the Flatpak and Snap runtime folders too. When a game moves to another process (e.g. at Steam launch), keep its first start time and don't resend the activity. Bump version to 0.2.
This commit is contained in:
@@ -16,17 +16,18 @@ import tomllib
|
||||
import urllib.request
|
||||
import uuid
|
||||
from collections.abc import Callable
|
||||
from dataclasses import dataclass, field
|
||||
from dataclasses import dataclass, field, replace
|
||||
from pathlib import Path
|
||||
from typing import Any
|
||||
|
||||
__version__ = "0.1"
|
||||
__version__ = "0.2"
|
||||
|
||||
NAME = "discord-game-presence"
|
||||
DETECTABLE_URL = "https://discord.com/api/v9/applications/detectable"
|
||||
CACHE_MAX_AGE = 7 * 24 * 3600 # seconds before the game list is downloaded again
|
||||
CACHE_CHECK = 3600 # seconds between cache age checks in the daemon
|
||||
CACHE_RETRY = 600 # seconds between download attempts while there is no game list at all
|
||||
SOCKET_DIRS = ("", "app/com.discordapp.Discord", "snap.discord") # under XDG_RUNTIME_DIR: host/firejail, Flatpak, Snap
|
||||
|
||||
OP_HANDSHAKE, OP_FRAME, OP_CLOSE, OP_PING, OP_PONG = range(5)
|
||||
|
||||
@@ -208,11 +209,11 @@ def scan(index: GameIndex, proc: Path = Path("/proc")) -> list[Game]:
|
||||
|
||||
|
||||
def choose(games: list[Game], current: Game | None) -> Game | None:
|
||||
"""Keep showing the current game while it runs, else the oldest one."""
|
||||
"""Keep showing the current game while it runs, timed from its first process, else the oldest one."""
|
||||
if current is not None:
|
||||
for game in games:
|
||||
if game.app.id == current.app.id:
|
||||
return game
|
||||
return replace(game, start=min(game.start, current.start))
|
||||
return games[0] if games else None
|
||||
|
||||
|
||||
@@ -272,8 +273,7 @@ class DiscordIPC:
|
||||
@classmethod
|
||||
def connect(cls, client_id: str, runtime_dir: Path, timeout: float = 5.0) -> "DiscordIPC":
|
||||
error: OSError = FileNotFoundError(f"no discord-ipc socket in {runtime_dir}")
|
||||
for i in range(10):
|
||||
path = runtime_dir / f"discord-ipc-{i}"
|
||||
for path in (runtime_dir / d / f"discord-ipc-{i}" for d in SOCKET_DIRS for i in range(10)):
|
||||
if not path.exists():
|
||||
continue
|
||||
sock = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
|
||||
@@ -363,8 +363,8 @@ class Presence:
|
||||
if game is None:
|
||||
self.failing = False
|
||||
return
|
||||
if game == self.shown:
|
||||
return
|
||||
if self.shown is not None and game.start == self.shown.start:
|
||||
return # same app and timer: only the process changed
|
||||
try:
|
||||
if self.ipc is None:
|
||||
self.ipc = DiscordIPC.connect(game.app.id, self.runtime_dir)
|
||||
@@ -406,6 +406,8 @@ def run(config: Config, cache: Path, runtime_dir: Path, stop: threading.Event, p
|
||||
log.info("%s exited", current.app.name)
|
||||
if game is not None and (current is None or game.app.id != current.app.id):
|
||||
log.info("Detected %s (pid %d)", game.app.name, game.pid)
|
||||
elif game is not None and current is not None and game.pid != current.pid:
|
||||
log.debug("%s now pid %d", game.app.name, game.pid)
|
||||
current = game
|
||||
presence.update(game)
|
||||
stop.wait(config.interval)
|
||||
|
||||
Reference in New Issue
Block a user