Skip to content

attempts to fix integration test#2

Open
gamesguru wants to merge 2 commits intomasterfrom
dev
Open

attempts to fix integration test#2
gamesguru wants to merge 2 commits intomasterfrom
dev

Conversation

@gamesguru
Copy link
Copy Markdown
Member

@gamesguru gamesguru commented Mar 24, 2026

Summary by cubic

Ships a v2 rewrite that packages matrix-premid as a proper CLI/daemon with a systemd user service, keyring-backed multi-account config, and dynamic versioning via hatch-vcs; it also stabilizes CI by running a configured Conduwuit and parsing its registration token. Presence is more accurate with a config-driven, URL-aware provider system (watch vs listen, timestamps), debounced idle, and clean shutdown to offline using direct REST via aiohttp.

  • New Features

    • Distributable Python package with matrix-premid entry point, tab completion, and git-backed versioning.
    • Config-driven providers (regex, priorities, templates) with per-account control; ships config.template.json.
    • CLI adds daemon/shutdown, --debug/--version, installers for user or /opt, and secure tokens via OS keyring.
  • Bug Fixes

    • Reduced flicker; better idle transitions and paused-track handling; fixed negative time deltas; graceful shutdown sets offline.
    • Safer lockfile handling and exponential backoff to avoid homeserver hammering.
    • CI integration runs a Dockerized Conduwuit via TOML and auto-parses its token; fixed module path execution in tests.
    • Clear hint for expired/invalid access tokens with steps to update the keyring secret.

Written for commit 1eb1a10. Summary will update on new commits.

Copilot AI review requested due to automatic review settings March 24, 2026 08:58
Copy link
Copy Markdown

@cubic-dev-ai cubic-dev-ai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No issues found across 1 file

Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Updates the GitHub Actions E2E workflow to start the Conduwuit homeserver via an explicit docker run with a generated TOML config, aiming to stabilize the integration test setup.

Changes:

  • Removes the GitHub Actions services: container definition for Conduwuit.
  • Adds a step that writes conduwuit.toml and starts Conduwuit via docker run.
  • Drops passing CONDUWUIT_CONTAINER_ID into the integration test step.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread .github/workflows/integration.yml
Comment thread .github/workflows/integration.yml Outdated
Comment thread .github/workflows/integration.yml
Copy link
Copy Markdown

@cubic-dev-ai cubic-dev-ai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

2 issues found across 2 files (changes from recent commits).

Prompt for AI agents (unresolved issues)

Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.


<file name="docker/test_integration.py">

<violation number="1" location="docker/test_integration.py:22">
P1: Fail fast when token discovery fails instead of silently falling back to a hardcoded token.</violation>

<violation number="2" location="docker/test_integration.py:44">
P2: Do not print the full registration token in logs; this leaks a credential used for registration.</violation>
</file>

Reply with feedback, questions, or to request a fix. Tag @cubic-dev-ai to re-run a review.

Comment thread docker/test_integration.py Outdated
Comment thread docker/test_integration.py Outdated
Copilot AI review requested due to automatic review settings March 24, 2026 10:21
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 3 out of 3 changed files in this pull request and generated 5 comments.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread matrix_premid.py Outdated
Comment thread src/matrix_premid/__main__.py
Comment thread docker/test_integration.py Outdated
Comment thread docker/test_integration.py Outdated
Comment thread .github/workflows/integration.yml Outdated
Copy link
Copy Markdown

@cubic-dev-ai cubic-dev-ai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

1 issue found across 5 files (changes from recent commits).

Prompt for AI agents (unresolved issues)

Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.


<file name="matrix_premid.py">

<violation number="1" location="matrix_premid.py:206">
P2: Adding the new `Watching` prefix without updating `update()` quality parsing regresses metadata prioritization, so lower-quality statuses can overwrite richer ones for the same title.</violation>
</file>

Reply with feedback, questions, or to request a fix. Tag @cubic-dev-ai to re-run a review.

