- دونستن مفاهیم پایه جاوا اسکریپت
- Node.js v16+
- Discord.js
- dotenv
- mongoose
- Visual Studio Code (من از VSCODE استفاده میکنم شما هرچی راحت تر هستید استفاده کنید)
- و فراموش نکنید که حتما باید یک اپلیکیشن و ربات در دولوپر پورتال دیسکورد بسازید
- https://discord.com/developers/applications
- تیک اپلیکیشن کامند رو هم حتما موقع اینوایت بات به سروتون رو از توی دولوپر پورتال حتما بزنید چون نیازش دارید
این ریپو برای این ساخته شده که به شما کمک بکنه که بتونید از صفر بدون نگرانی و استرس کار های باحالی رو انجام بدید که شاید به نظرتون در نگاه اول سخت بیاد پس صاف بشینید و خوب مثال هارو ببینید یاد بگیرید و ازشون کلی ایده های خفن بگیرید و ببرید توی ادیتور هاتون که بتونید چیزای قشنگ خلق بکنید🎇
❕چطور رباتی که ساختیم رو به سرور خودمون اضافه بکنیم
🚀یه پروژه همیشه کوچیک نمیمونه!
خیلی ساده میتونید برید به لینک زیر توی دیسکوردتون لوگین کنید و بعدش یه اپیلیکشن جدید به وجود بیارید بعدش میرید قسمت بات اون اپلیکیشن و یه بات میسازید
https://discord.com/developers/applications
create-bot.mp4
کافیه برید به دولوپر پورتال و توی اپلیکشنی که از قبل ساختید و قسمت OAuth2 و یه لینک بسازید که هم ربات به همراه دسترسی کامل رو به سرور شما دعوت میکنه هم دسترسی اسلش کامند رو برای استفاده اسلش کامند در سرور رو داشته باشه
invite-bot.mp4
- و یک نکته هم اینجا هست اینه که اگه میخاید کسی بجز شما نتونه ربات شما رو به سرورش دعوت بکنه باید برید توی ستینگ اپلیکیشن قسمت بات و اونجا گزینه
Public Bot
رو غیرفعال بکنید
- اول از نصب
node.js
شروع میکنیم- کافیه برید توی لینک زیر و یک ورژن که بالای
16
هستش رو بر اساس پلتفرم خودتون دانلود کنید و نصب کنید - https://nodejs.org/en/download/releases/
- (تا اونجایی که من اطلاع دارم node.js از ورژن 13 به بعد دیگه روی ویندوز 7 نصب نمیشه!)❗
- کافیه برید توی لینک زیر و یک ورژن که بالای
-
**بعد از node.js میریم سراغ ادیتور که من خودم از
vscode
استفاده میکنم حالا شما میتونید ادیتور های دیگه هم استفاده بکنید مثلsublimeTEXT
و یاnotepad++
-
بعد از نصب ادیتور میرسیم به نصب پکیج های
npm
که خیلی اصلی و مهم هستن- برای نصب پکیج یک فولدر برای پروژه میسازیم که اونجا پکیج هارو نصب بکنیم و فایل هارو بزاریم
- بعد از ساخت فولدر کافیه یه ترمینال از اون پوشه باز بکنیم که شروع کنیم به نصب کامند ها که خب این توی
vscode
خیلی راحته npm install discord.js @discordjs/rest discord-api-types @discordjs/builders
- در واقع ما با استفاده از دستور بالا 4 عدد پکیج اصلی که بهشون نیاز داریم رو نصب میکنیم
npm-i-vscode.mp4
- اگر هم ادیتوری که استفاده میکنید ترمینال نداره میتونید خیلی راحت از توی خوده پوشه یدونه باز بکنید و پکیج ها رو نصب بکنید
npm-i-win.mp4
- ❕ یادت باشه
- ما الان میخایم از یه پکیج به نام
discord.js
استفاده بکنیم که لینکش توی لیست پیش نیاز های بالا هست - توجه داشته باشید که حتما
node.js
رو نصب کرده باشید و ورژن اون بالای 16 باشه - در این اموزش زیاد با واژه ای
guild
رو به روی میشید که در واقع همون معنای سرور رو میدهserver
- ما الان میخایم از یه پکیج به نام
🔵استاندارد ترین روش برای ساخت یک کامند در دیسکورد جی اس با اسلش کامند هستش که اول باید یه کامند رو برای بات ریجستر بکنیم
2 نوع اسلش کامند وجود داره
-
guild command / کامند برای یک سرور
-
global command / کامند برای بات که به صورت کلی هست
ما با نوع اول شروع میکنیم که هم سریع تره هم برای توسعه بهتره
برای ساخت کافیه یک فایل بسازید به نام register-command.js
بعد از اون کافیه که کد مثال زیر رو توی اون وارد بکنید
const { REST } = require('@discordjs/rest');
const { Routes } = require('discord-api-types/v9');
let token = 'TOKEN';
let guild_ID = 'SERVER_ID';
let client_ID = 'BOT_ID';
const commands = [{
name: 'ping',
description: 'in cmd mamolan dar javab mige [pong!] :)'
}];
const rest = new REST({ version: '9' }).setToken(token);
(async () => {
try {
console.log('dar hal ezafe kardn (/)command be server');
await rest.put(
Routes.applicationGuildCommands(client_ID, guild_ID),
{ body: commands },
);
console.log('(/) command shoma be server mored nazar ezafe shod');
} catch (error) {
console.error(error);
}
})();
خب هدف ما الان اینه که جای چنتا چیزو با چیزایی که میخایم عوض بکنیم
let token = 'TOKEN';
let guild_ID = 'SERVER_ID';
let client_ID = 'BOT_ID';
توی کد بالا 3 تا متغیر وجود داره
1-token
2-server_ID
3-client_ID
-
token:
-
server id:
-
client id:
بعد از این که متغیر هارو درست عوض بکنید دارید به یه همچین چیزی توی اون قسمت نگاه میکنید
let token = 'ODy3Msdak4MjNzEyNjDU0.nmhg.xcE4Nj77nbEY5Rk4YU_6YwR_Tio';
let guild_ID = '763773594547126272';
let client_ID = '837098281712615454';
بعدش که جای متغیر هارو عوض کردید فقط کافیه که فایل رو ذخیره بکنید و بعدش با node.js
اونو ران بکنید
node register-command.js
- 🔴 یه نکته هم اینجا وجود داره و لازمه که بگم اینه که این فایل نقش بات رو نداره و فقط یبار بر اون اساسی که میخاید کانفیگ میکنید و ران میکنید و کامند رو اضافه میکنه همین!
خب همون جوری که دیدید ما اسلش کامندمون رو به راحتی درست کردیم
و وقتی الان بریم توی سرور موردنظر و تایپ بکنیم ping/
میبینیم که برای بات یک دستور پینگ با توضیحاتی که نوشته بودیم ساخته شده
برای اضافه کردن اسلش کامند برای همه ای سرور های بات هم فقط کافیه که یک قسمت از کد اولیه بالا رو عوض بکنید که 2 تا نکته وجود داره❕
- اضافه شدن هر دستور به صورت گلوبال در ربات چیزی حدود 1 ساعت زمان میبره از طرف API دیسکورد
- ما این نوع اضافه کردن رو برای کار های تستی پیشنهاد نمیکنیم و بهتره اول دستورات خودتون رو توی یه سرور تست اضافه و تست کنید و بعدش اونا رو به صورت گلوبال منتشر کنید
await rest.put(
Routes.applicationCommands(CLIENT_ID),
{ body: commands },
);
خب بعد از اینکه ما دستور رو به سرور اضافه کردیم فقط کافیه که اونو فعال بکنیم اسونه نه؟
با ساخت یه فایل به نام bot.js
شروع میکنیم
و بعدش میایم کد مثال زیر رو توی اون قرار میدیم
const { Client, Intents } = require('discord.js');
const client = new Client({ intents: [Intents.FLAGS.GUILDS] });
let token = 'TOKEN';
client.on('ready', () => {
console.log(`Logged in as ${client.user.tag}!`);
});
client.on('interactionCreate', async interaction => {
if (!interaction.isCommand()) return;
if (interaction.commandName === 'ping') {
await interaction.reply('Pong!');
}
});
client.login(token);
الان توی کد بالا تنها چیزی که نیازه که عوض بشه متغیر توکن هستش که خب مثل کد اول فقط نیازه از دولوپر پورتال کپی و پیست کنیدش
بعد از گذاشتن توکن فقط کافیه که فایل رو ذخیره و ران بکنید
node bot.js
اگه با همچین پیامی رو به رو شدید یعنی ربات شما اماده به کار هستش
و الان دیگه فقط کافیه برید توی سروری که کامند رو توش ثبت کردید و تایپ بکنید ping/
و اینتر رو فشار بدید
- 🎉 هورا! همون طوری که میبینید بات در جواب دستور شما گفت
!Pong
- ⚪ بعضی مواقع هم شاید دوست نداشته باشید چت با پیام بات شلوغ بشه و اون پیام رو فقط استفاده کننده ببینه و موقع باشه
await interaction.reply({ content: 'Pong!', ephemeral: true });
- فقط کافیه خط ارسال مسیج رو با اون این خط عوض بکنید و یه ephemeral بهش اضافه بکنید و اونو true تعریف بکنید
ما توی اموزش بالا به شما پایه ترین راه برای درست کردن یه دستور و راه اندازی اون رو اموزش دادیم ولی یه سری چیز ها رو باید برای نظم عوض بکنید
دیدید که برای استفاده از توکن سرور ایدی یا ایدی بات اونا رو توی خود کد تعریف میکردیم
ولی این کار در یه پروژه ای استاندارد توصیه نمیشه و بهتره شما یه کانفیگ فایل داشته باشید که اطلاعات مهمی که نیاز دارید توی اون تعریف بشه و بعد بتونید به راحتی اونارو تو کد خودتون استفاده بکنید
برای استفاد از یه کانفیگ ها توی یه کد روش های زیادی هست ولی ما میخایم اینجا از پکیج dotenv
استفاده بکنیم که بعدا همه جوره به کارمون میاد
- با نصبش شروع میکنیم که عین بقیه پکیج هاست و فرقی نداره
npm i dotenv
بعد از نصب میریم سراغ ساخت یه فایل جدید توی فولدر بات به نام env.
و دیتا هارو به صورت خیلی ساده توی فایل تعریف میکنیم من الان فقط 3 تا پارامتر نیاز دارم
TOKEN=ODJ3MDk4jgxNzWjE1BDU0.YI.xksnks77ebvqEY1Rk4YU_2YwE_Tyo
CLIENT_ID=837097281712415454
GUILD_ID=763773694542126274
# 📃 کامند هندلر ⚪ **بعد از اینکه دیتا هارو ذخیره کردیم دیگه فعلا باهاشون کاری نداریم و میریم سراغ ساخت یه فولدر رو ساخت فایل جدا برای کامند**
- یه فولدر بسازید به نام
commands
و یه فایل هم توش بسازید به نامping.js
و کد زیر رو توش قرار بدید و سیو کنید
const { SlashCommandBuilder } = require('@discordjs/builders');
module.exports = {
data: new SlashCommandBuilder()
.setName('ping')
.setDescription('ek command ping az command handler ke toy [/] command ha ham register mishe :D'),
async execute(interaction) {
await interaction.reply('man ba command handler kar mikonm va az folder ``commands`` va file ``ping.js`` miam va be shoma migam [Pong!] :)');
},
};
-
❗ یادتون باشه که این پکیج رو حتما نصب کرده باشید
npm i @discordjs/builders
-
❓ حالا با این عوض کردن کد ما چیکار کردیم؟
- ما با این کار دیگه نیاز نیست دونه دونه اسلش کامند هارو به سرور اضافه بکنیم و هر دستوری رو که به صورت کد بالا براش یه فایل بسازیم و توی پوشه ای کامندز بزاریم رو میتونید مستقیم به اسلش کامند ها اضافه بکنیم
-
قبلش نیازه یکمی توی کد
register-command.js
دست ببریم و عوض کنیمش
const { REST } = require('@discordjs/rest');
const { Routes } = require('discord-api-types/v9');
const fs = require('fs');
// ezafe kardn [dotenv] be file
require("dotenv").config();
// daryaft data ha az file [.env]
let clientID = process.env.CLIENT_ID
let token = process.env.TOKEN
let guildID = process.env.GUILD_ID
// def kardn e command ha az folder [commands]
const commands = [];
const commandFiles = fs.readdirSync('./commands').filter(file => file.endsWith('.js'));
for (const file of commandFiles) {
const command = require(`./commands/${file}`);
commands.push(command.data.toJSON());
}
const rest = new REST({ version: '9' }).setToken(token);
(async () => {
try {
console.log('Started refreshing application (/) commands.');
await rest.put(
Routes.applicationGuildCommands(clientID, guildID),
{ body: commands },
);
console.log('Successfully reloaded application (/) commands.');
} catch (error) {
console.error(error);
}
})();
- اگه به کد بالا دقت کرده باشید ما الان 2 تا کار انجام دادیم
- اولیش اینه که الان با ران کردن این فایل تمام فایل های کامند هایی که توی پوشه
commands
ساختیم اتوماتیک ساخته میشه و به اسلش کامند های سرور اضافه میشه - دومیش هم اینه که ما دیگه نیاز نیست چیزایی مثل توکن و سرور ایدی و ایدی بات رو توی این کد تعریف بکنیم به صورت مستقیم و اونا رو از فایل
env.
میگیریم
- اولیش اینه که الان با ران کردن این فایل تمام فایل های کامند هایی که توی پوشه
حالا نوبت فایل bot.js
هستش که باید بهینه بشه
جدا از اینکه باید متغیر توکن رو از دیگه از فایل env.
داخلش قرار بدیم باید دستورات بات رو هم به یک فولدر و فایل های جدا انتقال بدیم
دلیلش هم اینه که فرض کنید شما یه بات دارید با بیش از 50 تا دستور و اگه قصد داشته باشید هر بار یکی از دستورات رو ادیت بدید کار خیلی سختی خواهد بود چون باید همش توی یه فایل بزرگ و شلوغ این ور و اون ور برید تا بتونید تیکه تیکه اون دستور رو ادیت بدید
برای راحتی بهتر تمامی کد های توی فایل bot.js
رو پاک کنید و با کد پایین جای گزین بکنید
const { Client, Intents, Collection } = require('discord.js');
const client = new Client({ intents: [Intents.FLAGS.GUILDS] });
const fs = require('fs');
require("dotenv").config();
let token = process.env.TOKEN
client.on('ready', () => {
console.log(`Logged in as ${client.user.tag}!`);
});
client.commands = new Collection();
const commandFiles = fs.readdirSync('./commands').filter(file => file.endsWith('.js'));
for (const file of commandFiles) {
const command = require(`./commands/${file}`);
// set a new item in the Collection
// with the key as the command name and the value as the exported module
client.commands.set(command.data.name, command);
}
client.on('interactionCreate', async interaction => {
if (!interaction.isCommand()) return;
const { commandName } = interaction;
if (!client.commands.has(commandName)) return;
try {
await client.commands.get(commandName).execute(interaction);
} catch (error) {
console.error(error);
await interaction.reply({ content: 'There was an error while executing this command!', ephemeral: true });
}
});
client.login(token);
بعد از اینکه کد رو عوض کردیم کافیه فقط ذخیرش بکنیم و فایل رو ران بکنیم
node bot.js
- و دستور
ping/
رو درون سرور میزنیم
- و دستور
همونطور که میبینید ما تونستیم با موفقیت 2 تا کار خوب و مهم توی کد هامون انجام بدیم
- انتقال متغیر های مودرنیاز به یک فایل جدا و فراخونی اونا به درون کد های اصلی
- جدا کردن دستورات و اتقال اونها به یک پوشه ای جدا و فایل های جدا برای مدیریت و نظم بهتر
-
دقیقا مثل کامند هندلر که ما بالا برای مدیریت بهتر دستورات ساختیم الان میخایم یدونه از اون برای ایونت ها بسازیم
-
اول از همه یه فولدر به نام
events
میسازیم- بعد از اون یه فایل درون اون میسازیم به نام
command-use.js
- و بعدش کد پایین رو درون اون قرار میدیم
- بعد از اون یه فایل درون اون میسازیم به نام
module.exports = {
name: 'interactionCreate',
execute(interaction) {
console.log(`${interaction.user.tag} in #${interaction.channel.name} triggered an interaction.`);
},
};
ما در ایونت بالا اومدیم تعریف کردیم که هر وقت یه interaction
به وجود اومد بیاد توی کنسول بهمون بگه چه کسی از اون استفاده کرده و در کدوم چنل
- ❓
interaction
ها همون عکس العمل هایی هستن که بات به دستورات ما نشون میده!
فایل بالا رو سیو میکنیم و میریم سراغ فایل اصلی بات یعنی bot.js
- و این بخش رو به فایل اضافه میکنیم
// events
const eventFiles = fs.readdirSync('./events').filter(file => file.endsWith('.js'));
for (const file of eventFiles) {
const event = require(`./events/${file}`);
if (event.once) {
client.once(event.name, (...args) => event.execute(...args));
} else {
client.on(event.name, (...args) => event.execute(...args));
}
};
-
بعد از این میتونیم ربات رو ران بکنیم و ببنیم که ایونتی که ساختیم کار میکنه یا نه
- node bot.js
event-handler.mp4
- و ما حتی میتونیم دیگه از این به بعد وقتی بات استارت میشه با یه ایونت توی فولدر
events
متوجه بشیم و دیگه نیازی نیستش پیام ready رو توی فایل اصلی بزاریم و تعریف بکنیمready.js
module.exports = {
name: 'ready',
once: true,
execute(client) {
console.log(`Ready! Logged in as ${client.user.tag} from ready.js in events folder!`);
},
};
- MessageActionRow چیه؟
- شما که قرار نیست همیشه جواب دستورات رو با یه پیام خشک و خالی بدید!
- MessageActionRow بهمون کمک میکنه که بتونیم چیزای جالبی رو مثل دکمه هارو به پیام های خودمون اضافه بکنیم و ازشون استفاده بکنیم
🔵 امبد مسیج یه نوع پیامه ولی قشنگ تر مرتب تر و توی یک کادر قرار داره و به نظر بهتر میاد
- ساخت دستور رو شروع میکنیم
- همون طور که میدونید فقط کافیه برید توی پوشه commands و یک فایل بسازید برای کامند که من اینجا اسم فایل رو گذاشتم
embed.js
شما هرچی دوست دارید بزارید - بعدش کافیه کد پایین رو توی فایل وارد بکنید
- همون طور که میدونید فقط کافیه برید توی پوشه commands و یک فایل بسازید برای کامند که من اینجا اسم فایل رو گذاشتم
const { MessageEmbed } = require('discord.js');
const { SlashCommandBuilder } = require('@discordjs/builders');
module.exports = {
data: new SlashCommandBuilder()
.setName('embed')
.setDescription('be ma e embed mide!'),
async execute(interaction) {
// embed
const embed = new MessageEmbed()
.setColor('#bd282d')
.setTitle('be in text migan [title]')
.setURL('https://github.com/ali0sam/discord-guide-fa')
.setAuthor('be in text migan [author]', 'https://cdn.discordapp.com/attachments/826890223916154903/876116512803553330/AYAYA.png', 'https://github.com/')
.setDescription('text text text text!')
.setThumbnail('https://cdn.discordapp.com/attachments/826890223916154903/876115837013069854/SuchMeme.png')
.addFields(
{ name: 'Regular field title', value: 'Some value here' },
{ name: '\u200B', value: '\u200B' }, // inja vase in fild haro ba [\u200B] por kardin chon injori 1 field khali mishe va mire badi
{ name: 'Inline field title', value: 'Some value here', inline: true },
{ name: 'Inline field title', value: 'Some value here', inline: true },
)
.addField('Inline field title', 'Some value here', true) // injori ham mitonid field tarif konid vali model bala nazm behtari dare
.setImage('https://cdn.discordapp.com/attachments/826890223916154903/876115904038064138/Valorant_KAY-O-Trailer-1024x576.jpg')
.setTimestamp()
.setFooter('Some footer text here', 'https://cdn.discordapp.com/attachments/826890223916154903/876116512803553330/AYAYA.png');
return interaction.reply({content: 'inja ro negah kon, e embed message!', embeds: [embed] });
},
};
-
⚪ بعد از سیو کردن فایل بالا مثل مثال کامند ریجستر که برای کامند هندلر توی بالا دیدید کامندش رو به سرور اضافه میکنید
-
حالا ربات رو ران بکنیم
node bot.js
embed-message.mp4
- دکمه ها میتونن خیلی مفید باشن و استفاده ازشون کلی حال میده
- بریم ببنیم با دکمه ها میشه چیکار کرد و نکته هارو هم بهتون بگم
اول مثل همیشه توی فولدر commands
یه فایل برای دستور میسازیم که اینجا من اسمشو میزارم button.js
بعد از اون میایم و کد پایین رو توی فایل قرار میدیم
const { MessageActionRow, MessageButton } = require('discord.js');
const { SlashCommandBuilder } = require('@discordjs/builders');
module.exports = {
data: new SlashCommandBuilder()
.setName('button')
.setDescription('dokme ha'),
async execute(interaction) {
// button
const row = new MessageActionRow()
.addComponents(
new MessageButton()
.setCustomId('primary')
.setLabel('test')
.setStyle('PRIMARY'),
);
return interaction.reply({content: 'tada!', components: [row]});
},
};
- بعد از این فقط کافیه فایل رو سیو بکنیم و یبار کامند های سرور رو با فایل
register-command.js
ذخیره بکنیم و ربات رو ران کنیمnode bot.js
simple-button.mp4
- 🔵 بعضی از مواقع هم میخایم که دکمه غیر فعال باشه و قابل فشار دادن نباشه پس میایم این کار میکنیم
.setDisabled(true)
// button
.addComponents(
new MessageButton()
.setCustomId('primary')
.setLabel('test')
.setStyle('PRIMARY')
.setDisabled(true),
);
disabled-button.mp4
- 😃 نظرت راجب یه ایموجی به همراه دکمه چیه؟
.setEmoji()
🔷 ایموجی ساده
.addComponents(
new MessageButton()
.setCustomId('primary')
.setLabel('test')
.setStyle('PRIMARY')
.setEmoji('🎉'),
);
🔷 سرور ایموجی
.addComponents(
new MessageButton()
.setCustomId('primary')
.setLabel('test')
.setStyle('PRIMARY')
.setEmoji('emojiID'),
);
emoji-button.mp4
- ⚠ حتما هم حواستون باشه که بات توی اون سرور که ایموجی مال اونه باشه
-
🔄 عملکرد در اثر فشرده شده
-
رسیدیم به بحث اصلی که توی اون باید دکمه ها بعد از فشرده شدن یک کار رو برای ما انجام بدن
- و ما اینجا برای این کار از کالکتور استفاده میکنیم
- کالکتور چیه؟ -بیاین اینطوری فرض بکنیم که کالکتور یه نگهبانه که ما میزاریمش یه تایم خاصی حواسش به یه چیزی باشه
- من الان به طور مثال برای فایل
button.js
یه کالکتور میسازم
- و ما اینجا برای این کار از کالکتور استفاده میکنیم
const { MessageActionRow, MessageButton } = require('discord.js');
const { SlashCommandBuilder } = require('@discordjs/builders');
module.exports = {
data: new SlashCommandBuilder()
.setName('button')
.setDescription('dokme ha'),
async execute(interaction) {
// button
const row = new MessageActionRow()
.addComponents(
new MessageButton()
.setCustomId('primary')
.setLabel('test')
.setStyle('PRIMARY')
.setEmoji('🎉'),
);
// collector
const filter = i => i.customId === 'primary' && i.user.id === '575933571186032641';
const collector = interaction.channel.createMessageComponentCollector({ filter, time: 15000 });
collector.on('collect', async i => {
if (i.customId === 'primary') {
await i.update({ content: 'dokme click shod!', components: [] });
}
});
collector.on('end', collected => console.log(`Collected ${collected.size} items`));
// send message and button
return interaction.reply({content: 'tada!', components: [row]});
},
};
- توضیح چنتا نکته از کد بالا و قسمت کالکتور اون:
- ما معمولا برای این از متد
.setCustomId()
داخل دکمه ها استفاده میکنیم چون قراره از اون ایدی توی کالکتور برای شناسایی استفاده بشه - و ما در بخش کالکتور اول از همه میایم یه فیلتر میزاریم به این صورت که بیاد دکمه رو به ایدی و ایدی یوزری که اونو فشار میده فیلتر میکنه کارکردش رو
const filter = i => i.customId === 'primary' && i.user.id === '575933571186032641';
- البته برای یوزر ایدی دی کد بالا حتما نیاز نیست که ایدی رو دستی وارد بکنیم و میتونید از مثال پایین استفاده بکنید که به صورت خودکار ایدی اون فردی که از دستور استفاده کرده رو درنظر بگیره
const filter = i => i.customId === 'primary' && i.user.id === interaction.user.id;
- و در قسمت collector هم یک کالکتور ساخته میشه با فیلتر هایی که تعریف کردیم و تایم
15000
که به میلی ثانیه هست و میشه15
ثانیه و یعنی بعد از 15 ثانیه این کالتور تموم میشه - و در اخر هم کد زیر وجود داره که میاد بعد از تموم شدن تایم محاسبه میکنه که چند تا دکمه از کالکتور کلیک شده
collector.on('end', collected => console.log(`Collected ${collected.size} items`));
- ما معمولا برای این از متد
و توی این قسمت شما نیاز نیست حتما از update
استفاده بکنید و میتونید متد های دیگه هم استفاده بکنید
await i.update({ content: 'dokme click shod!', components: [] })
reply()
editReply()
deferReply()
fetchReply()
deleteReply()
followUp()
button-collector.mp4
-
استایل دکمه ها
-
در کل 5 تا استایل دکمه وجود داره
PRIMARY
SECONDARY
SUCCESS
DANGER
LINK
-
⚪ در قالب یه کامند دیگه همشون رو براتون این زیر یه مثال میزنم
buttons.js
const { MessageActionRow, MessageButton } = require('discord.js');
const { SlashCommandBuilder } = require('@discordjs/builders');
module.exports = {
data: new SlashCommandBuilder()
.setName('buttons')
.setDescription('tamam style haye dokme ha'),
async execute(interaction) {
// buttons
const row = new MessageActionRow()
.addComponents(
new MessageButton()
.setCustomId('1')
.setLabel('PRIMARY button')
.setStyle('PRIMARY'),
new MessageButton()
.setCustomId('2')
.setLabel('SECONDARY button')
.setStyle('SECONDARY'),
new MessageButton()
.setCustomId('3')
.setLabel('SUCCESS button')
.setStyle('SUCCESS'),
new MessageButton()
.setCustomId('4')
.setLabel('DANGER button')
.setStyle('DANGER'),
new MessageButton()
.setLabel('LINK button')
.setURL('https://github.com/ali0sam/discord-guide-fa')
.setStyle('LINK'),
);
// send message and button
return interaction.reply({content: 'style ha!', components: [row]});
},
};
buttons-style.mp4
- ❗ یه نکته هم اینجا هست اینه که دکمه های استایل
LINK
نبایدsetCustomId().
داشته باشن و فقط میتونید ازsetUrl().
توش استفاده بکنید
- برای ساخت یه کامند که به ما منو نشون بده من اول یه فایل توی پوشه
commands
میسازیم به نامmenu.js
- و کد زیر رو توش وارد میکنیم
const { MessageActionRow, MessageSelectMenu } = require('discord.js');
const { SlashCommandBuilder } = require('@discordjs/builders');
module.exports = {
data: new SlashCommandBuilder()
.setName('menu')
.setDescription('neshon dadan menu'),
async execute(interaction) {
const row = new MessageActionRow()
.addComponents(
new MessageSelectMenu()
.setCustomId('select')
.setPlaceholder('inja click kon')
.addOptions([
{
label: 'Select me',
description: 'This is a description',
value: 'first_option',
},
{
label: 'You can select me too',
description: 'This is also a description',
value: 'second_option',
},
]),
);
await interaction.reply({ content: 'Menu!', components: [row] });
},
};
select-menu.mp4
- ⚪ نوع دوم منو ها رو میشه دونه دونه میشه سلکت کرد و در اخر ریکوعست رو داد
menu2.js
const { MessageActionRow, MessageSelectMenu } = require('discord.js');
const { SlashCommandBuilder } = require('@discordjs/builders');
module.exports = {
data: new SlashCommandBuilder()
.setName('menu2')
.setDescription('neshon dadan Multi-select menus'),
async execute(interaction) {
const row = new MessageActionRow()
.addComponents(
new MessageSelectMenu()
.setCustomId('select')
.setPlaceholder('Nothing selected')
.setMinValues(2)
.setMaxValues(3)
.addOptions([
{
label: 'Select me',
description: 'This is a description',
value: 'first_option',
},
{
label: 'You can select me too',
description: 'This is also a description',
value: 'second_option',
},
{
label: 'I am also an option',
description: 'This is a description as well',
value: 'third_option',
},
]),
);
await interaction.reply({ content: 'Menu!', components: [row] });
},
};
select-menu2.mp4
- عملکرد در اثر انتخاب
- ما الان میخایم که فایل
menu.js
رو یکمی ادیت بدیم و بهش کالکتور اضافه بکنیم تا مثل دکمه ها وقتی یه اپشن رو از منو انتخواب میکنیم بهمون جواب بده
- ما الان میخایم که فایل
const { MessageActionRow, MessageSelectMenu } = require('discord.js');
const { SlashCommandBuilder } = require('@discordjs/builders');
module.exports = {
data: new SlashCommandBuilder()
.setName('menu')
.setDescription('neshon dadan menu'),
async execute(interaction) {
const row = new MessageActionRow()
.addComponents(
new MessageSelectMenu()
.setCustomId('select')
.setPlaceholder('inja click kon')
.addOptions([
{
label: 'Select me',
description: 'This is a description',
value: 'first_option',
},
{
label: 'You can select me too',
description: 'This is also a description',
value: 'second_option',
},
]),
);
await interaction.reply({ content: 'Menu!', components: [row] });
// collector
const filter = i => i.customId === 'select' && i.user.id === interaction.user.id;
const collector = interaction.channel.createMessageComponentCollector({ filter, time: 15000 });
collector.on('collect', async i => {
if (i.values[0] === 'first_option') {
await i.update({ content: 'shoma option 1 ro select kardid!', components: [] });
}
});
collector.on('end', collected => console.log(`Collected ${collected.size} items`));
},
};
- 🔷 توی کد بالا ما توی کالکتور تعریف کردیم که اگه اپشنی که انتخاب میشه value اون مساوی با
first_option
بود بیاد به ما یه پاسخ بده
و توی این قسمت شما نیاز نیست حتما از update
استفاده بکنید و میتونید متد های دیگه هم استفاده بکنید
await i.update({ content: 'shoma option 1 ro select kardid!', components: [] })
reply()
editReply()
deferReply()
fetchReply()
deleteReply()
followUp()
-
وب هوک چیه؟
- به صورت کلی یه سیستمه که بااستفاده از اون اطلاعات رو بین اپ های دیگه انتقال میدن
- مثلا انتقال رسید های پی پال شما به یک وب هوک که متوجه بشید و یا انتقال دیتا هایی که توی پروژه گیتهاب خودتون عوض کردید به یک وب هوک
- ❕
صد درصد من نمیتونم با همچین توضیحات کوتاهی بتونم کل متحوا رو برسونم پس بهتره خودتون هم سرچ داشته باشید
- ❕
- مثلا انتقال رسید های پی پال شما به یک وب هوک که متوجه بشید و یا انتقال دیتا هایی که توی پروژه گیتهاب خودتون عوض کردید به یک وب هوک
- به صورت کلی یه سیستمه که بااستفاده از اون اطلاعات رو بین اپ های دیگه انتقال میدن
-
ساخت وب هوک توی دیسکورد
- اول از همه وارد حالت ادیت یک تکست چنل بشید
- بعد قسمت
Integrations
رو باز بکنید- و بعدش از توی قسمت
Webhooks
بزنید روی گزینهCreate Webhook
- و بعدش از توی قسمت
- بعد قسمت
- اول از همه وارد حالت ادیت یک تکست چنل بشید
create-webhook.mp4
-
بعد از ساخت وب هوک میتونید براش یه اسم دلخواه بزارید یا اواتار ولی نکته اصلی اینه که یه لینک ساخته میشه که توی اون دیتا های وب هوکی که ساختید رو میده و میتونید توکن و ایدی وب هوک رو کپی کنید
-
با استفاده از
discord.js
ما 2 تا راه داریم که یه پیام رو به یک وب هوک ارسال بکنیم
WebhookClient
این روش برای وقتی هستش که میخاید یه کد بنویسید که فقط به وب هوک دیتا ارسال بکنه و نمیخاید اصلا با بات کار رو انجام بدیدBotClient
این روش هم مال وقتیه که میخاید با استفاده از یه بات به یک وبهوک دیتا ارسال کنید- WebhookClient Example
const { MessageEmbed, WebhookClient } = require('discord.js');
const { webhookId, webhookToken } = require('./config.json');
const webhookClient = new WebhookClient({ id: webhookId, token: webhookToken });
const embed = new MessageEmbed()
.setTitle('Some Title')
.setColor('#0099ff');
webhookClient.send({
content: 'Webhook test',
username: 'some-username',
avatarURL: 'https://i.imgur.com/AfFp7pu.png',
embeds: [embed],
});
- 🔷 TIP / نکته
توی وب هوک کلاینت ما میتونید به 2 حالت توکن و ایدی رو تعریف بکنید
const webhookClient = new WebhookClient({ id: 'id', token: 'token' });
یا همون لینکی که کپی کردید رو مستقیم وارد میکنید مثل مثال زیر
const webhookClient = new WebhookClient({ url: 'https://discord.com/api/webhooks/id/token' });
- BotClient Example
const { Client, Intents, MessageEmbed } = require('discord.js');
const { token } = require('./config.json');
const client = new Client({ intents: [Intents.FLAGS.GUILDS] });
const embed = new MessageEmbed()
.setTitle('Some Title')
.setColor('#0099ff');
client.once('ready', async () => {
const channel = client.channels.cache.get('123456789012345678');
try {
const webhooks = await channel.fetchWebhooks();
const webhook = webhooks.first();
await webhook.send({
content: 'Webhook test',
username: 'some-username',
avatarURL: 'https://i.imgur.com/AfFp7pu.png',
embeds: [embed],
});
} catch (error) {
console.error('Error trying to send a message: ', error);
}
});
client.login(token);
- ❗ کد بالا با بات کلاینت عمل میکنه و میاد بر اساس اون ایدی چنلی که بهش دادید میاد اولین وب هوک اون رو مشخص میکنه و یه امبد مسیج میفرسته اونجا و این یه کد ایندکس ساده هست نه اسلش کامند
select-menu-res.mp4
.addStringOption(option => option.setName('input').setDescription('Enter a string'))
.addIntegerOption(option => option.setName('int').setDescription('Enter an integer'))
.addNumberOption(option => option.setName('num').setDescription('Enter a number'))
.addBooleanOption(option => option.setName('choice').setDescription('Select a boolean'))
.addUserOption(option => option.setName('target').setDescription('Select a user'))
.addChannelOption(option => option.setName('destination').setDescription('Select a channel'))
.addRoleOption(option => option.setName('muted').setDescription('Select a role'))
.addMentionableOption(option => option.setName('mentionable').setDescription('Mention something'));
- و جوری که میتونید اونارو به متغیر تبدیل بکنید که راحت تر باشید
const string = interaction.options.getString('input');
const integer = interaction.options.getInteger('int');
const number = interaction.options.getNumber('num');
const boolean = interaction.options.getBoolean('choice');
const user = interaction.options.getUser('target');
const member = interaction.options.getMember('target');
const channel = interaction.options.getChannel('destination');
const role = interaction.options.getRole('muted');
const mentionable = interaction.options.getMentionable('mentionable');
- من اینجا برای تست اول از همه یه فایل توی فولدر
commands
میسازم به نامcallback.js
const { SlashCommandBuilder } = require('@discordjs/builders');
module.exports = {
data: new SlashCommandBuilder()
.setName('callback')
.setDescription('callback your text!')
.addStringOption(option =>
option.setName('text')
.setDescription('ek text baray callback vared konid')
.setRequired(true)
),
async execute(interaction) {
const text = interaction.options.getString('text');
await interaction.reply({content: `text vared shode tavasot shoma = [${text}]`, ephemeral: true})
}
}
- توی کد بالا ما اومدیم و یک استرینگ اپشن تعریف کردیم که بتونیم یه متن از طرف مقابل بگیریم و اپشن رو هم
required
تعریف کردیم که یوزر یه چیزی ارسال بکنه و کامند خالی نباشه (یکی از بزرگ ترین خوبی های اسلش کامند 😀)
و بعد اومدیم توی دستور استرینگ رو به یک متغیر تبدیل کردیم که راحت توی کد ازش استفاده بکنیم و اسمشو گذاشتیم text
- بعدش هم خیلی راحت با
{text}$
ازش استفاده کردیم - مسیج رو هم ephemeral کردیم که فقط یوزر ببینه و چنل الکی شلوغ نشه
callback-command.mp4
- فایل
ready.js
رو یادتونه؟ اینجا ما میخایم اول اونو یه ادیتی بدیم و بعد بریم سراغ 2 تا ایونت دیگه- ready.js
module.exports = {
name: 'ready',
once: true,
execute(client) {
global.servers = client.guilds.cache.size
console.log(`Ready! Logged in as ${client.user.tag} from ready.js in events folder! and servers: ${client.guilds.cache.size}`);
client.user.setActivity(`${global.servers} servers`, { type: "WATCHING"})
var checkservers = 5, checkthe_interval = checkservers * 60 * 1000; //in interval har 5 min check mishe va mitoind khodeton [5] ro ba harchi mikhayed change konid vali havaseton be api block discord bashe!
setInterval(function() {
client.user.setActivity(`${global.servers} servers`, { type: "WATCHING"})
}, checkthe_interval);
},
};
-
🔵 توضیحات راجب کد بالا
- اولیش اینکه شاید براتون سوال شده باشه که
global.servers
چیه و چرا ازش استفاده میکنیم؟ global
یه نوع متغیر گذاری تویnode.js
هست که به صورت همگانی میون فایل ها یه متغیر رو مشخص میکنیم یعنی من الان از این متغیر میتونم به صورتglobal.servers
توی فایل های دیگه خودم هم استفاده بکنم که به درد میخوره- 🔷 [اینجا چون ما نمیخواستیم الان وارد بحث دیتابیس بشیم من این کار رو کردم]
- و بعد از اون اومدم یه اکتیویتی روی سرور های فعلی بات ست کردم با
client.user.setActivity(`${global.servers} servers`, { type: "WATCHING"})
- من توی کد بالا از تایپه
WATCHING
استفاده کردم شما میتونید از تایپ های زیر هم استفده کنید LISTENING
COMPETING
- بعد از اون یه
interval
تعریف میکنم که یعنی یه فراینده لوپ و تکرار شونده و میگیم که هر 5 دقیقه اکتیویتی بروز بشه و دوباره ست بشه که اگه بات توی 5 دقیقه به سرور های جدیدی اضافه شد و یا از سروری حذف شد تعداد به روز شده رو به ما نشون بده
- بعد از اون یه
- اولیش اینکه شاید براتون سوال شده باشه که
-
بعد از ادیت کردن فایل
ready.js
2 عدد فایل جدید میسازیم توی پوشهevents
-
invite-guild.js
module.exports = {
name: 'guildCreate',
execute(guild) {
servers = global.servers + 1
console.log(`bot be ek server jadid ba id [${guild.id}] invite shod!, servers count: ${servers}`);
},
};
- remove-guild.js
module.exports = {
name: 'guildDelete',
execute(guild) {
servers = global.servers - 1
console.log(`bot az ek server remove shod, [${guild.id}], servers count: ${servers}`);
},
};
- 🔵 توی 2 تا ایونت بالا چنتا کار کردیم
- دیگه هر وقت که بات توی سرور جدیدی اینوایت بشه و یا از سرور بیرون بشه لاگ میشه . که حالا من برای تست که فقط نشون بدم گذاشتم روی لاگ و شما میتونید کار های دیگه بکنید
- و از اون
global.servers
که توی فایلready.js
گذاشتیم استفاده کردیم و هر وقت به طور مثال بات به سروری اضافه میشه اونو به علاوه 1 میکنیم و لاگ میکنیم و برای ریمو سرور و هم برعکس
invite-bot-event.mp4
خب به صورت کلی این کار خیلی سادس و فقط کافیه یه همچین کاری بکنیم
const user = client.users.cache.get('id');
user.send('the text!');
-
و اگه هم بخاید توی اسلش کامند به فردی که کامند رو یوز کرده دی ام بدید میشه
interaction.user.send('the text!')
-
ولی اگه بخایم این کار رو به صورت یک کامند در بیاریم مثالش میشه کد زیر
- folder:
commands
- file:
dm.js
- file:
- folder:
const { SlashCommandBuilder } = require('@discordjs/builders');
module.exports = {
data: new SlashCommandBuilder()
.setName('dm')
.setDescription('dm be ek user.')
// options
.addUserOption(option =>
option.setName('targetuser')
.setDescription('ek user ra entekhab konid baray DM!')
.setRequired(true)
)
.addStringOption(option =>
option.setName('text')
.setDescription('text khod ra varid konid')
.setRequired(true)
),
async execute(interaction) {
const mem = interaction.options.getUser('targetuser')
const text = interaction.options.getString('text');
mem.send(text);
await interaction.reply({content: 'text shoma ersal shod be DM!', ephemeral: true});
}
}
با استفاده از اسلش کامند و اپشن هاش این کار خیلی اسونه
- ❕ (البته بدون درنظر گرفت اینکه این کامند اینجوری شاید باقی نمونه و باید توش ادیت بدید و چنتا شرط اضافه بکنید)
طبق روال معمول توی پوشه commands
یک فایل میسازیم که اینجا من اسمشو گذاشتم giverole.js
و کد زیر رو توش وارد میکنیم
const { SlashCommandBuilder } = require('@discordjs/builders');
module.exports = {
data: new SlashCommandBuilder()
.setName('giverole')
.setDescription('the add role command')
.addUserOption(option =>
option.setName('member')
.setDescription('ek user to entekhab konid')
.setRequired(true)
)
.addRoleOption(option =>
option.setName('role')
.setDescription('ek role ra entekhab konid')
.setRequired(true)
),
async execute(interaction) {
const member = interaction.options.getMember('member');
const role = interaction.options.getRole('role');
member.roles.add(role)
await interaction.reply({content: 'be user role dade shod', ephemeral: true})
}
}
- و یبار هم فایل
register-command.js
رو ران میکنیم که دستور به سرور اضافه بشه و بعدی میریم سراغ تست