Skip to content

tnkerer/tribe-connect-bot

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

31 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Tribe Connect — Complete Setup & Deployment Guide

This document walks a brand-new developer from a clean machine to a fully-deployed, working Tribe Connect bot. Follow the sections in order — each one builds on the previous.


Table of Contents

  1. What This Bot Does
  2. Prerequisites
  3. Clone the Repository
  4. Create the Discord Application
  5. Set Up Firebase
  6. Create the X / Twitter App
  7. Get a RapidAPI Twitter241 Key
  8. Configure Your Local .env
  9. Install Dependencies and Test Locally
  10. Deploy Slash Commands
  11. Invite the Bot to a Test Server
  12. Smoke-Test the Bot Locally
  13. Deploy to Railway
  14. Switch X OAuth to Production URL
  15. Verify the Production Deployment
  16. Initialize the Bot on Your Discord Server
  17. Environment Variable Reference
  18. Files You'll Touch
  19. Troubleshooting

1. What This Bot Does

Tribe Connect is a Discord bot that lets community members link their X (Twitter) account, earn points for engaging with tweets the admin posts (reposts, comments, early-engager bonuses), spend points in a marketplace, and enter raffles. Admins manage points and view a leaderboard.

Stack:

  • Runtime: Node.js (ESM, "type": "module")
  • Bot library: discord.js v14
  • Database: Google Firestore (via firebase-admin)
  • Auth server: Express on PORT (handles X OAuth callback, exposes /health)
  • Twitter data: Twitter241 via RapidAPI (retweeters/commenters lookup)
  • Hosting: Railway.app (recommended)

2. Prerequisites

Install on your machine:

Tool Version Why
Node.js 18+ (20 LTS recommended) Runs the bot
Git any Clone & push the repo
A code editor VS Code recommended Editing
Railway CLI optional Easier deploys/logs

Accounts you'll need (all free to start):


3. Clone the Repository

git clone <your-repo-url> tribe
cd tribe

Important: Keep the repo private — even with .env gitignored, the codebase represents engagement logic you probably don't want public.


4. Create the Discord Application

4.1 Create the App

  1. Go to https://discord.com/developers/applications.
  2. Click "New Application", give it a name (e.g., Tribe Connect), accept ToS.
  3. From General Information, copy the Application ID → this is DISCORD_CLIENT_ID.

4.2 Create the Bot User

  1. In the left sidebar click Bot.
  2. Click "Reset Token" and copy the token → this is DISCORD_TOKEN.
    • You will only see this token once. Store it somewhere safe immediately.
  3. Under Privileged Gateway Intents, leave them all OFF. The bot only uses the unprivileged Guilds intent.
  4. Under Bot Permissions, you can ignore this section — we'll set permissions via the invite URL below.

4.3 Build the Invite URL

  1. Sidebar → OAuth2URL Generator.
  2. Scopes: check bot and applications.commands.
  3. Bot Permissions: check at minimum:
    • Manage Roles (assigning marketplace reward roles, raffle reward roles)
    • Manage Channels (used by /initiate to create the dedicated channels)
    • Manage Messages (cleaning up dashboards)
    • View Channels
    • Send Messages
    • Embed Links
    • Attach Files (for /export users CSV)
    • Read Message History
  4. Copy the generated URL at the bottom — you'll use it in Step 11 to invite the bot.

5. Set Up Firebase

5.1 Create the Project

  1. Go to https://console.firebase.google.comAdd project.
  2. Name it (e.g., tribe-connect), disable Google Analytics (not needed), finish.
  3. From Project Settings (gear icon) → General, copy the Project ID → this is FIREBASE_PROJECT_ID.