Comment thread matrix_premid.py Outdated
Copilot AI review requested due to automatic review settings March 24, 2026 11:06
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 6 out of 6 changed files in this pull request and generated 5 comments.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread matrix_premid.py Outdated
Comment thread docker/test_integration.py Outdated
Comment thread docker/test_integration.py
Comment thread .github/workflows/integration.yml Outdated
Comment thread matrix_premid.py Outdated
Copilot AI review requested due to automatic review settings March 24, 2026 11:26
Copy link
Copy Markdown

@cubic-dev-ai cubic-dev-ai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

1 issue found across 4 files (changes from recent commits).

Prompt for AI agents (unresolved issues)

Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.


<file name="Makefile">

<violation number="1" location="Makefile:53">
P1: `test` no longer depends on `deps`, so `make test` can fail on fresh setups because pytest/dev dependencies are not installed.</violation>
</file>

Reply with feedback, questions, or to request a fix. Tag @cubic-dev-ai to re-run a review.

Comment thread Makefile Outdated
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 8 out of 8 changed files in this pull request and generated 4 comments.

Comments suppressed due to low confidence (1)

tests/test_updater.py:172

  • test_main_execution_mocked_gather calls main(), but main() now exits early if playerctl is not found via shutil.which. This test (and the other main() test) should patch matrix_premid.shutil.which to return a fake path so the assertions exercise the intended code paths and don't become environment-dependent.
@pytest.mark.asyncio
@patch("matrix_premid.sys.exit")
@patch("matrix_premid.acquire_lock")
@patch("matrix_premid.HOMESERVER", "mock")
@patch("matrix_premid.USERNAME", "@user")
@patch("matrix_premid.ACCESS_TOKEN", "tok")
@patch("matrix_premid.DEVICE_ID", "dev")
async def test_main_execution_mocked_gather(_mock_lock, mock_exit):
    """Test main entrypoint setups everything cleanly resolving without errors."""
    with patch("matrix_premid.AsyncClient") as mock_client:
        mock_instance = AsyncMock()
        mock_client.return_value = mock_instance

        mock_event = MagicMock()
        mock_event.user_id = "@user"
        mock_event.presence = "dnd"

        mock_resp = MagicMock()
        mock_resp.presence.events = [mock_event]

        # Emit native valid presence payload once, then gracefully exit loop
        mock_instance.sync.side_effect = [mock_resp, asyncio.CancelledError()]

        with patch(
            "matrix_premid.MatrixStatusUpdater.update", new_callable=AsyncMock
        ) as mock_update:
            mock_update.side_effect = asyncio.CancelledError()

            with patch("matrix_premid.asyncio.create_subprocess_exec") as mock_exec:
                mock_proc = AsyncMock()
                mock_proc.communicate.side_effect = asyncio.CancelledError()
                mock_exec.return_value = mock_proc

                await main()

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread src/matrix_premid/__main__.py
Comment thread tests/test_updater.py Outdated
Comment thread docker/test_integration.py Outdated
Comment thread docker/test_integration.py Outdated
Copilot AI review requested due to automatic review settings March 24, 2026 12:25
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 8 out of 8 changed files in this pull request and generated 2 comments.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread matrix_premid.py Outdated
Comment thread Makefile Outdated
Copilot AI review requested due to automatic review settings March 24, 2026 12:29
Copy link
Copy Markdown

@cubic-dev-ai cubic-dev-ai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

1 issue found across 4 files (changes from recent commits).

Prompt for AI agents (unresolved issues)

Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.


<file name="tests/test_updater.py">

<violation number="1" location="tests/test_updater.py:156">
P2: This test fixture now uses `online`, which makes it unable to catch regressions where native non-default presence is ignored and forced back to online.</violation>
</file>

Reply with feedback, questions, or to request a fix. Tag @cubic-dev-ai to re-run a review.

Comment thread tests/test_updater.py Outdated
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 8 out of 8 changed files in this pull request and generated 3 comments.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread tests/test_parser.py Outdated
Comment thread docker/test_integration.py
Comment thread matrix_premid.py Outdated
Copilot AI review requested due to automatic review settings March 24, 2026 12:44
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 8 out of 8 changed files in this pull request and generated 2 comments.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread docker/test_integration.py Outdated
Comment thread matrix_premid.py Outdated
Copilot AI review requested due to automatic review settings March 24, 2026 12:57
Copy link
Copy Markdown

