generated from exteraGramPlugins/pluginBase
Publish plugin / publish (push) Successful in 4s
README now carries the icon, TL;DR, description and features; the technical sections live in docs/. tools/icon_png.py renders images/icon.svg to a square PNG (512x512 by default, --resolution N). plugin.json points at the plugin's own icon. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
70 lines
3.8 KiB
Markdown
70 lines
3.8 KiB
Markdown
# Development
|
|
|
|
## Writing your own plugin
|
|
|
|
1. Run `python3 tools/bundle.py --check` once. It enables the git hooks that auto-bump the
|
|
version on commit (see [Git hooks and versioning](versioning-and-releases.md#git-hooks-and-versioning)).
|
|
2. Edit `plugin.json` (id, name, description, etc.).
|
|
3. Write your plugin under `src/`, with `src/main.py` as the entry module (absolute imports
|
|
only — it's executed at plugin-module top level, not inside a package).
|
|
4. `python3 tools/bundle.py --release && python3 tools/verify_bundle.py dist/<id>.plugin`
|
|
(substitute your `id` from `plugin.json`).
|
|
5. `bash scripts/deploy.sh --enable` with a device connected.
|
|
|
|
## Repo layout
|
|
|
|
```
|
|
plugin.json single source of truth for plugin metadata
|
|
src/ the plugin, written as an ordinary Python package
|
|
main.py entry module — exactly one BasePlugin subclass, absolute imports only
|
|
screenshots.py FLAG_SECURE removal (FlagSecureReason + Window.setFlags hooks)
|
|
forwarding.py unlocks forward UI and intercepts forwards of protected messages
|
|
copier.py re-sends protected messages as copies (downloads + re-uploads media, albums)
|
|
badge.py red lock before protected chats' names (chat list, header, chat info)
|
|
protection.py shared "does this chat restrict saving content" check
|
|
hooking.py shared Xposed hook helpers
|
|
tools/
|
|
bundle.py compiles plugin.json + src/ into dist/<id>.plugin
|
|
devclient.py speaks the on-device dev-server protocol (127.0.0.1:42690)
|
|
verify_bundle.py offline harness that proves a built bundle behaves correctly, no phone needed
|
|
release.py publishes a built bundle to a Gitea release (used by CI)
|
|
icon_png.py renders images/icon.svg to a square PNG
|
|
images/icon.svg the plugin icon, source of truth for any PNG export
|
|
.gitea/workflows/ CI that builds, verifies and publishes the .plugin to Releases
|
|
scripts/ ADB debug-loop automation and the git hooks
|
|
docs/ these notes + sdk-notes.md, the condensed SDK API surface
|
|
```
|
|
|
|
## The three commands that matter
|
|
|
|
```bash
|
|
python3 tools/bundle.py --release # compile src/ -> dist/<id>.plugin
|
|
python3 tools/verify_bundle.py dist/<id>.plugin # offline proof the bundle works, no device needed
|
|
bash scripts/deploy.sh --enable # build (--dev) + push to a connected device + enable + reload
|
|
```
|
|
|
|
`bundle.py` walks `src/` recursively, embeds every `.py` file's source and dotted module name
|
|
into a compressed, base64-encoded payload, and appends a small runtime preamble that installs
|
|
a private import hook (scoped to a per-module `__builtins__` dict, never touching
|
|
`sys.modules`) so cross-module and cross-package imports resolve exactly as they would if the
|
|
files were still on disk. `--dev` (the default) embeds absolute local paths so a debugger
|
|
resolves breakpoints against your real source files; `--release` embeds repo-relative paths
|
|
for distribution. Both modes produce byte-reproducible output for a given `src/` + `plugin.json`.
|
|
Its first run in a clone also enables the repo's git hooks (see
|
|
[Git hooks and versioning](versioning-and-releases.md#git-hooks-and-versioning)).
|
|
|
|
## Exporting the icon as PNG
|
|
|
|
`tools/icon_png.py` renders `images/icon.svg` to `images/icon.png`, 512x512 by default.
|
|
`--resolution` sets the size of both sides, so `--resolution 1024` gives 1024x1024:
|
|
|
|
```bash
|
|
python3 tools/icon_png.py # images/icon.png, 512x512
|
|
python3 tools/icon_png.py --resolution 1024 # images/icon.png, 1024x1024
|
|
python3 tools/icon_png.py some.svg -o out.png
|
|
```
|
|
|
|
The output is always PNG; any other `-o` extension is rejected. The script itself is stdlib
|
|
only and hands the rendering to the first renderer it finds: the `cairosvg` Python package,
|
|
`rsvg-convert` (librsvg), ImageMagick or Inkscape. Install any one of them.
|