2 GrumpyInvites EN
darksoon edited this page 2026-07-11 13:15:17 +02:00

Invites — Invite Tracking, Leaderboard & Role Rewards

GrumpyInvites automatically detects which invite link (including the server's vanity link) was used for a new join, keeps per-inviter stats, and can automatically grant a role once someone reaches a configured invite threshold.


Example Scenario (Step by Step)

Sven wants to know who his most active "recruiters" are, and give them a special role for it — without counting anything by hand.

  1. Add a reward tier to configs/modules/invites.yml (copy the role ID from Discord first — right-click the role → "Copy ID", Developer Mode must be enabled in Discord for this):
    rewardRoles:
      - invites: 5
        roleId: "123456789012345678"   # e.g. role "🌟 Server Recruiter"
    
    Then run /invites reload so the change applies without a bot restart.
  2. Jonas creates his own invite link via Discord's built-in feature (channel → Invite) and shares it.
  3. Five new members join via Jonas's link. The bot detects this automatically on every join — nothing else to do.
  4. Once the fifth join counts (non-fake, still in the server), the bot automatically grants the 🌟 Server Recruiter role to Jonas.
  5. Check how Jonas is doing:
    /invites stats user:@Jonas
    
    → shows e.g. Total: 5, Regular: 5, Bonus: 0, Left again: 0, Suspicious: 0
  6. Show the server-wide leaderboard:
    /invites leaderboard
    

Special case — giveaway prize: Someone won a contest and should get 3 extra invites credited without actually having invited 3 people:

/invites bonus user:@Jonas amount:3

These count toward role rewards exactly like "real" invites.


Activation

In configs/config.yml:

addons:
  invites: true

On first start, configs/modules/invites.yml is created.


invites.yml

enabled: true

fakeThresholdDays: 7    # Accounts younger than X days count as "suspicious" (fake)
logChannelId: ""         # Channel for "X joined, invited by Y" posts. "" = don't post

rewardRoles: []
# Example:
# rewardRoles:
#   - invites: 5
#     roleId: "123456789012345678"
#   - invites: 10
#     roleId: "234567890123456789"
Field Default Description
fakeThresholdDays 7 Account age in days below which a join is marked "suspicious"
logChannelId "" Optional channel for join logs. Empty = don't post
rewardRoles [] List of invites (threshold) + roleIdonly ever granted, never auto-revoked

How Attribution Works

On startup and on every invite create/delete, the bot keeps an in-memory snapshot of all server invites (code, creator, use count). When a new member joins, it compares that snapshot against a fresh fetch:

  1. A known invite's use count went up → that invite was used.
  2. An invite disappeared entirely, but had a maxUses limit that was just reached → Discord auto-deletes single-use/limited invites the instant the last use is consumed, so no "increased count" is visible in that case. The bot detects this separately.
  3. Vanity URL (e.g. discord.gg/minetechworld) — compared via its own separate use counter.
  4. Nothing detectable (e.g. server discovery, widget join) → logged as "unknown", doesn't count for anyone.

After every join the snapshot is resynced so drift never accumulates over time. If multiple members join at the same moment, the bot processes them sequentially (not in parallel) — otherwise two joins could accidentally get attributed to the same invite.

Bot joins are not tracked — a bot is added via the OAuth2 "invite bot" flow, which never consumes a regular server invite.


"Suspicious" (Fake) Joins

If the new member's Discord account is younger than fakeThresholdDays, the join is marked as fake. Fake joins:

  • are flagged separately in the log
  • don't count toward the leaderboard, /invites stats (regular), or role rewards
  • still show up in the fake stat, so abuse (e.g. alt-account farming for invite rewards) stays visible

Leaving the Server

If a member leaves the server again, their most recent open join record is marked as "left". This:

  • counts toward the inviter's left stat
  • does not remove any role reward already granted — once a role has been granted it stays, even if the invited user later leaves

Commands

/invites stats [user]

Shows invite stats — your own or another member's.

Field Meaning
Total Regular + Bonus (this is what counts for role rewards)
Regular Successful, non-fake joins who are still in the server
Bonus Manually granted bonus invites (see /invites bonus)
Left again Invited members who have since left the server
Suspicious Joins from accounts younger than fakeThresholdDays
/invites stats
/invites stats user:@Jonas

Permission: Everyone


/invites leaderboard [limit]

Ranks the top inviters by total (regular + bonus).

Option Description
limit How many to show (default 10, max 25)
/invites leaderboard
/invites leaderboard limit:5

Permission: Everyone


/invites bonus <user> <amount>

Grants (or removes) manual bonus invites — e.g. as a giveaway prize or special reward. amount can be negative to take bonus invites back away.

/invites bonus user:@Jonas amount:5
/invites bonus user:@Jonas amount:-2

Permission: Manage Guild


/invites reload

Reloads invites.yml without restarting the bot.

/invites reload

Permission: Manage Guild


Role Rewards

Once a member's total (regular + bonus) reaches a threshold configured in rewardRoles, the bot automatically grants the matching role — checked right after every successful, non-fake join.

  • Roles are only ever granted, never auto-removed (not even if an invited member later leaves) — same behavior as the Leveling module's role rewards.
  • Multiple thresholds are allowed and all of them are granted once reached (not just the highest) — e.g. with thresholds at 5 and 10, a user with 12 invites gets both roles.
  • The bot needs Manage Roles, and its own role must sit above the reward role in the hierarchy, otherwise it's silently skipped.

Log Example

With logChannelId set:

📨 @NewUser joined — invited by @Jonas (code `abc123`, now 6 invites)
📨 @SuspiciousUser joined — invited by @Jonas (code `abc123`, now 7 invites) ⚠️ (new account — doesn't count toward rewards)
📨 @AnotherUser joined via the vanity link
📨 @OneMore joined — invite could not be determined (discovery/widget or similar)

Permissions

Command Permission
/invites stats Everyone
/invites leaderboard Everyone
/invites bonus Manage Guild
/invites reload Manage Guild

For automatic attribution the bot needs the Manage Guild permission (to view invites) and the Server Invites gateway intent (already part of the standard bot invite). All commands are guild-only (no DM context).