@cubic-dev-ai cubic-dev-ai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

1 issue found across 2 files (changes from recent commits).

Prompt for AI agents (unresolved issues)

Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.


<file name="docker/test_integration.py">

<violation number="1" location="docker/test_integration.py:29">
P2: Using `docker logs --since 1s` can miss the one-time registration-token log line and make this integration test flaky.</violation>
</file>

Reply with feedback, questions, or to request a fix. Tag @cubic-dev-ai to re-run a review.

Comment thread docker/test_integration.py Outdated
Copy link
Copy Markdown

@cubic-dev-ai cubic-dev-ai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

1 issue found across 2 files (changes from recent commits).

Prompt for AI agents (unresolved issues)

Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.


<file name="src/matrix_premid/__main__.py">

<violation number="1" location="src/matrix_premid/__main__.py:658">
P2: The new `set` command is incorrectly blocked by the global `playerctl` dependency check. `set` should work without `playerctl` since it does not use MPRIS.</violation>
</file>

Reply with feedback, questions, or to request a fix. Tag @cubic-dev-ai to re-run a review.

)
)

if args.command == "set":
Copy link
Copy Markdown

@cubic-dev-ai cubic-dev-ai Bot Mar 28, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2: The new set command is incorrectly blocked by the global playerctl dependency check. set should work without playerctl since it does not use MPRIS.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At src/matrix_premid/__main__.py, line 658:

<comment>The new `set` command is incorrectly blocked by the global `playerctl` dependency check. `set` should work without `playerctl` since it does not use MPRIS.</comment>

<file context>
@@ -652,6 +655,32 @@ async def main(args=None):
             )
         )
 
+    if args.command == "set":
+        status_msg = " ".join(args.status_args)
+        if not status_msg:
</file context>
Fix with Cubic

Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 15 out of 18 changed files in this pull request and generated 7 comments.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread README.rst
Comment on lines +57 to +59
1. **Install dependencies**: ``pip install .`` (or use installation methods above).
2. **Setup environment**: Place your ``.env`` file in the current directory or at ``~/.config/matrix-premid/.env``.
3. **Run the script**: ``matrix-premid``
Copy link

Copilot AI Mar 28, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The configuration instructions still mention placing a .env file and exporting env vars, but the CLI now loads ~/.config/matrix-premid/config.json and resolves tokens via keyring. Update these steps to describe config.json + keyring (or embedding access_token in config.json).

Copilot uses AI. Check for mistakes.
Comment thread README.rst
Comment on lines +39 to 42
sudo make install

This creates the directory ``/opt/matrix-premid``, copies the script and ``.env`` there, sets up an isolated Python virtual environment exclusively for the service, and symlinks the script to ``/usr/local/bin/matrix_premid``. The systemd service is placed in ``/etc/systemd/system/``.
This creates the directory ``/opt/matrix-premid``, copies the script and ``.env`` there, sets up an isolated Python virtual environment exclusively for the service, and symlinks the script to ``/usr/local/bin/matrix-premid``. The systemd service is placed in ``/etc/systemd/system/``.

Copy link

Copilot AI Mar 28, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The docs describe global install into /opt and /etc/systemd/system, but the Makefile install target now performs a user-level pip install and sets up a systemd user unit. Update this section so it matches the new installation flow and paths.

Copilot uses AI. Check for mistakes.
@@ -39,6 +25,13 @@ jobs:
make deps
Copy link

Copilot AI Mar 28, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The repo is now a package with a matrix-premid console script, but this workflow only installs requirements*.txt via make deps and never installs the package itself. If the integration test is updated to run matrix-premid/python -m matrix_premid, ensure the workflow also does pip install ./pip install -e . (so runtime deps like keyring are present) or otherwise sets up PYTHONPATH=src explicitly.

Suggested change
make deps
make deps
. .venv/bin/activate
pip install .

Copilot uses AI. Check for mistakes.
Comment thread README.rst

.. code-block:: bash

make install-user
Copy link

Copilot AI Mar 28, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

README references a make install-user target, but the Makefile in this PR only defines install (and no install-user). Either add the missing target or update the README to point to the correct Make target/command.

Suggested change
make install-user
pip install --user .

Copilot uses AI. Check for mistakes.
lines = stdout.decode("utf-8").strip().splitlines() if stdout else []
if updaters and updaters[0].verbose: # pragma: no cover
print(f"DEBUG: raw playerctl lines: {lines}", flush=True)
activity, title = _get_best_mpris_activity(lines)
Copy link

Copilot AI Mar 28, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

When _get_best_mpris_activity() returns an empty activity (e.g., no players / only unparseable lines), MatrixStatusUpdater.update() currently treats that as a no-op, so the idle debounce logic never runs and the last non-idle status can remain stuck indefinitely after media stops/closes. Consider mapping the “no activity” case to an explicit "Idle" update (either in _get_best_mpris_activity() or here in monitor_mpris) so the existing idle_strikes / idle_timeout mechanism can work.

Suggested change
activity, title = _get_best_mpris_activity(lines)
activity, title = _get_best_mpris_activity(lines)
# If no meaningful activity is found, treat it as explicit Idle
if not activity:
activity = "Idle"

Copilot uses AI. Check for mistakes.
Comment on lines +129 to +133
if "YT Music" in activity:
quality += 1
elif activity.startswith("Paused:"):
quality = 6 if " - " in activity else 4
if "YT Music" in activity:
Copy link

Copilot AI Mar 28, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The quality boost checks for the substring "YT Music", but activities are tagged with the provider name "YouTube Music" (e.g., "| YouTube Music"). As written, this bonus will never apply, which can affect metadata quality comparisons and update suppression. Align this check with the actual provider label you emit.

Suggested change
if "YT Music" in activity:
quality += 1
elif activity.startswith("Paused:"):
quality = 6 if " - " in activity else 4
if "YT Music" in activity:
if "YouTube Music" in activity:
quality += 1
elif activity.startswith("Paused:"):
quality = 6 if " - " in activity else 4
if "YouTube Music" in activity:

Copilot uses AI. Check for mistakes.
Comment on lines +219 to +222
if is_exit or activity == "Idle" or not activity:
payload_s = {}
else:
payload_s = {"status": activity}
Copy link

Copilot AI Mar 28, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

update() treats any activity starting with "Idle" as idle (for debouncing), but send_update() only clears Element status when activity == "Idle". This means idle-like states such as "Idle (YouTube Music)" can be sent as a visible custom status instead of being cleared. Consider using a consistent idle predicate here (e.g., activity.startswith("Idle")).

Copilot uses AI. Check for mistakes.
Copy link
Copy Markdown

@cubic-dev-ai cubic-dev-ai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

1 issue found across 2 files (changes from recent commits).

Prompt for AI agents (unresolved issues)

Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.


<file name="tests/test_updater.py">

<violation number="1" location="tests/test_updater.py:544">
P2: Avoid re-patching `open` inside the test body; call `install_service()` directly and assert the existing `_mock_open` decorator mock was used.</violation>
</file>

Reply with feedback, questions, or to request a fix. Tag @cubic-dev-ai to re-run a review.

Comment thread tests/test_updater.py
Copilot AI review requested due to automatic review settings March 28, 2026 09:22
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 15 out of 18 changed files in this pull request and generated 1 comment.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread .github/workflows/integration.yml Outdated
Comment on lines 22 to 50
env:
CONDUWUIT_CONTAINER_ID: ${{ job.services.conduwuit.id }}
run: |
python docker/test_integration.py
Copy link

Copilot AI Mar 28, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The workflow runs the integration test without installing the package. With the new src/ layout and removal of matrix_premid.py, the integration test needs the module installed (e.g. pip install -e .) or an explicit PYTHONPATH=src when invoking the CLI. As written, the job is likely to fail once docker/test_integration.py is updated to python -m matrix_premid/matrix-premid.