5.2 Enable Firestore

  1. Left sidebar → Build → Firestore DatabaseCreate database.
  2. Start in production mode (we'll lock rules below).
  3. Choose a region near your users (e.g., us-central1 or europe-west1). This cannot be changed later.

5.3 Create the Required Composite Index

The leaderboard and CSV export use a collectionGroup query that needs an index.

  1. Firestore → Indexes tab → Add index.
  2. Configure:
    • Collection ID: guilds
    • Query scope: Collection group (not Collection)
    • Fields:
      • guildIdAscending
      • pointsDescending
      • __name__Descending (Firestore adds this automatically)
  3. Click Create. It takes a few minutes to build.

If you skip this, leaderboard / export commands will throw FAILED_PRECONDITION: The query requires an index — and the error message will include a direct link to create the index it needs.

5.4 Lock Down Security Rules

Firestore → Rules → paste:

rules_version = '2';
service cloud.firestore {
  match /databases/{database}/documents {
    // The Admin SDK bypasses these rules — this denies all other access.
    match /{document=**} {
      allow read, write: if false;
    }
  }
}

Click Publish. Because the bot uses the Admin SDK (service account), it bypasses these rules — but no one else can touch your data.

5.5 Download the Service Account Key

  1. Project SettingsService accounts tab → Generate new private keyGenerate key.
  2. A JSON file downloads. Treat this like a password.
  3. Move it into the repo root and rename it to serviceAccountKey.json:
mv ~/Downloads/tribe-connect-*.json ./serviceAccountKey.json

The file is already in .gitignore — verify with git status that it does not appear.


6. Create the X / Twitter App

6.1 Apply for Developer Access (if you don't have it)

Go to https://developer.x.com/en/portal/dashboard and complete the developer signup. A free tier is sufficient for OAuth (we read user identity only — bulk tweet data comes from RapidAPI).

6.2 Create a Project + App

  1. Projects & AppsNew Project → name it Tribe Connect, pick any use case.
  2. Inside the project create an App (or reuse the auto-created one).

6.3 Configure User Authentication

  1. Inside the app → User authentication settingsSet up (or Edit).
  2. Configure:
    • App permissions: Read
    • Type of App: Web App, Automated App or Bot
    • Callback URI / Redirect URL — for now use the local URL:
      http://localhost:3100/auth/x/callback
      
      (You'll add the production URL alongside this one in Step 14.)
    • Website URL: anything valid (e.g., https://example.com)
  3. Save.

6.4 Copy OAuth Credentials

In the app → Keys and tokens tab:

  • OAuth 2.0 Client ID and Client Secret → click Regenerate if not visible. Copy both:
    • X_CLIENT_ID
    • X_CLIENT_SECRET
  • Bearer Token (optional) → X_BEARER_TOKEN. The bot only uses this for a couple of public endpoints; you can leave it blank.

7. Get a RapidAPI Twitter241 Key

The bot uses Twitter241 to fetch the list of users who reposted/commented on a tweet — this is what powers /verify on tweet dashboards.

  1. Go to https://rapidapi.com/davethebeast/api/twitter241.
  2. Sign up / log in.
  3. Click Subscribe to Test → pick a plan (the free tier works for development; pick a paid plan for production based on your server size).
  4. On any endpoint page in the Code Snippets panel, copy:
    • X-RapidAPI-KeyRAPIDAPI_KEY
    • X-RapidAPI-HostRAPIDAPI_HOST (should be twitter241.p.rapidapi.com)

8. Configure Your Local .env

cp .env.example .env

Open .env and fill in everything you collected above. A working local config looks like this:

# Discord
DISCORD_TOKEN=MTQxxxxxxxxxxxxxxxxxxxxxxxxxxx.GxxxxX.xxxxxxxxxxxxxxxxxxxxxxxxxx
DISCORD_CLIENT_ID=1234567890123456789

# Firebase
GOOGLE_APPLICATION_CREDENTIALS=./serviceAccountKey.json
FIREBASE_PROJECT_ID=tribe-connect-abc12

# X OAuth
X_CLIENT_ID=eVFtb0RMRxxxxxxxxxxxxxxxxxxxxx
X_CLIENT_SECRET=cmqOYDes2snxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
X_REDIRECT_URI=http://localhost:3100/auth/x/callback
X_SCOPES=tweet.read users.read like.read offline.access
X_BEARER_TOKEN=

# RapidAPI
RAPIDAPI_KEY=252b7e5f8amshxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
RAPIDAPI_HOST=twitter241.p.rapidapi.com
RAPIDAPI_BASE_URL=https://twitter241.p.rapidapi.com
RAPIDAPI_TIMEOUT_MS=10000
RAPIDAPI_MAX_PAGES=3

# Public URL
BOT_PUBLIC_URL=http://localhost:3100
PORT=3100

A full description of each variable is in Section 17.

Critical: X_REDIRECT_URI must be character-for-character identical to the Callback URI you configured in the X Developer Portal. A trailing slash mismatch will break OAuth.


9. Install Dependencies and Test Locally

npm install
npm start

You should see:

✅ Firebase credentials written to file        (Linux/macOS only — see note)
✅ Logged in as Tribe Connect#0000
✅ Auth server listening on http://localhost:3100
   Health check: http://localhost:3100/health
✅ Setting up cron jobs for Tribe Connect#0000

Windows note: npm start runs chmod +x start.sh && ./start.sh && node src/index.js. On Windows, chmod and ./start.sh won't work in PowerShell/cmd. Either:

  • Run the bot directly: node src/index.js, or
  • Use Git Bash / WSL to run npm start.

start.sh exists for Railway's Linux containers; locally you don't need it because your service account JSON is already on disk.

Verify the health endpoint in a separate terminal:

curl http://localhost:3100/health
# → ok

If anything throws on boot, jump to Troubleshooting.


10. Deploy Slash Commands

Slash commands must be registered with Discord before they appear in the UI. This is separate from the bot running.

node src/deploy-commands.js

Expected output:

Started refreshing N application (/) commands.
✅ Successfully reloaded N application (/) commands.

Re-run this any time you add/modify commands in src/commands.js. Global commands can take up to an hour to propagate; a freshly-deployed command usually appears within a few minutes.


11. Invite the Bot to a Test Server

  1. Paste the OAuth2 URL you generated in Step 4.3 into a browser.
  2. Pick a server you have Manage Server permission on (create a private test server if you don't have one).
  3. Click Authorize.

The bot should now appear in the server's member list (offline until you start the bot locally or remotely).


12. Smoke-Test the Bot Locally

With npm start still running:

  1. In your test server, type / and confirm Tribe Connect commands appear.
  2. Run /initiate. This creates the marketplace, tweets, raffles, and intro channels along with the Tribe Channels role.
  3. Run /connect x. You should get a button that opens http://localhost:3100/auth/x/start?discordId=… and redirects to X. Authorize, then verify you land on the styled success page.
  4. Run /profile. You should see your Discord/X linkage.
  5. Run /engage points repost:2 comment:3 to set point values.
  6. Run /tweet <any tweet URL> to spawn an engagement dashboard.

If all six work, your local setup is healthy.


13. Deploy to Railway

13.1 Push to GitHub

git add .
git commit -m "Initial commit"
git remote add origin git@github.com:YOUR-ORG/tribe.git
git push -u origin main

Confirm .env and serviceAccountKey.json are not in the commit (run git ls-files | grep -E '\.env$|serviceAccountKey'; output should be empty).

13.2 Create the Railway Project

  1. Go to https://railway.app/dashboardNew ProjectDeploy from GitHub repo.
  2. Authorize Railway against your GitHub if prompted, then pick the tribe repository.
  3. Railway autodetects Node.js (Nixpacks) and starts building. Wait for the first build to finish — it will crash because env vars aren't set yet. That's expected.

13.3 Generate the Public Domain

  1. Project → SettingsNetworkingGenerate Domain.
  2. Copy the URL (e.g. https://tribe-connect-production-abc123.up.railway.app). You'll need it in the next step.

13.4 Set Environment Variables

Project → Variables tab → Raw Editor, paste this (substitute your real values):

DISCORD_TOKEN=<from Step 4.2>
DISCORD_CLIENT_ID=<from Step 4.1>

FIREBASE_PROJECT_ID=<from Step 5.1>
GOOGLE_APPLICATION_CREDENTIALS=/app/firebase-credentials.json
GOOGLE_APPLICATION_CREDENTIALS_JSON=<see 13.5 below>

X_CLIENT_ID=<from Step 6.4>
X_CLIENT_SECRET=<from Step 6.4>
X_REDIRECT_URI=https://<your-railway-domain>/auth/x/callback
X_SCOPES=tweet.read users.read like.read offline.access

RAPIDAPI_KEY=<from Step 7>
RAPIDAPI_HOST=twitter241.p.rapidapi.com
RAPIDAPI_BASE_URL=https://twitter241.p.rapidapi.com
RAPIDAPI_TIMEOUT_MS=10000
RAPIDAPI_MAX_PAGES=3

BOT_PUBLIC_URL=https://<your-railway-domain>
PORT=3000

13.5 Add the Firebase Credentials as a Variable

GOOGLE_APPLICATION_CREDENTIALS_JSON is special: it holds the entire JSON of your service account.

  1. Open serviceAccountKey.json in a text editor.
  2. Copy the entire file contents (everything from the first { to the last }).
  3. In Railway, set GOOGLE_APPLICATION_CREDENTIALS_JSON to that value (the Raw Editor accepts multi-line JSON without issue).

When the container boots, start.sh writes that JSON to /app/firebase-credentials.json, which GOOGLE_APPLICATION_CREDENTIALS already points to. No code changes needed.

13.6 Redeploy

Railway redeploys automatically after variables change. Watch Deployments → View Logs; you want to see the same boot sequence from Section 9.

13.7 Deploy Slash Commands Against Production

Slash commands are deployed once per application (not per host), so if you already ran node src/deploy-commands.js locally against the same DISCORD_CLIENT_ID/DISCORD_TOKEN, they're already live. If you skipped local testing, run it now against your production env:

# From your local machine, with .env temporarily holding the production token, run:
node src/deploy-commands.js

14. Switch X OAuth to Production URL

X allows multiple callback URIs per app. Add the production one alongside the local one:

  1. https://developer.x.com/en/portal/dashboard → your app → User authentication settingsEdit.
  2. Under Callback URI / Redirect URL, add:
    https://<your-railway-domain>/auth/x/callback
    
  3. Save.

The X library on the bot side picks whichever URI matches X_REDIRECT_URI in your env — keep both registered if you want both local and prod working.


15. Verify the Production Deployment

curl https://<your-railway-domain>/health
# → ok

In Railway logs you should see exactly the local boot output. From your Discord server:

  • /profile returns without error.
  • /connect x opens the X OAuth flow on your production URL.
  • /leaderboard renders (will be empty if no one has points yet).

If /connect x opens but X returns "redirect_uri mismatch", X_REDIRECT_URI in Railway doesn't match what's registered in the X Developer Portal — fix one to match the other.


16. Initialize the Bot on Your Discord Server

Run these in order in the server where you'll actually use the bot:

Command Purpose
/initiate Creates the marketplace, tweets, raffles, intro, and logs channels plus the Tribe Channels role.
/engage points repost:<n> comment:<n> early_bonus:<n> Sets point payouts per action.
/announce enabled:true role:@Tribe (optional) Tags a role when a new tweet dashboard is posted.
/authorize add role:@Mods (optional) Grants non-admins access to manager commands.
/marketplace show Renders the marketplace UI in the marketplace channel.
/marketplace add name:"Custom Role" price:1000 role:@VIP Adds your first item.

You're live.


17. Environment Variable Reference

Variable Required? Default What it does
DISCORD_TOKEN Yes Bot login token. From Discord Developer Portal → Bot. Never commit.
DISCORD_CLIENT_ID Yes Discord application ID. Used by deploy-commands.js to register slash commands.
FIREBASE_PROJECT_ID Yes Firebase project ID (e.g. tribe-connect-abc12).
GOOGLE_APPLICATION_CREDENTIALS Yes Path to the service account key JSON file. Local: ./serviceAccountKey.json. Railway: /app/firebase-credentials.json.
GOOGLE_APPLICATION_CREDENTIALS_JSON Railway only Full JSON contents of the service account. start.sh writes this to the path above at boot. Unused locally.
X_CLIENT_ID Yes OAuth 2.0 client ID from the X Developer Portal.
X_CLIENT_SECRET Yes OAuth 2.0 client secret. Never commit.
X_REDIRECT_URI Yes OAuth callback. Must match the X Developer Portal verbatim.
X_SCOPES No tweet.read users.read like.read offline.access OAuth scope list. Don't change unless you intentionally need more/less access.
X_BEARER_TOKEN No App-only Bearer for occasional public endpoints. Most flows go through RapidAPI; safe to leave blank.
RAPIDAPI_KEY Yes Twitter241 RapidAPI key. The bot throws on boot if missing.
RAPIDAPI_HOST No twitter241.p.rapidapi.com RapidAPI host header.
RAPIDAPI_BASE_URL No https://twitter241.p.rapidapi.com Base URL for RapidAPI requests.
RAPIDAPI_TIMEOUT_MS No 15000 Per-request timeout in ms.
RAPIDAPI_MAX_PAGES No 3 How many pages to walk when fetching retweeters/commenters.
BOT_PUBLIC_URL Yes Base URL the bot tells users to visit for OAuth. Must be reachable from the user's browser.
PORT No 3000 Port the express auth server binds to. Railway sets this automatically; match it to BOT_PUBLIC_URL locally.

src/config.js will throw on startup if any Yes variable is missing.


18. Files You'll Touch

A new developer typically modifies only these files during setup. Everything else can stay untouched.

File When you change it What to do
.env Always Copy from .env.example, paste real secrets. Gitignored.
serviceAccountKey.json Always Drop the Firebase service account file here. Gitignored.
.env.example If you add a new env var Document it so the next developer knows it exists.
src/commands.js When adding a slash command Register the new SlashCommandBuilder. Re-run node src/deploy-commands.js after.
src/index.js When adding a slash command Wire the new command name to its handler in the InteractionCreate block.
src/handlers/<name>.js When adding a slash command Create the handler.
package.json If adding npm deps npm install <pkg> updates this.
railway.json Rarely Only if you need a custom build/start command.
start.sh Rarely Only if the Railway boot sequence changes.

You should never need to edit anything under src/firebase/, src/auth/, src/rapid/, or src/discord/ for a routine setup — those are infrastructure.


19. Troubleshooting

Boot errors

Missing env var: X — Your .env doesn't have variable X (or, on Railway, the Variables tab doesn't). Check Section 17.

Missing RAPIDAPI_KEY in .envsrc/rapid/rapidClient.js throws this on import if RAPIDAPI_KEY isn't set. Same fix.

Error: Could not load the default credentialsfirebase-admin can't find the service account. Verify GOOGLE_APPLICATION_CREDENTIALS points to an existing file with valid JSON. On Railway, double-check that GOOGLE_APPLICATION_CREDENTIALS_JSON was pasted in full (curly braces included) and that start.sh ran (look for ✅ Firebase credentials written to file in the logs).

X OAuth fails

"Something went wrong" on X's pageX_REDIRECT_URI doesn't match what's registered in the Developer Portal. They must be byte-identical: scheme, host, port, path, no trailing slash differences.

Bot says "Connect your X account first" after a successful OAuth — Firestore writes are failing silently. Check Firestore Console → Data → users collection; if it's empty after a connect attempt, the service account doesn't have permission. Re-download the service account key.

Slash commands missing

Commands don't appear in Discord — You need to run node src/deploy-commands.js. Wait 1–2 minutes after running. If still missing after 10 minutes, kick the bot and re-invite it.

Only some commands appear — You added a command to src/commands.js but didn't re-deploy. Re-run the deploy script.

Verification (/verify button) fails

"X API is temporarily busy" — RapidAPI rate-limited the bot. The client already retries with backoff; if it persists, you've exceeded your RapidAPI plan's per-minute quota. Either upgrade the plan or reduce RAPIDAPI_MAX_PAGES.

Verify returns repost: ❌ even though you reposted — RapidAPI caches data and may lag 1-2 minutes behind X. Ask the user to wait and try again.

Permission errors in Discord

The bot prints a detailed permission diagnostic when it hits Missing Permissions (50013). Read the output — it tells you exactly which permission is missing and whether the bot's role is positioned correctly in the role hierarchy. Most fixes are:

  • Move the bot's integration role above the Tribe Channels role in Server Settings → Roles.
  • Re-run /initiate so channel overrides are reapplied.

Firestore "requires an index"

You missed Step 5.3. Click the link in the error message — it opens the Firebase Console pre-configured with the exact index you need.


Appendix: Local Development Tips

  • Hot reload: This project doesn't include a watcher. Use nodemon: npm install -D nodemon then run npx nodemon src/index.js.
  • Inspect Firestore: Use the Firebase Console's Data tab — collections are users/, guilds/, tweets/, oauth_states/.
  • Resetting your dev data: Delete documents directly in the Firebase Console.
  • Multiple Discord apps: If you want a separate dev bot, repeat Section 4 for a "Tribe Connect Dev" app and keep two .env files (.env and .env.prod).

You're done. Once npm start boots clean locally and Railway shows green, point a community at the bot and let /connect x do the rest.

About

Tribe Connect Bot Manager

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors