Skip to content

Commit f73da24

Browse files
committed
feat: added set channel and get daily question commands and docker stuff
1 parent 44849d3 commit f73da24

19 files changed

Lines changed: 1520 additions & 33 deletions

.dockerignore

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
# Dependencies
2+
node_modules/
3+
npm-debug.log*
4+
5+
# Git
6+
.git/
7+
.gitignore
8+
9+
# Docker
10+
Dockerfile
11+
docker-compose.yml
12+
.dockerignore
13+
14+
# IDE
15+
.vscode/
16+
.idea/
17+
18+
# OS
19+
.DS_Store
20+
Thumbs.db
21+
22+
# Misc
23+
*.log

.eslintrc.json

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
{
2+
"env": {
3+
"es2022": true,
4+
"node": true
5+
},
6+
"extends": "eslint:recommended",
7+
"parserOptions": {
8+
"ecmaVersion": "latest",
9+
"sourceType": "module"
10+
},
11+
"rules": {
12+
"no-unused-vars": "warn",
13+
"no-console": "off"
14+
}
15+
}

.github/workflows/ci.yml

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
name: CI
2+
3+
on:
4+
push:
5+
branches: [main]
6+
pull_request:
7+
branches: [main]
8+
9+
concurrency:
10+
group: ${{ github.workflow }}-${{ github.ref }}
11+
cancel-in-progress: true
12+
13+
jobs:
14+
lint:
15+
runs-on: ubuntu-latest
16+
steps:
17+
- name: Checkout code
18+
uses: actions/checkout@v4
19+
20+
- name: Setup Node.js
21+
uses: actions/setup-node@v4
22+
with:
23+
node-version: '20'
24+
cache: 'npm'
25+
26+
- name: Install dependencies
27+
run: npm ci
28+
29+
- name: Check formatting (Prettier)
30+
run: npm run format -- --check
31+
32+
- name: Run ESLint
33+
run: npm run lint
34+
35+
test:
36+
runs-on: ubuntu-latest
37+
steps:
38+
- name: Checkout code
39+
uses: actions/checkout@v4
40+
41+
- name: Setup Node.js
42+
uses: actions/setup-node@v4
43+
with:
44+
node-version: '20'
45+
cache: 'npm'
46+
47+
- name: Install dependencies
48+
run: npm ci
49+
50+
- name: Run tests
51+
run: npm test

.prettierrc

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
{
2+
"semi": true,
3+
"singleQuote": true,
4+
"tabWidth": 2,
5+
"trailingComma": "es5"
6+
}

DOCKER.md

Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,85 @@
1+
# DailyNode Discord Bot - Docker Setup
2+
3+
## Quick Start
4+
5+
### Using Docker Compose (Recommended)
6+
7+
1. **Build and start the bot:**
8+
```bash
9+
docker-compose up -d
10+
```
11+
12+
2. **View logs:**
13+
```bash
14+
docker-compose logs -f
15+
```
16+
17+
3. **Stop the bot:**
18+
```bash
19+
docker-compose down
20+
```
21+
22+
4. **Restart the bot:**
23+
```bash
24+
docker-compose restart
25+
```
26+
27+
### Using Docker directly
28+
29+
1. **Build the image:**
30+
```bash
31+
docker build -t dailynode-bot .
32+
```
33+
34+
2. **Run the container:**
35+
```bash
36+
docker run -d \
37+
--name dailynode-bot \
38+
--env-file .env \
39+
-v $(pwd)/config.json:/app/config.json \
40+
--restart unless-stopped \
41+
dailynode-bot
42+
```
43+
44+
## Configuration
45+
46+
Ensure your `.env` file contains:
47+
```env
48+
DISCORD_TOKEN=your_discord_bot_token
49+
clientId=your_client_id
50+
guildId=your_guild_id
51+
```
52+
53+
## Maintenance
54+
55+
**Update the bot:**
56+
```bash
57+
docker-compose down
58+
docker-compose build --no-cache
59+
docker-compose up -d
60+
```
61+
62+
**View real-time logs:**
63+
```bash
64+
docker-compose logs -f dailynode
65+
```
66+
67+
**Execute commands inside container:**
68+
```bash
69+
docker-compose exec dailynode sh
70+
```
71+
72+
## Timezone
73+
74+
The default timezone is set to `America/New_York`. To change it:
75+
1. Edit `docker-compose.yml`
76+
2. Change the `TZ` environment variable
77+
3. Restart: `docker-compose restart`
78+
79+
## Data Persistence
80+
81+
The `config.json` file is mounted as a volume to persist:
82+
- LeetCode channel configuration
83+
- Daily problem data
84+
85+
This ensures your settings survive container restarts.

