Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions .github/workflows/node.js.yml
Original file line number Diff line number Diff line change
Expand Up @@ -84,8 +84,8 @@ jobs:
# I don't remember why that was valuable but I'm afraid to remove it
run: |
kubectl diff -k . || echo \n
kubectl delete secret reactibot-env || echo \n
kubectl create secret generic reactibot-env \
kubectl delete secret nodeibot-env || echo \n
kubectl create secret generic nodeibot-env \
--from-literal=DISCORD_HASH=${{ secrets.DISCORD_HASH }} \
--from-literal=DISCORD_PUBLIC_KEY=${{ secrets.DISCORD_PUBLIC_KEY }} \
--from-literal=DISCORD_APP_ID=${{ secrets.DISCORD_APP_ID }} \
Expand Down
2 changes: 1 addition & 1 deletion CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@
1. `npm run dev`
1. Look for the following message in the logs, and open the URL in a browser where you're logged into Discord.
- `Bot started. If necessary, add it to your test server:`
- Make sure to not install this bot directly on Reactiflux but on the Reactiflux Test Server. Ask for the correct role in RF's #reactibot channel
- Make sure to to install this to the Reactiflux Test Server. Ask for access in the #talk-to-staff channel

# Implementation notes

Expand Down
174 changes: 174 additions & 0 deletions DISCORD_SERVER_MIGRATION_GUIDE.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,174 @@
# Discord Server Migration Guide

This document identifies all hardcoded Discord server-specific values that need to be updated when deploying this bot to a different Discord server.

## Environment Variables

**File: `src/helpers/env.ts`**

- Set `GUILD_ID` environment variable to your target Discord server ID

## Channel IDs

**File: `src/constants/channels.ts`**

### Production Channels (Lines 25-44)

All channel IDs in the `PRODUCTION_CHANNELS` object need to be replaced:

- `helpReact: "103696749012467712"`
- `helpThreadsReact: "902647189120118794"`
- `helpJs: "565213527673929729"`
- `random: "103325358643752960"`
- `gaming: "509219336175747082"`
- `thanks: "798567961468076072"`
- `jobBoard: "103882387330457600"`
- `resumeReview: "955507127877791795"`
- `lookingForGroup: "1255898446158757939"`
- `jobsLog: "989201828572954694"`
- `events: "127442949435817984"`
- `iBuiltThis: "312761588778139658"`
- `iWroteThis: "918616846100492298"`
- `twitterFeed: "951207372125274112"`
- `techReadsAndNews: "105816607976095744"`
- `modLog: "591326408396111907"`
- `botLog: "701462381703856158"`
- `vcLog: "1237161125473161347"`

### Local Development Channels (Lines 4-23)

All channel IDs in the `LOCAL_CHANNELS` object need to be replaced with your test server channels:

- `helpReact: "926931785219207301"`
- `helpThreadsReact: "950790460857794620"`
- `helpJs: "950790460857794620"`
- `random: "926931785219207301"`
- `gaming: "926931785219207301"`
- `thanks: "926931785219207301"`
- `jobBoard: "925847361996095509"`
- `resumeReview: "1166075559172907008"`
- `lookingForGroup: "1166085100493078590"`
- `jobsLog: "925847644318879754"`
- `events: "950790520811184150"`
- `iBuiltThis: "950790520811184150"`
- `iWroteThis: "950790520811184150"`
- `twitterFeed: "950790520811184150"`
- `techReadsAndNews: "950790520811184150"`
- `modLog: "925847644318879754"`
- `botLog: "916081991542276096"`
- `vcLog: "1237103703740121201"`

## Role IDs

**File: `src/constants/channels.ts`**

### Production Roles (Lines 54-59)

All role IDs in the `PRODUCTION_ROLES` object need to be replaced:

- `starHelper: "852537681346691102"`
- `mvp: "340332804611244043"`
- `moderator: "102870499406647296"`
- `admin: "103261043291082752"`

### Local Development Roles (Lines 48-53)

All role IDs in the `LOCAL_ROLES` object need to be replaced:

- `starHelper: "932749426785665136"`
- `mvp: "932749517290344488"`
- `moderator: "916797467918471190"`
- `admin: "916797467918471190"`

**File: `src/constants.ts`**

- Line 1: `modRoleId = "&102870499406647296"` - Replace with your server's moderator role ID

## Hardcoded Channel Mentions in Messages

**File: `src/features/scheduled-messages.ts`**

### Lines 101-112 - Help Channel References

Replace all hardcoded channel mentions with your server's channel IDs:

```
<#565213527673929729> For questions about pure Javascript problems.
<#105765765117935616> For questions about CSS or other visual problems.
<#145170347921113088> For questions about issues with your server code.
<#105765859191975936> Get deeper review of a snippet of code.
<#287623405946011648> If you have a question about your job or career, ask it in here.
<#547620660482932737> Discussion of non-JS code, or that new laptop you're deciding on.
<#108428584783220736> for questions about building, linting, generating, or otherwise processing your code.
<#103882387330457600> Job board channel
<#798567961468076072> Thanks/shoutout channel
```

## Server-Specific URLs and Branding

Replace all Reactiflux-specific URLs and references throughout the codebase:

### URLs to Replace

- `https://www.reactiflux.com/conduct` → Your server's code of conduct
- `https://www.reactiflux.com/promotion` → Your server's promotion guidelines
- `https://www.reactiflux.com/jobs` → Your server's jobs page
- `https://www.reactiflux.com/learning` → Your server's learning resources
- `https://reactiflux.com/contact` → Your server's contact form
- `hello@reactiflux.com` → Your server's contact email

### Files Containing These References

- `src/features/commands.ts` (multiple instances)
- `src/features/scheduled-messages.ts` (multiple instances)
- `src/features/jobs-moderation.ts` (guidance URL)

## Channel Purpose Mapping

When creating channels in your new server, ensure they serve the same purposes:

| Channel Constant | Purpose |
| ------------------ | ------------------------------ |
| `helpReact` | React-specific help questions |
| `helpThreadsReact` | React help with thread support |
| `helpJs` | Pure JavaScript questions |
| `random` | General discussion |
| `gaming` | Gaming discussions |
| `thanks` | Appreciation messages |
| `jobBoard` | Job postings |
| `resumeReview` | Resume feedback |
| `lookingForGroup` | Finding project partners |
| `jobsLog` | Job posting moderation logs |
| `events` | Server events |
| `iBuiltThis` | Project showcases |
| `iWroteThis` | Article/blog sharing |
| `twitterFeed` | Twitter feed integration |
| `techReadsAndNews` | Tech news sharing |
| `modLog` | Moderation activity logs |
| `botLog` | Bot activity logs |
| `vcLog` | Voice channel activity logs |

## Required Permissions

Ensure the bot has the following permissions in your Discord server:

- Read Messages/View Channels
- Send Messages
- Manage Messages
- Add Reactions
- Use Slash Commands
- Connect (for voice channels)
- View Audit Log (for moderation features)

## Testing Checklist

After updating all values:

1. ✅ Bot connects to your server
2. ✅ All channel references work
3. ✅ Role-based permissions function correctly
4. ✅ Scheduled messages post to correct channels
5. ✅ Moderation features work with your role structure
6. ✅ All URL references point to your resources
7. ✅ Job board moderation functions properly
8. ✅ Voice activity logging works (if using voice channels)
10 changes: 5 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# Reactibot

Useful saved commands, auto-moderation tools, and more, for the Reactiflux server.
Useful saved commands, auto-moderation tools, and more, for the Node.js Discord server.

## Contributing

Expand All @@ -14,10 +14,10 @@ This is dumb and I hate it but it's how the tools work together.

New secrets need to be added in a bunch of different places in order to work in production:

- the GitHub [secrets config for Reactibot in settings](https://github.com/reactiflux/reactibot/settings/secrets/actions)
- [env.ts](https://github.com/reactiflux/reactibot/blob/main/src/helpers/env.ts) to load it from the environment (please do not freely use `process.env`)
- [our deployment action](https://github.com/reactiflux/reactibot/blob/main/.github/workflows/node.js.yml#L88), under the Kubernetes secret creation step
- [the Kubernetes deployment config](https://github.com/reactiflux/reactibot/blob/main/cluster/deployment.yaml#L18)
- the GitHub [secrets config for Nodeibot in settings](https://github.com/nodeiflux/nodeibot/settings/secrets/actions)
- [env.ts](https://github.com/nodeiflux/nodeibot/blob/main/src/helpers/env.ts) to load it from the environment (please do not freely use `process.env`)
- [our deployment action](https://github.com/nodeiflux/nodeibot/blob/main/.github/workflows/node.js.yml#L88), under the Kubernetes secret creation step
- [the Kubernetes deployment config](https://github.com/nodeiflux/nodeibot/blob/main/cluster/deployment.yaml#L18)

## Testing deployment

Expand Down
24 changes: 12 additions & 12 deletions cluster/deployment.yaml
Original file line number Diff line number Diff line change
@@ -1,60 +1,60 @@
apiVersion: apps/v1
kind: Deployment
metadata:
name: reactibot-deployment
name: nodeibot-deployment
spec:
selector:
matchLabels:
app: reactibot
app: nodeibot
replicas: 1
template:
metadata:
labels:
app: reactibot
app: nodeibot
spec:
containers:
- name: reactibot
- name: nodeibot
image: $(IMAGE)
env:
- name: ENVIRONMENT
value: production
- name: DISCORD_HASH
valueFrom:
secretKeyRef:
name: reactibot-env
name: nodeibot-env
key: DISCORD_HASH
- name: GH_READ_TOKEN
valueFrom:
secretKeyRef:
name: reactibot-env
name: nodeibot-env
key: GH_READ_TOKEN
- name: AMPLITUDE_KEY
valueFrom:
secretKeyRef:
name: reactibot-env
name: nodeibot-env
key: AMPLITUDE_KEY
- name: DISCORD_PUBLIC_KEY
valueFrom:
secretKeyRef:
name: reactibot-env
name: nodeibot-env
key: DISCORD_PUBLIC_KEY
- name: DISCORD_APP_ID
valueFrom:
secretKeyRef:
name: reactibot-env
name: nodeibot-env
key: DISCORD_APP_ID
- name: GUILD_ID
valueFrom:
secretKeyRef:
name: reactibot-env
name: nodeibot-env
key: GUILD_ID
- name: OPENAI_KEY
valueFrom:
secretKeyRef:
name: reactibot-env
name: nodeibot-env
key: OPENAI_KEY
- name: REACTIBOT_API_KEY
valueFrom:
secretKeyRef:
name: reactibot-env
name: nodeibot-env
key: REACTIBOT_API_KEY
10 changes: 5 additions & 5 deletions cluster/ingress.yaml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: reactibot-ingress
name: nodeibot-ingress
annotations:
nginx.ingress.kubernetes.io/ssl-redirect: "true"
nginx.ingress.kubernetes.io/force-ssl-redirect: "true"
Expand All @@ -12,17 +12,17 @@ metadata:
spec:
ingressClassName: nginx
rules:
- host: api.reactiflux.com
- host: api.node.reactiflux.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: reactibot-service
name: nodeibot-service
port:
number: 80
tls:
- hosts:
- api.reactiflux.com
secretName: reactibot-tls-cert
- api.node.reactiflux.com
secretName: nodeibot-tls-cert
6 changes: 3 additions & 3 deletions cluster/service.yaml
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
apiVersion: v1
kind: Service
metadata:
name: reactibot-service
name: nodeibot-service
labels:
app: reactibot
app: nodeibot
spec:
type: ClusterIP
ports:
- port: 80 # External port
targetPort: 3000 # Port the pod exposes
selector:
app: reactibot
app: nodeibot
2 changes: 1 addition & 1 deletion kustomization.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
namespace: default
commonLabels:
app: reactibot
app: nodeibot
resources:
- cluster/service.yaml
- cluster/deployment.yaml
Expand Down
6 changes: 3 additions & 3 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "reactibot",
"name": "nodeibot",
"version": "1.0.0",
"description": "Source code of Reactibot, utilized at Reactiflux server",
"description": "Source code of Nodeibot, used in the Node.js Discord server",
"private": true,
"type": "module",
"scripts": {
Expand All @@ -17,7 +17,7 @@
},
"repository": {
"type": "git",
"url": "https://github.com/reactiflux/reactibot.git"
"url": "https://github.com/nodeiflux/nodeiflux-bot.git"
},
"license": "MIT",
"dependencies": {
Expand Down
4 changes: 2 additions & 2 deletions src/constants/channels.ts
Original file line number Diff line number Diff line change
Expand Up @@ -65,10 +65,10 @@ const cachedChannels: Record<string, Record<string, TextChannel>> = {
};

export const initCachedChannels = async (bot: Client) => {
const reactiflux = await bot.guilds.fetch(guildId);
const nodejsDiscord = await bot.guilds.fetch(guildId);
const channels = await Promise.all(
[CHANNELS.botLog, CHANNELS.modLog, CHANNELS.jobsLog].map((channelId) =>
reactiflux.channels.fetch(channelId),
nodejsDiscord.channels.fetch(channelId),
),
);

Expand Down
Loading