Skip to content

Add write commands: dc send / edit / delete - #4

Open
nguyenvanduocit wants to merge 3 commits into
jackwener:mainfrom
nguyenvanduocit:feat/write-commands
Open

Add write commands: dc send / edit / delete#4
nguyenvanduocit wants to merge 3 commits into
jackwener:mainfrom
nguyenvanduocit:feat/write-commands

Conversation

@nguyenvanduocit

@nguyenvanduocit nguyenvanduocit commented Jun 17, 2026

Copy link
Copy Markdown

Closes #3

What

Adds user-token write operations behind explicit safety gating:

discord dc send   <channel> "<content>"
discord dc edit   <channel> <message_id> "<content>"
discord dc delete <channel> <message_id>
  • client._mutate (POST/PATCH/DELETE) reuses the existing _handle_rate_limit backoff; send_message / edit_message / delete_message.
  • db.update_message / db.delete_message keep the local SQLite mirror in sync after a write.
  • dc send / dc edit / dc delete with the shared output envelope; failed writes return a clean error envelope.

Safety (strengthens, doesn't weaken, the user-token messaging)

  • prints a user-token risk warning on every write;
  • confirms before writing, or --yes;
  • refuses to write in a non-interactive session without --yes (no silent scripted posting), verified by the gate firing before the token is even read;
  • single-shot only.

Tests

tests/test_client.py covers the HTTP layer via httpx.MockTransport (POST/PATCH/DELETE path + body, 204 → None); tests/test_discord_cmds.py covers CLI behavior (store-on-send, delete-removes-local-row, refuse-without---yes).

uv run ruff check .      # passed
uv run python -m pytest  # 24 passed

Note on scope

This branch stacks on #1 (attachment-URL fix), so the diff currently shows that commit too — the write-commands change is the second commit (feat: add dc send / edit / delete write commands). Once #1 merges, this reduces to a single commit. Happy to rebase/split however you prefer.

See #3 for the ToS discussion — I fully understand if you'd rather gate this behind an opt-in flag or keep the tool read-only.

Update: file attachments

dc send now takes repeatable --file/-f for multipart uploads (CONTENT optional for file-only sends). Implemented by dropping the hardcoded application/json default header so httpx sets multipart/form-data per request; json bodies still get their content-type automatically. Live-tested end to end (real upload returns a CDN attachment URL). Tests now 28 passed.

nguyenvanduocit and others added 2 commits June 17, 2026 14:38
Discord's message API returns each attachment's CDN url, but _parse_message
kept only the filename ("[attachment: foo.png]") and discarded the url, so
images and files were unreachable from stored content — export, search, and
recent showed a placeholder with no way to fetch the actual file.

Keep the url as a markdown link ("[attachment: foo.png](https://cdn...)"),
falling back to proxy_url, then to the bare placeholder when neither exists.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Adds user-token write operations behind explicit safety gating:

- client.py: _mutate (POST/PATCH/DELETE with rate-limit handling) plus
  send_message / edit_message / delete_message.
- db.py: update_message / delete_message keep the local SQLite mirror in
  sync after a write.
- cli: dc send / dc edit / dc delete. Each prints a user-token risk
  warning, confirms before writing (or --yes), and refuses to run
  unconfirmed in a non-interactive session so scripts can't write
  silently. Failed writes surface a clean HTTP error envelope.

Tests cover the HTTP layer (httpx MockTransport) and CLI behavior
(store-on-send, delete-removes-local-row, refuse-without-yes).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
- client: send_message accepts files=[...] and switches to a multipart
  upload (_upload) when given; drop the hardcoded application/json default
  header so httpx can set multipart/form-data with a boundary (json bodies
  still get application/json automatically).
- cli: dc send --file/-f (repeatable); CONTENT is now optional so files
  can be sent without a caption, with an empty-message guard.

Tests cover multipart encoding (httpx MockTransport), the absence of a
default content-type, and the CLI forwarding/empty-message paths.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
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.

Feature: write commands (dc send / edit / delete)

1 participant