Copilot uses AI. Check for mistakes.
Copilot AI review requested due to automatic review settings March 28, 2026 10:42
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 16 out of 19 changed files in this pull request and generated no new comments.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Copy link
Copy Markdown

@cubic-dev-ai cubic-dev-ai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

1 issue found across 2 files (changes from recent commits).

Prompt for AI agents (unresolved issues)

Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.


<file name="tests/test_parser.py">

<violation number="1" location="tests/test_parser.py:192">
P3: This test bypasses provider detection by hardcoding `global_provider`, so it doesn’t actually verify the stated Spotify detection behavior.</violation>
</file>

Reply with feedback, questions, or to request a fix. Tag @cubic-dev-ai to re-run a review.

Comment thread tests/test_parser.py
Copilot AI review requested due to automatic review settings March 29, 2026 03:54
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 16 out of 19 changed files in this pull request and generated 3 comments.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread README.rst
.. code-block:: bash

make install
sudo make install
Copy link

Copilot AI Mar 29, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

README now instructs sudo make install, but the Makefile install target already uses sudo internally and then runs matrix-premid install-service without sudo to create a user systemd unit. Running the whole make target under sudo will create the user service/config under root’s home instead. Update the docs to run make install (no sudo) or adjust the install target so only the privileged steps run as root.

Suggested change
sudo make install
make install

Copilot uses AI. Check for mistakes.
Comment on lines +132 to +136
if "YT Music" in activity:
quality += 1
elif activity.startswith("Paused:"):
quality = 6 if " - " in activity else 4
if "YT Music" in activity:
Copy link

Copilot AI Mar 29, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

MatrixStatusUpdater.update() boosts quality when activity contains "YT Music", but the provider strings produced elsewhere are "YouTube Music". This makes the quality boost ineffective and can change debouncing/override behavior. Consider checking for "YouTube Music" (or a more general provider marker like "| YouTube Music").

Suggested change
if "YT Music" in activity:
quality += 1
elif activity.startswith("Paused:"):
quality = 6 if " - " in activity else 4
if "YT Music" in activity:
if "YT Music" in activity or "YouTube Music" in activity:
quality += 1
elif activity.startswith("Paused:"):
quality = 6 if " - " in activity else 4
if "YT Music" in activity or "YouTube Music" in activity:

Copilot uses AI. Check for mistakes.
Comment on lines +215 to +231
payload_p = {
"presence": self.current_presence,
}
if activity and activity != "Idle":
payload_p["status_msg"] = activity

# 2. Element Status Payload
url_s = (
f"{self.homeserver}/_matrix/client/v3/user/{self.username}/"
"account_data/im.vector.user_status"
)

if is_exit or activity == "Idle" or not activity:
payload_s = {}
else:
payload_s = {"status": activity}

Copy link

Copilot AI Mar 29, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

send_update() treats only the exact string "Idle" as idle when deciding whether to omit status_msg / clear im.vector.user_status, but other code emits idle variants like "Idle (YouTube Music)". This will incorrectly publish an idle status message instead of clearing it. Use the same idle predicate as update() (e.g., activity.startswith("Idle") or a shared helper) when building both payloads.

Copilot uses AI. Check for mistakes.
Copy link
Copy Markdown

@cubic-dev-ai cubic-dev-ai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

3 issues found across 4 files (changes from recent commits).

Prompt for AI agents (unresolved issues)

Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.


<file name="src/matrix_premid/__main__.py">

<violation number="1" location="src/matrix_premid/__main__.py:696">
P2: Disabled accounts still require an access token, so `enabled: false` accounts can abort startup before they are skipped.</violation>

<violation number="2" location="src/matrix_premid/__main__.py:867">
P3: Close the temporary `/dev/null` FD after `dup2` to avoid leaking a file descriptor in daemon mode.</violation>
</file>

<file name="Makefile">

<violation number="1" location="Makefile:29">
P1: `install-service` is executed as the current Make user, which becomes root under `sudo make install`; this sets up user-service/config for the wrong account.</violation>
</file>

Reply with feedback, questions, or to request a fix. Tag @cubic-dev-ai to re-run a review.

