commit 77cfc6a10a1c556a1c2f848b90c544eb33e06cb0 Author: disqualifier Date: Thu Jul 2 19:59:13 2026 -0400 init: mirror a project folder onto the bot's application emojis for discord.py Signed-off-by: disqualifier diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..be64430 --- /dev/null +++ b/.gitignore @@ -0,0 +1,15 @@ +# claude +.claude/ + +# python +__pycache__/ +*.py[cod] +*.egg-info/ +build/ +dist/ +.eggs/ + +# env +.venv/ +venv/ +.env diff --git a/README.md b/README.md new file mode 100644 index 0000000..2acae01 --- /dev/null +++ b/README.md @@ -0,0 +1,72 @@ +# dpy_appemojis + +Mirror a project folder onto your bot's **application emojis** (bot-owned, usable in any +guild the app is in — not guild emojis) for discord.py. Drop an image in `assets/emojis`, +call `refresh()`, and it becomes an application emoji named after the file. The folder is the +source of truth: a file removed means its emoji is deleted. + +## Install + +``` +dpy_appemojis @ git+ssh://git@git.rethinkstudios.io/rethink-public/dpy_appemojis.git@v0.1.0 +``` + +## Usage + +```python +from dpy_appemojis import DPYAppEmojis + +appmojis = DPYAppEmojis(bot) +await appmojis.refresh() # e.g. in setup_hook / on_ready + +await ctx.send(f"done {appmojis.get.success_mark}") # dot-access -> discord.Emoji +appmojis.emoji("success_mark").url # explicit accessor +appmojis.list() # ["success_mark", ...] +``` + +`refresh()` makes the app's emoji set **mirror** `assets/emojis`: + +- a **new file** → the emoji is created (name = filename stem) +- a **removed file** → its emoji is deleted server-side +- a **same-name** emoji → left alone (this lib does **not** diff image content; to replace an + image, rename the file or delete + re-add) + +Call `refresh()` at startup, or from a command, to re-sync on demand — the lib adds no +commands of its own. + +## Dot-access vs `emoji()` + +`self.get` is a namespace whose attribute lookup returns the emoji by name. It lives apart +from the methods, so an emoji named `list` or `refresh` can't shadow them. For names that +aren't valid Python identifiers, use `emoji("name")`. `.url` comes free — `get.x` / +`emoji("x")` return a real `discord.Emoji`. + +## Fixed constants (not configurable) + +| | | +|---|---| +| Folder | `assets/emojis` (relative to cwd) | +| Extensions | `.png .jpg .jpeg .gif .webp` | +| Max file size | 256 KB (Discord's emoji limit) | +| Name rules | 2–32 chars, `[A-Za-z0-9_]` | +| App emoji cap | 2000 | + +## What you inject + +Your `discord.Client` / `commands.Bot`. Application-emoji methods live on the client +(`fetch_application_emojis` / `create_application_emoji`, added in discord.py 2.5), so this +targets **`discord.py>=2.5`**. + +## Contract (fail-loud) + +The module docstring (`help(dpy_appemojis)` / IDE hover) is the source of truth. Nothing is +swallowed: an invalid emoji name from a bad filename or an oversized file raises `ValueError` +naming the file; exceeding the 2000 cap raises `DPYAppEmojisError` **before** any create; a +discord API error (`Forbidden` / `HTTPException`) propagates **unwrapped** so a partial sync +never hides behind a silent success. `emoji(name)` / `get.` for a name that wasn't +synced raise `KeyError` / `AttributeError` (call `refresh()` first). + +## Versioning + +Tagged `vX.Y.Z`; pin a tag in your install line. Targets `discord.py>=2.5` (not +`discord.py-self`).