Skip to content

Commit 6eaa552

Browse files
[gw] Add Nicholas support
1 parent f37ffc6 commit 6eaa552

5 files changed

Lines changed: 562 additions & 2 deletions

File tree

package.json

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,11 @@
55
"description": "Bot Discord pour le serveur Diverge",
66
"main": "src/index.js",
77
"dependencies": {
8+
"cheerio": "^1.2.0",
89
"discord.js": "^14.25.1",
910
"dotenv": "^17.2.3",
1011
"mariadb": "^3.4.5",
12+
"node-cron": "^4.2.1",
1113
"sequelize": "^6.37.7"
1214
},
1315
"devDependencies": {

src/commands/nicholas.js

Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
const { SlashCommandBuilder, EmbedBuilder, PermissionFlagsBits } = require('discord.js');
2+
const { getAllNicholasInfo } = require('../helpers/nicholasScraper');
3+
4+
module.exports = {
5+
data: new SlashCommandBuilder()
6+
.setName('nicholas')
7+
.setDescription('[Admin] Affiche les informations actuelles de Nicholas (Guild Wars 1)')
8+
.setDefaultMemberPermissions(PermissionFlagsBits.Administrator),
9+
async execute(interaction) {
10+
// Double check permissions
11+
if (!interaction.member.permissions.has(PermissionFlagsBits.Administrator)) {
12+
return interaction.reply({
13+
content: '❌ Cette commande est réservée aux administrateurs.',
14+
ephemeral: true,
15+
});
16+
}
17+
18+
await interaction.deferReply();
19+
20+
try {
21+
const { traveler, sandford } = await getAllNicholasInfo();
22+
23+
// Build clickable links for Traveler
24+
const travelerLocation = traveler.mapUrl
25+
? `[${traveler.location}](${traveler.mapUrl})`
26+
: traveler.location;
27+
const travelerItem = traveler.itemUrl
28+
? `[${traveler.item}](${traveler.itemUrl})`
29+
: traveler.item;
30+
31+
// Embed pour Nicholas le Voyageur
32+
const travelerEmbed = new EmbedBuilder()
33+
.setTitle('🧳 Nicholas le Voyageur')
34+
.setColor(0x00AE86)
35+
.addFields(
36+
{ name: '📍 Localisation', value: travelerLocation, inline: true },
37+
{ name: '📦 Objet demandé', value: travelerItem, inline: true },
38+
{ name: '🔢 Quantité', value: `${traveler.quantity} par cadeau`, inline: true },
39+
)
40+
.setFooter({ text: 'Mise à jour hebdomadaire - Tous les lundis à 15:00 UTC' })
41+
.setTimestamp();
42+
43+
44+
// Build clickable link for Sandford item
45+
const sandfordItem = sandford.itemUrl
46+
? `[${sandford.item}](${sandford.itemUrl})`
47+
: sandford.item;
48+
49+
// Embed pour Nicholas Sandford
50+
const sandfordEmbed = new EmbedBuilder()
51+
.setTitle('🏹 Nicholas Sandford')
52+
.setColor(0xFF6B35)
53+
.addFields(
54+
{ name: '📦 Objet demandé', value: sandfordItem, inline: true },
55+
{ name: '🔢 Quantité', value: `${sandford.quantity} objets`, inline: true },
56+
)
57+
.setFooter({ text: 'Mise à jour quotidienne - Tous les jours à 07:00 UTC' })
58+
.setTimestamp();
59+
60+
61+
await interaction.editReply({
62+
embeds: [travelerEmbed, sandfordEmbed],
63+
});
64+
} catch (error) {
65+
console.error('Error in /nicholas command:', error);
66+
await interaction.editReply({
67+
content: '❌ Erreur lors de la récupération des informations de Nicholas. Vérifiez les logs.',
68+
});
69+
}
70+
},
71+
};

src/events/ready.js

Lines changed: 115 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
1-
const { Events, ActivityType } = require('discord.js');
1+
const { Events, ActivityType, EmbedBuilder } = require('discord.js');
2+
const cron = require('node-cron');
3+
const { getNicholasTraveler, getNicholasSandford } = require('../helpers/nicholasScraper');
24

35
const STATUSES = [
46
'Pourquoi ? Pour feur.',
@@ -20,6 +22,115 @@ function rotateStatus(client) {
2022
client.user.setActivity(status, { type: ActivityType.Custom });
2123
}
2224

25+
/**
26+
* Posts Nicholas the Traveler update
27+
*/
28+
async function postNicholasTraveler(client) {
29+
try {
30+
const channelId = process.env.NICHOLAS_CHANNEL_ID;
31+
if (!channelId) {
32+
console.log('NICHOLAS_CHANNEL_ID not configured, skipping Nicholas the Traveler post');
33+
return;
34+
}
35+
36+
const channel = await client.channels.fetch(channelId);
37+
if (!channel) {
38+
console.error('Nicholas channel not found');
39+
return;
40+
}
41+
42+
const data = await getNicholasTraveler();
43+
44+
// Build clickable links
45+
const locationValue = data.mapUrl
46+
? `[${data.location}](${data.mapUrl})`
47+
: data.location;
48+
const itemValue = data.itemUrl
49+
? `[${data.item}](${data.itemUrl})`
50+
: data.item;
51+
52+
const embed = new EmbedBuilder()
53+
.setTitle('🧳 Nicholas le Voyageur')
54+
.setColor(0x00AE86)
55+
.addFields(
56+
{ name: '📍 Localisation', value: locationValue, inline: true },
57+
{ name: '📦 Objet demandé', value: itemValue, inline: true },
58+
{ name: '🔢 Quantité', value: `${data.quantity} par cadeau`, inline: true },
59+
)
60+
.setFooter({ text: 'Mise à jour hebdomadaire - Tous les lundis à 15:00 UTC' })
61+
.setTimestamp();
62+
63+
await channel.send({ embeds: [embed] });
64+
console.log('Posted Nicholas the Traveler update');
65+
} catch (error) {
66+
console.error('Error posting Nicholas the Traveler update:', error);
67+
}
68+
}
69+
70+
/**
71+
* Posts Nicholas Sandford update
72+
*/
73+
async function postNicholasSandford(client) {
74+
try {
75+
const channelId = process.env.NICHOLAS_CHANNEL_ID;
76+
if (!channelId) {
77+
console.log('NICHOLAS_CHANNEL_ID not configured, skipping Nicholas Sandford post');
78+
return;
79+
}
80+
81+
const channel = await client.channels.fetch(channelId);
82+
if (!channel) {
83+
console.error('Nicholas channel not found');
84+
return;
85+
}
86+
87+
const data = await getNicholasSandford();
88+
89+
// Build clickable link for item
90+
const itemValue = data.itemUrl
91+
? `[${data.item}](${data.itemUrl})`
92+
: data.item;
93+
94+
const embed = new EmbedBuilder()
95+
.setTitle('🏹 Nicholas Sandford')
96+
.setColor(0xFF6B35)
97+
.addFields(
98+
{ name: '📦 Objet demandé', value: itemValue, inline: true },
99+
{ name: '🔢 Quantité', value: `${data.quantity} objets`, inline: true },
100+
)
101+
.setFooter({ text: 'Mise à jour quotidienne - Tous les jours à 07:00 UTC' })
102+
.setTimestamp();
103+
104+
await channel.send({ embeds: [embed] });
105+
console.log('Posted Nicholas Sandford update');
106+
} catch (error) {
107+
console.error('Error posting Nicholas Sandford update:', error);
108+
}
109+
}
110+
111+
/**
112+
* Setup cron jobs for Nicholas posts
113+
*/
114+
function setupNicholasCronJobs(client) {
115+
// Nicholas the Traveler: Every Monday at 15:05 UTC
116+
cron.schedule('5 15 * * 1', () => {
117+
console.log('Running Nicholas the Traveler cron job');
118+
postNicholasTraveler(client);
119+
}, {
120+
timezone: 'UTC',
121+
});
122+
123+
// Nicholas Sandford: Every day at 07:05 UTC
124+
cron.schedule('5 7 * * *', () => {
125+
console.log('Running Nicholas Sandford cron job');
126+
postNicholasSandford(client);
127+
}, {
128+
timezone: 'UTC',
129+
});
130+
131+
console.log('Nicholas cron jobs scheduled');
132+
}
133+
23134
module.exports = {
24135
name: Events.ClientReady,
25136
once: true,
@@ -28,5 +139,8 @@ module.exports = {
28139

29140
rotateStatus(client);
30141
setInterval(() => rotateStatus(client), 5 * 60 * 1000); // toutes les 5 min
142+
143+
// Setup Nicholas auto-posting
144+
setupNicholasCronJobs(client);
31145
},
32146
};

0 commit comments

Comments
 (0)