Comment thread Makefile
sudo /opt/matrix-premid/venv/bin/pip install .
sudo ln -sf /opt/matrix-premid/venv/bin/matrix-premid /usr/local/bin/matrix-premid
@echo "Setting up systemd service..."
/usr/local/bin/matrix-premid install-service
Copy link
Copy Markdown

@cubic-dev-ai cubic-dev-ai Bot Mar 29, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1: install-service is executed as the current Make user, which becomes root under sudo make install; this sets up user-service/config for the wrong account.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At Makefile, line 29:

<comment>`install-service` is executed as the current Make user, which becomes root under `sudo make install`; this sets up user-service/config for the wrong account.</comment>

<file context>
@@ -21,9 +21,12 @@ deps: ##H Install standard and dev dependencies
+	sudo ln -sf /opt/matrix-premid/venv/bin/matrix-premid /usr/local/bin/matrix-premid
 	@echo "Setting up systemd service..."
-	~/.local/bin/matrix-premid install-service
+	/usr/local/bin/matrix-premid install-service
 
 # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
</file context>
Suggested change
/usr/local/bin/matrix-premid install-service
if [ -n "$$SUDO_USER" ]; then sudo -u "$$SUDO_USER" /usr/local/bin/matrix-premid install-service; else /usr/local/bin/matrix-premid install-service; fi
Fix with Cubic

account["username"],
account["access_token"],
device_id=account.get("device_id", ""),
enabled=account.get("enabled", True),
Copy link
Copy Markdown

@cubic-dev-ai cubic-dev-ai Bot Mar 29, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2: Disabled accounts still require an access token, so enabled: false accounts can abort startup before they are skipped.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At src/matrix_premid/__main__.py, line 696:

<comment>Disabled accounts still require an access token, so `enabled: false` accounts can abort startup before they are skipped.</comment>

<file context>
@@ -685,6 +693,7 @@ async def main(args=None):
                 account["username"],
                 account["access_token"],
                 device_id=account.get("device_id", ""),
+                enabled=account.get("enabled", True),
                 idle_timeout=idle_timeout,
                 poll_interval=poll_interval,
</file context>
Fix with Cubic

Comment thread src/matrix_premid/__main__.py
Copy link
Copy Markdown

@cubic-dev-ai cubic-dev-ai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

1 issue found across 6 files (changes from recent commits).

Prompt for AI agents (unresolved issues)

Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.


<file name="tests/test_updater.py">

<violation number="1" location="tests/test_updater.py:187">
P2: This test now uses a loose substring check and no longer validates the expected `title` kwarg, which can let real regressions pass unnoticed.</violation>
</file>

Reply with feedback, questions, or to request a fix. Tag @cubic-dev-ai to re-run a review.

Comment thread tests/test_updater.py
Copilot AI review requested due to automatic review settings March 29, 2026 10:24
Copy link
Copy Markdown

@cubic-dev-ai cubic-dev-ai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

1 issue found across 2 files (changes from recent commits).

Prompt for AI agents (unresolved issues)

Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.


<file name="src/matrix_premid/__main__.py">

<violation number="1" location="src/matrix_premid/__main__.py:643">
P2: Time-quality bonus is granted based on raw non-empty fields, so zero/invalid durations can be misclassified as valid timestamps.</violation>
</file>

Reply with feedback, questions, or to request a fix. Tag @cubic-dev-ai to re-run a review.

has_real_artist = bool(
clean_raw_artist and clean_raw_artist.lower() not in banned_artists
)
has_time = bool(raw_pos and raw_len)
Copy link
Copy Markdown

@cubic-dev-ai cubic-dev-ai Bot Mar 29, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2: Time-quality bonus is granted based on raw non-empty fields, so zero/invalid durations can be misclassified as valid timestamps.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At src/matrix_premid/__main__.py, line 643:

<comment>Time-quality bonus is granted based on raw non-empty fields, so zero/invalid durations can be misclassified as valid timestamps.</comment>

