robo.js icon indicating copy to clipboard operation
robo.js copied to clipboard

@robojs/welcome - Welcome & Goodbye for Discord bots

Open Pkmmte opened this issue 2 months ago • 2 comments

Motivation

MEE6/Dyno-style welcome features are universally loved: a warm channel greeting and optional DM onboarding. Robo.js already provides the primitives: file-based commands/events and a tiny KV store (Flashcore). This plugin will make onboarding new members delightful and easy to configure.

Goals

  • Welcome & goodbye messages, configurable per guild
  • Optional DM onboarding message to new members
  • Simple message definitions (plain text and basic embed JSON)
  • Per-guild persistence with Flashcore (clean namespacing)
  • Helpful preview command(s) for fast iteration
  • Optional HTTP API when @robojs/server is installed (not a hard dep)
  • Friendly docs and examples

User Stories

  • As a server admin, I want to set a welcome channel and message quickly so new members feel greeted.
  • As a server admin, I want to send a concise DM with helpful links to new members.
  • As a moderator, I want to preview the messages without waiting for a real member to join.

Acceptance Criteria

  • Slash commands to configure welcome and goodbye flows are available and auto-register in a Robo project.
  • guildMemberAdd and guildMemberRemove events trigger appropriate messages.
  • Welcome and goodbye messages can include placeholder tokens and support text or minimal embed JSON.
  • DM onboarding sends to new members when configured and gracefully handles closed DMs.
  • /welcome preview and /goodbye preview display exactly what would be sent.
  • Per-guild settings persist reliably using Flashcore, isolated by guildId.
  • Optional HTTP API automatically mounts only if @robojs/server is installed.
  • Clear documentation about required Discord intents and bot permissions.

Scope & Features

1) Welcome message (channel)

  • Configure a target text channel.
  • Message can be either plain text or a minimal embed JSON.
  • Simple placeholder tokens (see Tokens).

2) Goodbye message (channel)

  • Optional; same capabilities as Welcome.

3) DM Onboarding (optional)

  • Plain text or minimal embed JSON sent to the new user.
  • Graceful fallback if user DMs are closed (log + optional ephemeral notice to admin who ran preview).

4) Preview

  • Command to render messages now (to channel or ephemeral) so admins can iterate fast.

5) Rate-safe delivery

  • Queue + backoff to stay within Discord limits (burst-join scenarios).

Tokens (simple placeholders)

Supported in text and embed fields:

  • {user} — user mention
  • {username} — username
  • {tag} — username#discriminator (or username if discriminator-less)
  • {id} — user ID
  • {guild} — guild name
  • {memberCount} — current member count

Unresolved tokens remain literal. Keep this minimal for v1; more can be added later.

API Design

Slash Commands

/welcome set-channel <#channel>
/welcome message set <text-or-embed-json>
/welcome message clear
/welcome dm set <text-or-embed-json>
/welcome dm clear
/welcome toggle <on|off>
/welcome preview [here|channel]

/goodbye set-channel <#channel>
/goodbye message set <text-or-embed-json>
/goodbye message clear
/goodbye toggle <on|off>
/goodbye preview [here|channel]

Notes

  • text-or-embed-json accepts either raw text or a minimal embed shape (see Examples)
  • Permission checks: bot must be able to Send Messages/Embed Links in the configured channel

Imperative API (for future dashboards)

export interface WelcomeConfig {
  enabled?: boolean
  channelId?: string
  message?: TextOrEmbed
  dm?: TextOrEmbed
  goodbye?: {
    enabled?: boolean
    channelId?: string
    message?: TextOrEmbed
  }
}

export type TextOrEmbed =
  | { type: 'text'; content: string }
  | { type: 'embed'; data: MinimalEmbed }

export const Welcome = {
  getGuildConfig(guildId: string): Promise<WelcomeConfig>,
  setGuildConfig(guildId: string, patch: Partial<WelcomeConfig>): Promise<void>,
  resetGuildConfig(guildId: string): Promise<void>,
  preview(guildId: string, opts?: { channelId?: string; dm?: boolean }): Promise<void>
}

Optional HTTP API (mounted only if @robojs/server is installed)

  • Base: /api/welcome/:guildId
  • GET → returns WelcomeConfig
  • PATCH → partial update of config
  • POST /preview → triggers a preview
  • Auth: use a simple bearer token from env for MVP; document that this is intended for private dashboards

Behavior Details

Events & Intents

  • Subscribe to guildMemberAdd and guildMemberRemove.
  • Document how to enable Server Members Intent in the bot settings and in code.

Rate Limits

  • Use a small in-memory queue for outbound messages; respect 429s and retry-after headers.
  • Coalesce duplicate joins when many happen at once (lightweight debounce).

Permissions & Safety

  • Validation when setting channels.
  • Helpful error messages if permissions are missing.

DM Fallback

  • If DM send fails, log the failure; do not spam retries.

Data Model (Flashcore)

  • Namespace: guildId
  • Key: welcome:config
  • Shape: WelcomeConfig
  • Versioning: include _v in the stored object (for upgrade functions in future changes later)

Architecture & File Layout

@robojs/welcome
├─ package.json
├─ src/
│  ├─ commands/
│  │  ├─ welcome/
│  │  │  ├─ set-channel.ts
│  │  │  ├─ message-set.ts
│  │  │  ├─ message-clear.ts
│  │  │  ├─ dm-set.ts
│  │  │  ├─ dm-clear.ts
│  │  │  ├─ toggle.ts
│  │  │  └─ preview.ts
│  │  └─ goodbye/
│  │     ├─ set-channel.ts
│  │     ├─ message-set.ts
│  │     ├─ message-clear.ts
│  │     ├─ toggle.ts
│  │     └─ preview.ts
│  ├─ events/
│  │  ├─ guildMemberAdd.ts
│  │  └─ guildMemberRemove.ts
│  ├─ lib/
│  │  ├─ config.ts      # Flashcore get/set, schema, defaults, migrations
│  │  ├─ render.ts      # token expansion + embed builder
│  │  ├─ post.ts        # channel/DM posting with queue + backoff
│  │  └─ permissions.ts # capability checks & helpful errors
│  └─ api/ (optional; only if @robojs/server is installed)
│     ├─ welcome.get.ts
│     ├─ welcome.patch.ts
│     └─ preview.post.ts
└─ README.md

Examples

1) Minimal welcome text

Welcome {user}! You’re member #{memberCount}. Please read the rules in #rules.

2) Minimal embed JSON

{
  "type": "embed",
  "data": {
    "title": "Welcome, {username}! 🎉",
    "description": "Say hi to {user}! You’re member #{memberCount}.",
    "image": "https://example.com/welcome-banner.png"
  }
}

3) DM onboarding example

Welcome to {guild}! Quick links:
• Rules: #rules
• Roles: #get-roles
• Introductions: #introductions

Setup Notes (for users)

  1. Install: npx robo add @robojs/welcome
  2. Ensure Server Members Intent is enabled (Discord developer portal + client code)
  3. Run locally: npx robo dev
  4. Configure with /welcome … commands

Testing (encouraged, not required)

  • Unit tests for token expansion and config get/set
  • Basic event simulation for guildMemberAdd to assert the right post destination
  • Linting/formatting checks as in repo standards

References

Pkmmte avatar Oct 06 '25 05:10 Pkmmte

@Pkmmte I wan't to work on this. Can I get assigned?

dthlss26 avatar Oct 08 '25 12:10 dthlss26

@dthlss26 Sure, task has been assigned! Feel free to reach out either here or on our Discord if you have any questions.

Pkmmte avatar Oct 10 '25 08:10 Pkmmte