Dockerfile

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
# Use official Node.js LTS image
2+
FROM node:20-alpine
3+
4+
# Set working directory
5+
WORKDIR /app
6+
7+
# Copy package files
8+
COPY package*.json ./
9+
10+
# Install dependencies
11+
RUN npm ci --only=production
12+
13+
# Copy application files
14+
COPY . .
15+
16+
# Create config.json if it doesn't exist
17+
RUN if [ ! -f config.json ]; then echo '{"leetcodeChannelId":""}' > config.json; fi
18+
19+
# Set environment to production
20+
ENV NODE_ENV=production
21+
22+
# Run the bot
23+
CMD ["node", "index.js"]

commands/utility/ping.js

Lines changed: 0 additions & 8 deletions
This file was deleted.
Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
import { SlashCommandBuilder, PermissionFlagsBits } from 'discord.js';
2+
import fs from 'node:fs';
3+
import path from 'node:path';
4+
import { fileURLToPath } from 'node:url';
5+
6+
const __dirname = path.dirname(fileURLToPath(import.meta.url));
7+
const configPath = path.join(__dirname, '../../config.json');
8+
9+
export const data = new SlashCommandBuilder()
10+
.setName('setleetcodechannel')
11+
.setDescription('Set the channel where the daily LeetCode challenge will be posted')
12+
.addChannelOption(option =>
13+
option
14+
.setName('channel')
15+
.setDescription('The channel to send daily LeetCode challenges to')
16+
.setRequired(true)
17+
)
18+
.setDefaultMemberPermissions(PermissionFlagsBits.Administrator);
19+
20+
export async function execute(interaction) {
21+
const channel = interaction.options.getChannel('channel');
22+
23+
try {
24+
// Load existing config or create new one
25+
let config = {};
26+
if (fs.existsSync(configPath)) {
27+
config = JSON.parse(fs.readFileSync(configPath, 'utf8'));
28+
}
29+
30+
// Update the channel ID
31+
config.leetcodeChannelId = channel.id;
32+
33+
// Write back to config file
34+
fs.writeFileSync(configPath, JSON.stringify(config, null, 2), 'utf8');
35+
36+
await interaction.reply({
37+
content: `✅ LeetCode daily challenge channel set to ${channel}!`,
38+
ephemeral: true
39+
});
40+
41+
console.log(`✅ LeetCode channel updated to ${channel.name} (${channel.id})`);
42+
} catch (error) {
43+
console.error('Error setting LeetCode channel:', error);
44+
await interaction.reply({
45+
content: '❌ Failed to set the channel. Please try again.',
46+
ephemeral: true
47+
});
48+
}
49+
}

commands/utility/todayleetcode.js

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
import { SlashCommandBuilder, EmbedBuilder } from 'discord.js';
2+
import fs from 'node:fs';
3+
import path from 'node:path';
4+
import { fileURLToPath } from 'node:url';
5+
6+
const __dirname = path.dirname(fileURLToPath(import.meta.url));
7+
const configPath = path.join(__dirname, '../../config.json');
8+
9+
export const data = new SlashCommandBuilder()
10+
.setName('todayleetcode')
11+
.setDescription('Get a reminder of today\'s LeetCode challenge');
12+
13+
export async function execute(interaction) {
14+
try {
15+
const config = JSON.parse(fs.readFileSync(configPath, 'utf8'));
16+
const problem = config.dailyProblem;
17+
const problemDate = config.dailyProblemDate;
18+
19+
if (!problem) {
20+
await interaction.reply({
21+
content: '❌ No LeetCode problem has been set for today yet. Try again later!',
22+
ephemeral: true
23+
});
24+
return;
25+
}
26+
27+
// Check if the saved problem is from today
28+
const today = new Date().toISOString().split('T')[0];
29+
if (problemDate !== today) {
30+
await interaction.reply({
31+
content: '⏰ The daily problem will be sent at 12:00 PM. Check back then for a fresh challenge!',
32+
ephemeral: true
33+
});
34+
return;
35+
}
36+
37+
const embed = new EmbedBuilder()
38+
.setColor('#FFA500')
39+
.setTitle('🎯 Today\'s LeetCode Challenge')
40+
.addFields(
41+
{ name: 'Problem', value: `**${problem.title}**`, inline: false },
42+
{ name: 'Difficulty', value: problem.difficulty, inline: true },
43+
{ name: 'Problem ID', value: `#${problem.id}`, inline: true },
44+
{ name: 'Link', value: `[Solve on LeetCode](${problem.link})`, inline: false }
45+
)
46+
.setFooter({ text: 'Good luck! 🍀' })
47+
.setTimestamp();
48+
49+
await interaction.reply({ embeds: [embed] });
50+
} catch (error) {
51+
console.error('Error retrieving today\'s LeetCode challenge:', error);
52+
await interaction.reply({
53+
content: '❌ Failed to retrieve today\'s problem. Please try again.',
54+
ephemeral: true
55+
});
56+
}
57+
}

commands/utility/user.js

Lines changed: 0 additions & 11 deletions
This file was deleted.

0 commit comments

Comments
 (0)