<file context>
@@ -629,13 +629,32 @@ def _get_best_mpris_activity(lines: list[str]) -> tuple[str, str]:
+        has_real_artist = bool(
+            clean_raw_artist and clean_raw_artist.lower() not in banned_artists
+        )
+        has_time = bool(raw_pos and raw_len)
+
         quality = 0
</file context>
Fix with Cubic

Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 19 out of 22 changed files in this pull request and generated 4 comments.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread README.rst
Comment on lines +57 to 60
1. **Install dependencies**: ``pip install .`` (or use installation methods above).
2. **Setup environment**: Place your ``.env`` file in the current directory or at ``~/.config/matrix-premid/.env``.
3. **Run the script**: ``matrix-premid``

Copy link

Copilot AI Mar 29, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The README now instructs users to place a .env file for configuration, but the new CLI no longer loads dotenv/env-based configuration; it requires ~/.config/matrix-premid/config.json and uses keyring for missing access tokens. Update the “Basic Usage” steps to describe creating/editing config.json (or using the provided template) and storing tokens in keyring (or placing access_token in config for non-interactive setups like CI).

Copilot uses AI. Check for mistakes.
Comment on lines +245 to +248
# If no activity detected, we don't force 'Idle' immediately.
# We preserve the last activity unless it's explicitly 'Idle'
# or we are exiting.
return
Copy link

Copilot AI Mar 29, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

MatrixStatusUpdater.update() returns immediately when activity is empty (unless is_exit), but the idle debounce/idle_timeout logic only runs when activity is "Idle"/"Idle...". Combined with _get_best_mpris_activity() returning "" when nothing is playing, this means the updater may never transition to Idle when playback stops and idle_timeout becomes ineffective. Consider treating empty activity as an idle signal (possibly debounced via idle_strikes) or have _get_best_mpris_activity() return "Idle" when no active players are detected.

Suggested change
# If no activity detected, we don't force 'Idle' immediately.
# We preserve the last activity unless it's explicitly 'Idle'
# or we are exiting.
return
# Treat lack of activity as a potential idle state so that
# idle_timeout / idle_strikes logic can take effect.
activity = "Idle"
title = ""

Copilot uses AI. Check for mistakes.
Comment on lines +1037 to +1041
# Clean up lock file so next start works cleanly
try:
os.unlink(LOCK_FILE)
except OSError:
pass
Copy link

Copilot AI Mar 29, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The lock file is unlinked during shutdown, but the lock file descriptor returned by acquire_lock() is never closed. Unlinking while still holding the lock releases the name while the process is still alive, allowing a second instance to create a new lock file and acquire a lock before this process exits. Keep a reference to the lock FD and close it before unlinking (or just leave the lock file in place and rely on lockf + truncation).

Suggested change
# Clean up lock file so next start works cleanly
try:
os.unlink(LOCK_FILE)
except OSError:
pass
# Do not unlink the lock file here. Locking is enforced via the file
# descriptor and POSIX locking (lockf), not by the mere presence of
# the file. Unlinking while still holding the lock can allow another
# process to recreate the file and acquire a separate lock before this
# process fully exits.

Copilot uses AI. Check for mistakes.
Comment thread Makefile
sudo /opt/matrix-premid/venv/bin/pip install .
sudo ln -sf /opt/matrix-premid/venv/bin/matrix-premid /usr/local/bin/matrix-premid
@echo "Setting up systemd service..."
/usr/local/bin/matrix-premid install-service
Copy link

Copilot AI Mar 29, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

make install is intended to be run via sudo (per README), but it then runs matrix-premid install-service without dropping privileges. That will create the user systemd unit under /root/.config/systemd/user (and generate root-owned config), not the invoking user’s home directory. Either avoid sudo make install for the user-service flow, or run install-service as the original user (e.g., via sudo -u $SUDO_USER ...), or change the install to create a system-level service instead of a user service.

Suggested change
/usr/local/bin/matrix-premid install-service
@if [ -n "$$SUDO_USER" ]; then \
echo "Running matrix-premid install-service as $$SUDO_USER"; \
sudo -u "$$SUDO_USER" /usr/local/bin/matrix-premid install-service; \
else \
/usr/local/bin/matrix-premid install-service; \
fi

Copilot uses AI. Check for mistakes.
Copy link
Copy Markdown

@cubic-dev-ai cubic-dev-ai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

1 issue found across 1 file (changes from recent commits).

Prompt for AI agents (unresolved issues)

Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.


<file name="src/matrix_premid/__main__.py">

<violation number="1" location="src/matrix_premid/__main__.py:707">
P2: Validate `poll_interval`/`idle_timeout` from hot-reloaded config before assigning; invalid types can crash the monitor loop at runtime.</violation>
</file>

Reply with feedback, questions, or to request a fix. Tag @cubic-dev-ai to re-run a review.

Comment thread src/matrix_premid/__main__.py
Copilot AI review requested due to automatic review settings March 30, 2026 05:15
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 19 out of 22 changed files in this pull request and generated 2 comments.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +1086 to +1090
# Clean up lock file so next start works cleanly
try:
os.unlink(LOCK_FILE)
except OSError:
pass
Copy link

Copilot AI Mar 30, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The lock file is unlinked at shutdown, but the file descriptor returned from acquire_lock() is never closed before os.unlink(LOCK_FILE). On POSIX, unlinking while still holding the lock can allow a second process to create a new lock file and acquire a lock before the first process fully exits, defeating the single-instance guarantee. Fix by closing the lock fd before unlinking, or by leaving the lock file in place and relying on advisory locking + PID contents for cleanup.

Suggested change
# Clean up lock file so next start works cleanly
try:
os.unlink(LOCK_FILE)
except OSError:
pass
# Intentionally keep the lock file; rely on advisory locking and PID
# contents for cleanup to avoid unlink-while-locked races on POSIX.

Copilot uses AI. Check for mistakes.

if quality > best_quality:
best_activity, best_title, best_quality = activity, title, quality

Copy link

Copilot AI Mar 30, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

When no valid playerctl lines are found, _get_best_mpris_activity() returns empty strings. monitor_mpris() then passes an empty activity into MatrixStatusUpdater.update(), which returns early and never increments idle_strikes, so the last activity can be refreshed indefinitely (keep_alive sends last_activity). Consider returning an explicit idle sentinel (e.g., "Idle") in the no-activity case (or translating empty->Idle in monitor_mpris()), and update tests accordingly so debounced idle can work.

Suggested change
# If no suitable activity was found, explicitly return Idle so that
# downstream idle debouncing logic can trigger correctly.
if not best_activity:
return "Idle", ""

Copilot uses AI. Check for mistakes.
@cubic-dev-ai
Copy link
Copy Markdown

cubic-dev-ai Bot commented Apr 4, 2026

You're iterating quickly on this pull request. To help protect your rate limits, cubic has paused automatic reviews on new pushes for now—when you're ready for another review, comment @cubic-dev-ai review.

- Removed matrix-nio dependency in favor of lightweight aiohttp requests
- Added multi-account support with secure keyring token storage
- Refactored into a distributable Python package with dynamic git versioning (hatch-vcs)
- Introduced daemon and shutdown CLI commands with robust lockfile management
- Improved provider parsing (media time tracking, watch vs. listen priority)
- Implemented exponential backoff for sync loop and fixed idle state transitions
- Expanded test coverage and fixed integration test instability
Copilot AI review requested due to automatic review settings April 5, 2026 06:45
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 19 out of 22 changed files in this pull request and generated 1 comment.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread README.rst
Command-line Options
--------------------

* ``--unset`` or ``--clear``: Manually clear status to AFK (unavailable) and exit.
Copy link

Copilot AI Apr 5, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

--unset/--clear is documented as clearing status to "AFK (unavailable)", but the implementation sets Matrix presence to offline and clears the custom status (see MatrixStatusUpdater.send_update(..., is_exit=True)). Suggest updating the wording to match actual behavior (offline/clear) or changing the code to set the intended presence state.

Suggested change
* ``--unset`` or ``--clear``: Manually clear status to AFK (unavailable) and exit.
* ``--unset`` or ``--clear``: Set presence to ``offline``, clear the custom status, and exit.

Copilot uses AI. Check for mistakes.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants