Shrimple User Purging on Discord (Includes Apps)
  • Python 98.2%
  • Dockerfile 1.8%
Find a file
Repository files (latest commit first)
Filename Latest commit message Latest commit date
resba 1e6a1b7a6f
Some checks failed
Build and push image / build (push) Failing after 31s
Init
2026-07-05 21:24:30 -04:00
.forgejo/workflows Init 2026-07-05 21:24:30 -04:00
.gitignore Init 2026-07-05 21:24:30 -04:00
bot.py Init 2026-07-05 21:24:30 -04:00
docker-compose.yml Init 2026-07-05 21:24:30 -04:00
Dockerfile Init 2026-07-05 21:24:30 -04:00
logo.png Init 2026-07-05 21:24:30 -04:00
README.md Init 2026-07-05 21:24:30 -04:00
requirements.txt Init 2026-07-05 21:24:30 -04:00

Shrimple logo

Shrimple

It's as shrimple as that.

A minimal Discord moderation bot. /purgeuser deletes a given user ID's messages from every text/voice/stage channel and active thread in the server — useful for cleaning up after a spammer or a banned account. /autopurge keeps deleting their new messages automatically, and /appactivity plus the "Who posted this?" context menu reveal who is behind app-posted messages.

Setup

  1. Create an application at https://discord.com/developers/applications, add a Bot, and copy the token.

  2. Invite it with the bot + applications.commands scopes and these permissions: View Channels, Read Message History, Manage Messages (permissions integer 74752).

  3. Install and run:

    pip install -r requirements.txt
    DISCORD_TOKEN=your-token-here python bot.py
    

Docker

echo "DISCORD_TOKEN=your-token-here" > .env
docker compose up -d

The compose file pulls yena.dev/kaisa/shrimple:latest (or builds locally with docker compose up -d --build). The autopurge watch list is kept on the shrimple-data volume so it survives container recreation.

CI

.forgejo/workflows/build.yml builds the image on every push to main and pushes it to yena.dev/kaisa/shrimple:latest. It expects two repository secrets on the Forgejo repo (Settings → Actions → Secrets):

  • REGISTRY_USER — your yena.dev username
  • REGISTRY_TOKEN — an access token with package:write scope

The workflow assumes a runner with the docker label that can run docker-in-docker jobs.

Usage

/purgeuser user_id:<numeric ID> [search_limit:<per-channel scan depth>]
/autopurge add user_id:<numeric ID>
/autopurge remove user_id:<numeric ID>
/autopurge list
/appactivity [search_limit:<scan depth, default 500>]

To identify who is behind app messages: right-click any message → Apps → Who posted this? to see its author, the user who invoked the app command, and the app ID. Or run /appactivity in a channel to get a ranked summary of who has been posting via apps recently.

/purgeuser sweeps existing messages once. /autopurge add puts an ID on a watch list: any new message from that user (or app response they invoke) is deleted the moment it's posted. The list is saved to autopurge.json next to the script, so it survives restarts. Note that autopurge does not sweep history — run /purgeuser for the same ID if you also want old messages gone.

  • Requires the invoker to have Manage Messages.
  • search_limit defaults to 1000 — the bot scans that many recent messages per channel. Raise it to reach further back (slower).
  • Get a user ID by enabling Developer Mode in Discord settings, then right-click the user → Copy User ID. This works even after the user has left or been banned.

Notes

  • Messages newer than 14 days are bulk-deleted; older ones are removed one-by-one, which is slower due to rate limits. discord.py handles the rate limiting automatically — a large purge may just take a few minutes.
  • App/bot messages: passing a person's ID also removes app responses they invoked (matched via interaction metadata). Passing an app's own ID removes everything that app posted. Webhook posts (e.g. from integrations) match by the webhook's ID, not the person behind it.
  • Channels the bot can't read or manage are skipped and listed in the summary.
  • Archived threads are not swept; unarchive a thread first if you need it cleaned.