Important: This documentation covers Yarn 1 (Classic).
For Yarn 2+ docs and migration guide, see yarnpkg.com.

Package detail

invitron

Boda335169Apache-2.01.0.1TypeScript support: included

A powerful Discord.js invite tracker with persistent storage, member analytics, vanity URL support, and comprehensive join monitoring system for Discord bots.

discord, discord.js, discordjs, invite-tracker, invite-analytics, discord-bot, server-analytics, member-tracking, join-tracker, invite-monitoring, discord-invites, guild-analytics, leaderboard, statistics, metrics, persistent-storage, vanity-url, audit-logs, typescript, nodejs

readme

Invitron Logo

A powerful Discord.js invite tracker with persistent storage and comprehensive analytics

NPM Version NPM Downloads NPM License Discord GitHub Stars

🎯 Track member joins and leaves via invites  
📝 Support for normal, vanity, and audit-log based invites  
💾 Optional persistent JSON storage with analytics
📊 Built-in leaderboards and comprehensive statistics

InstallationQuick StartDocumentationExamples


✨ Features

  • 🌐 Complete Invite Tracking - Monitor all guild member joins and leaves
  • 📊 Advanced Analytics - Leaderboards, statistics, and detailed invite data
  • 🤖 Bot-Friendly - Optional bot filtering and comprehensive error handling
  • 💾 Persistent Storage - Local JSON file storage with automatic data management
  • 🔄 Real-time Updates - Automatic invite cache management and event handling
  • 🛡️ Multiple Sources - Support for normal invites, vanity URLs, and audit logs
  • 🧪 Debug Support - Comprehensive logging for easier troubleshooting
  • TypeScript Ready - Fully typed with excellent IDE support
  • 🎛️ Highly Configurable - Flexible options for different use cases

📦 Installation

# Using npm
npm install invitron

# Using yarn  
yarn add invitron

# Using pnpm
pnpm add invitron

Requirements:

  • Node.js 16.9.0 or higher
  • Discord.js v14.11.0 or higher

🚀 Quick Start

Basic Setup

import { Client, GatewayIntentBits } from "discord.js";
import InvitesTracker from "invitron";

const client = new Client({ 
  intents: [
    GatewayIntentBits.Guilds, 
    GatewayIntentBits.GuildMembers, 
    GatewayIntentBits.GuildInvites
  ] 
});

// Initialize the tracker
const tracker = InvitesTracker.init(client, {
  fetchGuilds: true,      // Load existing invites on startup
  fetchVanity: true,      // Track vanity URL joins
  fetchAuditLogs: true,   // Use audit logs as fallback
  ignoreBots: true,       // Ignore bot joins
  deductOnLeave: true,    // Remove invite credit when members leave
  storage: { 
    enabled: true, 
    path: "./data/invites.json" 
  }
});

// Listen for member joins
tracker.on("guildMemberAdd", (member, joinData) => {
  const { inviter, code, totalInvites, type } = joinData;

  if (type === "normal" && inviter) {
    console.log(`👋 ${member.user.tag} joined using ${inviter.tag}'s invite (${code})`);
    console.log(`📊 ${inviter.tag} now has ${totalInvites} total invites`);
  }
});

client.login("YOUR_BOT_TOKEN");

Advanced Usage

// Get user's invite statistics
const userInvites = tracker.getInvites(guildId, userId);
console.log(`User has ${userInvites} invites`);

// Get server leaderboard
const leaderboard = tracker.getLeaderboard(guildId, 10);
leaderboard.forEach((entry, index) => {
  console.log(`${index + 1}. User ${entry.userId}: ${entry.invites} invites`);
});

// Get top inviter
const topInviter = tracker.getTopInviter(guildId);
if (topInviter) {
  console.log(`🏆 Top inviter: ${topInviter.userId} with ${topInviter.invites} invites`);
}

// Reset guild data
tracker.resetGuild(guildId);

📖 API Reference

InvitesTracker.init(client, options)

Initializes the invite tracker with the specified Discord client and options.

Parameters

Parameter Type Default Description
client Client - Discord.js client instance
options TrackerOptions {} Configuration options

TrackerOptions

Option Type Default Description
fetchGuilds boolean false Preload invites from all guilds on startup
fetchVanity boolean false Track joins via vanity URLs
fetchAuditLogs boolean false Use audit logs when invite source is unknown
debug boolean false Enable debug logging
ignoreBots boolean false Ignore bot joins/leaves
deductOnLeave boolean false Subtract invite count when members leave
storage.enabled boolean false Enable persistent storage
storage.path string "./invites.json" Path to storage file

Methods

getInvites(guildId: string, userId: string): number

Returns the total number of invites for a user in the specified guild.

resetGuild(guildId: string): void

Resets all invite data for the specified guild.

getTopInviter(guildId: string): { userId: string; invites: number } | null

Returns the user with the most invites in the guild.

getLeaderboard(guildId: string, limit?: number): Array<{ userId: string; invites: number }>

Returns a sorted leaderboard of inviters (default limit: 10).

Events

guildMemberAdd

Emitted when a member joins a guild.

  • member: The member who joined
  • joinData: Detailed information about the join

guildMemberRemove

Emitted when a member leaves a guild.

  • member: The member who left

💡 Examples

Discord Bot Command Example

// !invites command
if (message.content === "!invites") {
  const userId = message.author.id;
  const guildId = message.guild!.id;
  const invites = tracker.getInvites(guildId, userId);

  message.reply(`You have **${invites}** invites! 🎉`);
}

// !leaderboard command  
if (message.content === "!leaderboard") {
  const guildId = message.guild!.id;
  const leaderboard = tracker.getLeaderboard(guildId, 5);

  let response = "🏆 **Top Inviters:**\n";
  leaderboard.forEach((entry, index) => {
    const user = client.users.cache.get(entry.userId);
    response += `${index + 1}. ${user?.tag || 'Unknown'}: ${entry.invites} invites\n`;
  });

  message.reply(response);
}

Slash Command Example

// Register slash command
const invitesCommand = {
  name: 'invites',
  description: 'Check your invite count',
  options: [{
    name: 'user',
    description: 'User to check (optional)',
    type: 6, // USER type
    required: false
  }]
};

// Handle slash command
client.on('interactionCreate', async (interaction) => {
  if (!interaction.isChatInputCommand() || interaction.commandName !== 'invites') return;

  const targetUser = interaction.options.getUser('user') || interaction.user;
  const invites = tracker.getInvites(interaction.guildId!, targetUser.id);

  await interaction.reply(`${targetUser.tag} has **${invites}** invites! 🎯`);
});

🔧 Configuration Examples

Minimal Setup

const tracker = InvitesTracker.init(client);

Production Setup

const tracker = InvitesTracker.init(client, {
  fetchGuilds: true,
  fetchVanity: true,
  fetchAuditLogs: true,
  ignoreBots: true,
  deductOnLeave: true,
  storage: {
    enabled: true,
    path: process.env.DATA_PATH || "./data/invites.json"
  }
});

Development Setup

const tracker = InvitesTracker.init(client, {
  debug: true,
  fetchGuilds: true,
  storage: { enabled: true }
});

🤝 Contributing

We welcome contributions! Please see our Contributing Guide for details.

  1. Fork the repository
  2. Create your feature branch (git checkout -b feature/amazing-feature)
  3. Commit your changes (git commit -m 'Add some amazing feature')
  4. Push to the branch (git push origin feature/amazing-feature)
  5. Open a Pull Request

📄 License

This project is licensed under the Apache-2.0 License - see the LICENSE file for details.


🆘 Support


Made with ❤️ by boda335