Move to rp.jarviscli.dev with real per-plugin pages
This commit is contained in:
parent
6af091940f
commit
37ceb8e424
9 changed files with 218 additions and 23 deletions
53
.github/ISSUE_TEMPLATE/bug_report.yml
vendored
Normal file
53
.github/ISSUE_TEMPLATE/bug_report.yml
vendored
Normal file
|
|
@ -0,0 +1,53 @@
|
|||
name: Bug report
|
||||
description: Something in a plugin is broken or behaving wrong
|
||||
labels: ["bug"]
|
||||
body:
|
||||
- type: dropdown
|
||||
id: plugin
|
||||
attributes:
|
||||
label: Which plugin?
|
||||
options:
|
||||
- Staff Tags
|
||||
- RoleColorEverywhere
|
||||
- PronounDB
|
||||
- Message Snippets
|
||||
- Reminders
|
||||
- Not sure / something else
|
||||
validations:
|
||||
required: true
|
||||
|
||||
- type: textarea
|
||||
id: what-happened
|
||||
attributes:
|
||||
label: What happened?
|
||||
description: What did you expect, and what did you actually get?
|
||||
placeholder: "I tried /snippet welcome and nothing was sent to the channel."
|
||||
validations:
|
||||
required: true
|
||||
|
||||
- type: textarea
|
||||
id: repro
|
||||
attributes:
|
||||
label: Steps to reproduce
|
||||
placeholder: |
|
||||
1. Enable the plugin
|
||||
2. Run /snippet welcome
|
||||
3. ...
|
||||
validations:
|
||||
required: false
|
||||
|
||||
- type: input
|
||||
id: discord-version
|
||||
attributes:
|
||||
label: Discord app version (Settings → About)
|
||||
placeholder: "e.g. 338.4"
|
||||
validations:
|
||||
required: false
|
||||
|
||||
- type: textarea
|
||||
id: logs
|
||||
attributes:
|
||||
label: Anything in the Revenge debugger/logs?
|
||||
description: Settings → General → Debugger, if you have it enabled
|
||||
validations:
|
||||
required: false
|
||||
5
.github/ISSUE_TEMPLATE/config.yml
vendored
Normal file
5
.github/ISSUE_TEMPLATE/config.yml
vendored
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
blank_issues_enabled: false
|
||||
contact_links:
|
||||
- name: Core Revenge app issue (not a plugin)
|
||||
url: https://github.com/revenge-mod/revenge-bundle/issues
|
||||
about: If the problem is with Revenge itself rather than one of these plugins, report it there instead.
|
||||
29
.github/ISSUE_TEMPLATE/feature_request.yml
vendored
Normal file
29
.github/ISSUE_TEMPLATE/feature_request.yml
vendored
Normal file
|
|
@ -0,0 +1,29 @@
|
|||
name: Feature request / new plugin idea
|
||||
description: Something you want added to an existing plugin, or a new plugin entirely
|
||||
labels: ["enhancement"]
|
||||
body:
|
||||
- type: dropdown
|
||||
id: kind
|
||||
attributes:
|
||||
label: What kind of request is this?
|
||||
options:
|
||||
- New feature for an existing plugin
|
||||
- A brand new plugin idea
|
||||
validations:
|
||||
required: true
|
||||
|
||||
- type: input
|
||||
id: plugin
|
||||
attributes:
|
||||
label: Which plugin? (leave blank if this is a new plugin idea)
|
||||
placeholder: "e.g. Staff Tags"
|
||||
validations:
|
||||
required: false
|
||||
|
||||
- type: textarea
|
||||
id: description
|
||||
attributes:
|
||||
label: What do you want, and why?
|
||||
description: The more concrete, the better - what would you actually do with it?
|
||||
validations:
|
||||
required: true
|
||||
55
.github/ISSUE_TEMPLATE/plugin_broken.yml
vendored
Normal file
55
.github/ISSUE_TEMPLATE/plugin_broken.yml
vendored
Normal file
|
|
@ -0,0 +1,55 @@
|
|||
name: A plugin stopped working after a Discord update
|
||||
description: The most common failure mode here - Discord renamed/removed something a plugin depends on
|
||||
labels: ["bug", "discord-update"]
|
||||
body:
|
||||
- type: markdown
|
||||
attributes:
|
||||
value: |
|
||||
Discord's internals change without notice, and plugins in this ecosystem patch those internals
|
||||
directly - this is the single most common way something breaks here. Reports like this are
|
||||
genuinely useful, thank you.
|
||||
|
||||
- type: dropdown
|
||||
id: plugin
|
||||
attributes:
|
||||
label: Which plugin?
|
||||
options:
|
||||
- Staff Tags
|
||||
- RoleColorEverywhere
|
||||
- PronounDB
|
||||
- Message Snippets
|
||||
- Reminders
|
||||
validations:
|
||||
required: true
|
||||
|
||||
- type: dropdown
|
||||
id: surface
|
||||
attributes:
|
||||
label: What stopped showing up / working?
|
||||
description: Pick whichever's closest - helps narrow down which patch broke
|
||||
options:
|
||||
- Chat messages
|
||||
- Member list
|
||||
- Profile popout
|
||||
- Channel header
|
||||
- Typing indicator
|
||||
- Voice channel
|
||||
- A slash command
|
||||
- Not sure
|
||||
validations:
|
||||
required: false
|
||||
|
||||
- type: input
|
||||
id: discord-version
|
||||
attributes:
|
||||
label: Discord app version (Settings → About)
|
||||
placeholder: "e.g. 338.4"
|
||||
validations:
|
||||
required: true
|
||||
|
||||
- type: textarea
|
||||
id: worked-before
|
||||
attributes:
|
||||
label: Did this work before, and if so, roughly when did it stop?
|
||||
validations:
|
||||
required: false
|
||||
36
README.md
36
README.md
|
|
@ -2,11 +2,17 @@
|
|||
|
||||
A collection of plugins for [Revenge](https://github.com/revenge-mod/revenge-bundle), the Discord Android client mod.
|
||||
|
||||
**Browse them at [rp.jarviscli.dev](https://rp.jarviscli.dev)** - searchable, with a full detail page per plugin.
|
||||
|
||||
## Installing a plugin
|
||||
|
||||
1. Open Discord with Revenge installed, go to **Settings → Plugins**.
|
||||
2. Tap the `+` button and paste the plugin's install link (see below).
|
||||
3. Enable it.
|
||||
Each plugin has two URLs:
|
||||
|
||||
- `rp.jarviscli.dev/<plugin>/` - a real page describing the plugin (features, commands, how it works)
|
||||
- `rp.jarviscli.dev/<plugin>/install/` - the actual install link you paste into Revenge
|
||||
|
||||
To install: open Discord with Revenge installed, go to **Settings → Plugins**, tap `+`, and paste the
|
||||
`/install/` link.
|
||||
|
||||
## Plugins
|
||||
|
||||
|
|
@ -14,16 +20,16 @@ A collection of plugins for [Revenge](https://github.com/revenge-mod/revenge-bun
|
|||
|
||||
| Plugin | Status | Description | Install link |
|
||||
| --- | --- | --- | --- |
|
||||
| Staff Tags | Rebuilt | OWNER/ADMIN/STAFF/MOD-style tags next to members, computed from real server permissions. Per-tag text, colors, gradients, and visibility. | `https://everestmcarthur.github.io/revenge-plugins/staff-tags/` |
|
||||
| RoleColorEverywhere | Revived | A member's top role color shown in mentions, the typing indicator, voice channel names, member list role headers, and optionally message text. | `https://everestmcarthur.github.io/revenge-plugins/role-color-everywhere/` |
|
||||
| PronounDB | Revived | Shows a user's pronouns in their profile, if they've set them at pronoundb.org (nothing to configure in the plugin itself). | `https://everestmcarthur.github.io/revenge-plugins/pronoun-db/` |
|
||||
| Staff Tags | Rebuilt | OWNER/ADMIN/STAFF/MOD-style tags next to members, computed from real server permissions. Per-tag text, colors, gradients, and visibility. | `https://rp.jarviscli.dev/staff-tags/install/` |
|
||||
| RoleColorEverywhere | Revived | A member's top role color shown in mentions, the typing indicator, voice channel names, member list role headers, and optionally message text. | `https://rp.jarviscli.dev/role-color-everywhere/install/` |
|
||||
| PronounDB | Revived | Shows a user's pronouns in their profile, if they've set them at pronoundb.org (nothing to configure in the plugin itself). | `https://rp.jarviscli.dev/pronoun-db/install/` |
|
||||
|
||||
### Productivity
|
||||
|
||||
| Plugin | Status | Description | Install link |
|
||||
| --- | --- | --- | --- |
|
||||
| Message Snippets | New | Save reusable text and send it with `/snippet <name>`. Manage snippets in-app or with `/snippet-save`, `/snippet-delete`, `/snippet-list`. | `https://everestmcarthur.github.io/revenge-plugins/message-snippets/` |
|
||||
| Reminders | New | `/remind 20m Walk the dog` - fires while Discord is running. Can't wake the app from fully closed (no native notification access from a JS plugin). | `https://everestmcarthur.github.io/revenge-plugins/reminders/` |
|
||||
| Message Snippets | New | Save reusable text and send it with `/snippet <name>`. Manage snippets in-app or with `/snippet-save`, `/snippet-delete`, `/snippet-list`. | `https://rp.jarviscli.dev/message-snippets/install/` |
|
||||
| Reminders | New | `/remind 20m Walk the dog` - fires while Discord is running. Can't wake the app from fully closed (no native notification access from a JS plugin). | `https://rp.jarviscli.dev/reminders/install/` |
|
||||
|
||||
"Revived" means the plugin previously existed elsewhere, stopped working after a Discord/API update, and has been rebuilt here.
|
||||
"Rebuilt" means it's a from-scratch reimplementation of a previously-broken plugin with expanded features. "New" means
|
||||
|
|
@ -58,7 +64,19 @@ npm install
|
|||
npm run build
|
||||
```
|
||||
|
||||
Output is written to `dist/<plugin>/`.
|
||||
This runs both `build.mjs` (compiles every plugin in `plugins/*` into `dist/<id>/install/`) and
|
||||
`scripts/generate-site.mjs` (builds `dist/plugins-data.json` from those manifests + `site/meta.json`,
|
||||
and writes the website - a homepage at `dist/index.html` and a real page per plugin at `dist/<id>/index.html`).
|
||||
|
||||
## Releasing an update
|
||||
|
||||
1. Edit a plugin under `plugins/<id>/src/`.
|
||||
2. `npm run build` locally and sanity-check the output in `dist/`.
|
||||
3. `git add -A && git commit -m "..." && git push origin main`.
|
||||
4. GitHub Actions rebuilds and redeploys to `rp.jarviscli.dev` automatically (usually under a minute) -
|
||||
check progress at the repo's **Actions** tab.
|
||||
|
||||
There's no manual deploy step - anything merged to `main` goes live.
|
||||
|
||||
## Contributing
|
||||
|
||||
|
|
|
|||
|
|
@ -60,9 +60,11 @@ const plugins = [
|
|||
esbuild({ minify: true }),
|
||||
];
|
||||
|
||||
// Each plugin's actual install target (manifest.json + index.js) lives at /<id>/install/, so that
|
||||
// /<id>/ itself is free to be a real, bookmarkable HTML page describing the plugin (see generate-site.mjs).
|
||||
for (const plug of await readdir("./plugins")) {
|
||||
const manifest = JSON.parse(await readFile(`./plugins/${plug}/manifest.json`));
|
||||
const outPath = `./dist/${plug}/index.js`;
|
||||
const outPath = `./dist/${plug}/install/index.js`;
|
||||
|
||||
try {
|
||||
const bundle = await rollup({
|
||||
|
|
@ -90,7 +92,7 @@ for (const plug of await readdir("./plugins")) {
|
|||
const toHash = await readFile(outPath);
|
||||
manifest.hash = createHash("sha256").update(toHash).digest("hex");
|
||||
manifest.main = "index.js";
|
||||
await writeFile(`./dist/${plug}/manifest.json`, JSON.stringify(manifest));
|
||||
await writeFile(`./dist/${plug}/install/manifest.json`, JSON.stringify(manifest));
|
||||
|
||||
console.log(`Successfully built ${manifest.name}!`);
|
||||
} catch (e) {
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
import { readFile, writeFile, readdir, copyFile, stat } from "fs/promises";
|
||||
|
||||
const PAGES_BASE = "https://everestmcarthur.github.io/revenge-plugins";
|
||||
const PAGES_BASE = "https://rp.jarviscli.dev";
|
||||
const REPO_BASE = "https://github.com/everestmcarthur/revenge-plugins";
|
||||
|
||||
const meta = JSON.parse(await readFile("./site/meta.json", "utf8"));
|
||||
|
|
@ -12,7 +12,7 @@ for (const id of await readdir("./dist")) {
|
|||
|
||||
let manifest;
|
||||
try {
|
||||
manifest = JSON.parse(await readFile(`${dir}/manifest.json`, "utf8"));
|
||||
manifest = JSON.parse(await readFile(`${dir}/install/manifest.json`, "utf8"));
|
||||
} catch {
|
||||
continue; // not a plugin output directory
|
||||
}
|
||||
|
|
@ -33,7 +33,8 @@ for (const id of await readdir("./dist")) {
|
|||
features: info.features ?? [],
|
||||
commands: info.commands ?? [],
|
||||
limitations: info.limitations ?? "",
|
||||
installUrl: `${PAGES_BASE}/${id}/`,
|
||||
pageUrl: `${PAGES_BASE}/${id}/`,
|
||||
installUrl: `${PAGES_BASE}/${id}/install/`,
|
||||
sourceUrl: `${REPO_BASE}/tree/main/plugins/${id}`,
|
||||
issueUrl: `${REPO_BASE}/issues/new?title=${encodeURIComponent(`[${manifest.name}] `)}`
|
||||
});
|
||||
|
|
@ -44,5 +45,12 @@ plugins.sort((a, b) => a.category.localeCompare(b.category) || a.name.localeComp
|
|||
await writeFile("./dist/plugins-data.json", JSON.stringify(plugins, null, 2));
|
||||
await copyFile("./site/index.html", "./dist/index.html");
|
||||
await copyFile("./site/index.html", "./dist/404.html");
|
||||
await copyFile("./site/CNAME", "./dist/CNAME");
|
||||
|
||||
// Each plugin gets its own real, bookmarkable page at /<id>/ (not just a hash route) - it's the
|
||||
// same SPA shell, which reads location.pathname on boot to know which plugin to show directly.
|
||||
for (const p of plugins) {
|
||||
await copyFile("./site/index.html", `./dist/${p.id}/index.html`);
|
||||
}
|
||||
|
||||
console.log(`Generated site data for ${plugins.length} plugin(s).`);
|
||||
|
|
|
|||
1
site/CNAME
Normal file
1
site/CNAME
Normal file
|
|
@ -0,0 +1 @@
|
|||
rp.jarviscli.dev
|
||||
|
|
@ -96,6 +96,12 @@
|
|||
from { transform: translate3d(0,0,0) scale(1); }
|
||||
to { transform: translate3d(-2%, 2%, 0) scale(1.08); }
|
||||
}
|
||||
.hero-spotlight {
|
||||
position: absolute; inset: 0; z-index: 0; pointer-events: none; opacity: 0;
|
||||
background: radial-gradient(280px circle at var(--sx, 50%) var(--sy, 50%), color-mix(in srgb, var(--accent) 22%, transparent), transparent 70%);
|
||||
transition: opacity 0.25s ease;
|
||||
}
|
||||
.hero:hover .hero-spotlight { opacity: 1; }
|
||||
.hero-inner { position: relative; z-index: 1; }
|
||||
.mark {
|
||||
display: inline-flex;
|
||||
|
|
@ -294,6 +300,7 @@
|
|||
|
||||
<header class="hero" id="hero">
|
||||
<div class="hero-mesh" aria-hidden="true"></div>
|
||||
<div class="hero-spotlight" id="heroSpotlight" aria-hidden="true"></div>
|
||||
<div class="wrap hero-inner">
|
||||
<div class="mark">
|
||||
<svg viewBox="0 0 32 32" fill="none"><path d="M9 12l7-5 7 5v9l-7 5-7-5z" stroke="currentColor" stroke-width="2"/><circle cx="16" cy="16" r="3" fill="currentColor"/></svg>
|
||||
|
|
@ -471,7 +478,7 @@
|
|||
'<div class="cta">View details →</div>';
|
||||
|
||||
card.addEventListener("click", function () {
|
||||
location.hash = "#/plugin/" + p.id;
|
||||
navigateToPlugin(p.id);
|
||||
});
|
||||
|
||||
grid.appendChild(card);
|
||||
|
|
@ -508,6 +515,13 @@
|
|||
controlsEl.classList.toggle("stuck", window.scrollY > 8);
|
||||
});
|
||||
|
||||
var heroSpotlight = document.getElementById("heroSpotlight");
|
||||
heroEl.addEventListener("mousemove", function (e) {
|
||||
var rect = heroEl.getBoundingClientRect();
|
||||
heroSpotlight.style.setProperty("--sx", (e.clientX - rect.left) + "px");
|
||||
heroSpotlight.style.setProperty("--sy", (e.clientY - rect.top) + "px");
|
||||
});
|
||||
|
||||
/* ---------- Detail view ---------- */
|
||||
|
||||
function renderDetail(p) {
|
||||
|
|
@ -571,7 +585,7 @@
|
|||
actions.appendChild(issueLink);
|
||||
|
||||
document.getElementById("backLink").addEventListener("click", function () {
|
||||
history.pushState(null, "", location.pathname + location.search);
|
||||
history.pushState(null, "", "/");
|
||||
showGrid();
|
||||
});
|
||||
}
|
||||
|
|
@ -597,16 +611,26 @@
|
|||
document.title = "revenge-plugins";
|
||||
}
|
||||
|
||||
function routeFromHash() {
|
||||
var match = location.hash.match(/^#\/plugin\/([\w-]+)/);
|
||||
if (match) {
|
||||
/**
|
||||
* Each plugin has a real static page at /<id>/ (a copy of this same file), so a direct visit or
|
||||
* refresh works without any server-side routing - this just avoids a full reload when navigating
|
||||
* from within an already-loaded page.
|
||||
*/
|
||||
function navigateToPlugin(id) {
|
||||
history.pushState(null, "", "/" + id + "/");
|
||||
showDetail(id);
|
||||
}
|
||||
|
||||
function routeFromLocation() {
|
||||
var match = location.pathname.match(/^\/([\w-]+)\/?$/);
|
||||
if (match && match[1]) {
|
||||
showDetail(match[1]);
|
||||
} else {
|
||||
showGrid();
|
||||
}
|
||||
}
|
||||
|
||||
window.addEventListener("hashchange", routeFromHash);
|
||||
window.addEventListener("popstate", routeFromLocation);
|
||||
|
||||
/* ---------- Command palette ---------- */
|
||||
|
||||
|
|
@ -659,7 +683,7 @@
|
|||
var plugin = paletteMatches[i];
|
||||
if (!plugin) return;
|
||||
closePalette();
|
||||
location.hash = "#/plugin/" + plugin.id;
|
||||
navigateToPlugin(plugin.id);
|
||||
}
|
||||
|
||||
paletteInput.addEventListener("input", function (e) { renderPalette(e.target.value); });
|
||||
|
|
@ -692,14 +716,14 @@
|
|||
|
||||
/* ---------- Boot ---------- */
|
||||
|
||||
fetch("https://everestmcarthur.github.io/revenge-plugins/plugins-data.json")
|
||||
fetch("https://rp.jarviscli.dev/plugins-data.json")
|
||||
.then(function (r) { return r.json(); })
|
||||
.then(function (data) {
|
||||
state.plugins = data;
|
||||
renderStats();
|
||||
renderChips();
|
||||
render();
|
||||
routeFromHash();
|
||||
routeFromLocation();
|
||||
})
|
||||
.catch(function () {
|
||||
count.textContent = "";
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue