\`\`\`**');
14 | const msgEmbed = new MessageEmbed()
15 |
16 | .setColor('#f82c2c')
17 | .setTitle(`**${mentionUser.username} Warning**`)
18 | .setThumbnail(`${mentionUser.avatarURL({format : 'png', dynamic : true, size : 1024})}`)
19 | .setDescription(`${mentionUser.username} **berhasil diwarn dengan alasan:**\`\`\`diff\n- ${args.slice(1).join(' ')}\`\`\``)
20 | .setFooter({text: `Diwarn oleh ${message.author.username}`, iconURL: message.author.avatarURL({format : 'png', dynamic : true, size : 1024})})
21 | .setTimestamp();
22 |
23 | message.channel.send({embeds: [msgEmbed]});
24 |
25 | let channellog = client.channels.cache.get(process.env.CHANNELLOGID);
26 | let channellogembed = new MessageEmbed()
27 |
28 | .setColor('#ff0000')
29 | .setAuthor({name: `${mentionUser.username} Warning`, iconURL: mentionUser.avatarURL({format : 'png', dynamic : true, size : 1024})})
30 | .setDescription(`**⚠️ - ${mentionUser.username} telah diwarn oleh ${message.author.username}**`)
31 | .setTimestamp();
32 |
33 | channellog.send({embeds: [channellogembed]});
34 | }
35 | };
36 |
--------------------------------------------------------------------------------
/src/commands/interaction/weather.js:
--------------------------------------------------------------------------------
1 | const MsnWeather = require('msn-weather-api');
2 | const weather = new MsnWeather('en', 'C');
3 | const { SlashCommandBuilder } = require('@discordjs/builders');
4 | const { MessageEmbed } = require('discord.js');
5 |
6 | module.exports = {
7 | data: new SlashCommandBuilder()
8 | .setName('weather')
9 | .setDescription('Weather forecast')
10 | .addStringOption(option =>
11 | option.setName('location')
12 | .setDescription('location')
13 | .setRequired(true)
14 | ),
15 | /**
16 | * @param {import("../../../client").interaction} interaction
17 | */
18 | async execute(interaction) {
19 | let location = interaction.options.get('location').value;
20 |
21 | if (!location) return interaction.reply('**Berikan args**');
22 |
23 | const current = await weather.getCurrentData(location);
24 |
25 | const weatherEmbed = new MessageEmbed()
26 |
27 | .setColor('#89e0dc')
28 | .setTitle('Weather')
29 | .setThumbnail(current.icon)
30 | .setDescription('Powered by msn-weather-api')
31 | .addFields(
32 | { name: 'Location', value: `${current.location}`, inline: true },
33 | { name: 'Weather', value: `${current.weather}`, inline: true },
34 | { name: 'Temperature', value: `${current.temperature}`, inline: true },
35 | { name: 'Humidity', value: `${current.humidity}`, inline: true },
36 | { name: 'Date', value: `${current.date}`, inline: true },
37 | { name: 'Windspeed', value: `${current.windspeed}`, inline: true }
38 | )
39 | .setFooter({ text: `Direquest oleh ${interaction.member.nickname || interaction.user.username}`, iconURL: interaction.user.avatarURL({ format: 'png', dynamic: true, size: 1024 }) })
40 | .setTimestamp();
41 |
42 | interaction.reply({ embeds: [weatherEmbed] });
43 | }
44 | };
45 |
--------------------------------------------------------------------------------
/src/commands/interaction/mal.js:
--------------------------------------------------------------------------------
1 | const { SlashCommandBuilder } = require('@discordjs/builders');
2 | const { MessageEmbed } = require('discord.js');
3 | const malScraper = require('mal-scraper');
4 |
5 | module.exports = {
6 | data: new SlashCommandBuilder()
7 | .setName('mal')
8 | .setDescription('MAL scraper')
9 | .addStringOption(option =>
10 | option.setName('anime')
11 | .setDescription('Anime name')
12 | .setRequired(true)
13 | ),
14 | /**
15 | * @param {import("../../../client").interaction} interaction
16 | * @param {import("../../../client").client} client
17 | */
18 | async execute(interaction, client) {
19 | const animeValue = interaction.options.get('anime').value;
20 | const animeScraper = await malScraper.getInfoFromName(animeValue);
21 | if (!animeScraper) return interaction.reply(process.env.DEFAULT_ERROR);
22 |
23 | const msgEmbed = new MessageEmbed()
24 |
25 | .setColor('#CE0F3D')
26 | .setAuthor({name: animeScraper.title, iconURL: client.user.displayAvatarURL(), url: animeScraper.url})
27 | .setImage(animeScraper.picture)
28 | .setDescription(animeScraper.synopsis)
29 | .addFields(
30 | { name: 'Type', value: `${animeScraper.type}`, inline: true },
31 | { name: 'Episode', value: `${animeScraper.episodes}`, inline: true },
32 | { name: 'Duration', value: `${animeScraper.duration}`, inline: true },
33 | { name: 'Genres', value: `${animeScraper.genres.join(', ')}`, inline: true },
34 | { name: 'Status', value: `${animeScraper.status}`, inline: true },
35 | { name: 'Score', value: `${animeScraper.score}`, inline: true }
36 | )
37 | .setFooter({text: animeScraper.url, iconURL: 'https://pbs.twimg.com/profile_images/1190380284295950339/Py6XnxvH_400x400.jpg'})
38 | .setTimestamp();
39 |
40 | interaction.reply({embeds: [msgEmbed]});
41 | }
42 | };
43 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | ***
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 | ***
15 |
16 |
RyU
17 | Powerful Discord Automaton written in JavaScript. Lightweight, Efficient, Feature-rich.
18 |
19 | # Requirements
20 |
21 | |Tools|Version|
22 | |-|-|
23 | |**Node.JS**|**>=16.20.2**|
24 | |**NPM**|**>=8.19.4**|
25 |
26 | ## How to use
27 |
28 | 1. Install all dependencies, or you can ignore the optional dependencies if you prefer:
29 | ```
30 | npm install
31 |
32 | # or
33 |
34 | npm install --no-optional
35 | ```
36 | 2. Rename **.env.example** to **.env** and populate it with all the necessary values:
37 | ```
38 | .env.example > .env
39 | ```
40 | 3. Similarly, rename **config.json.example** to **config.json** and provide the required values:
41 | ```
42 | Rename config.json.example to config.json and complete all the available values.
43 | ```
44 | 4. After completing the above steps, execute **npm run deploy** to register your slash command with the REST API:
45 | ```
46 | npm run deploy
47 | ```
48 | 5. Lastly, run **npm start** to launch your client:
49 | ```
50 | npm start
51 | ```
52 |
53 | ## Security
54 |
55 | |Version|Vulnerability|
56 | |-|-|
57 | |5.5.x|:white_check_mark:|
58 | |5.4.x|:x:|
59 | |5.3.x|:x:|
60 | |5.2.x|:x:|
61 | |5.1.x|:x:|
62 | |5.0.x|:x:|
63 |
64 | Click [here](https://github.com/Muunatic/RyU/security/policy) for more info.
65 |
66 | ## Disclaimer
67 |
68 | This file is part of the RyU project.
69 |
70 | The RyU project can not be distributed without the express permission of Muunatic.
71 |
--------------------------------------------------------------------------------
/src/commands/interaction/osu.js:
--------------------------------------------------------------------------------
1 | const { SlashCommandBuilder } = require('@discordjs/builders');
2 | const { MessageEmbed } = require('discord.js');
3 | const osu = require('node-osu');
4 | const osuApi = new osu.Api(process.env.OSU_API);
5 |
6 | module.exports = {
7 | data: new SlashCommandBuilder()
8 | .setName('osu')
9 | .setDescription('Osu profile')
10 | .addStringOption(option =>
11 | option.setName('username')
12 | .setDescription('osu! username')
13 | .setRequired(true)
14 | )
15 | .addNumberOption(option2 =>
16 | option2.setName('mode')
17 | .setDescription('osu! mode')
18 | .setRequired(true)
19 | .addChoices(
20 | {name: 'osu', value: 1},
21 | {name: 'taiko', value: 2},
22 | {name: 'osumania', value: 3}
23 | )
24 | ),
25 | /**
26 | * @param {import("../../../client").interaction} interaction
27 | */
28 | async execute(interaction) {
29 | const args1 = interaction.options.get('username').value;
30 | const args2 = interaction.options.get('mode').value;
31 | const user = args1;
32 | const mode = args2;
33 | if (!user) return interaction.reply('**Username tidak ditemukan**');
34 | if (!mode) return interaction.reply('**Mode tidak ditemukan**');
35 | const data = await osuApi.getUser({
36 | u: user, m: mode
37 | });
38 | if (!data) return interaction.reply('**Data tidak ditemukan**');
39 | if (!data.pp.rank || !data.accuracy === null) return interaction.reply('**Data tidak ditemukan**');
40 | const msgEmbed = new MessageEmbed()
41 |
42 | .setColor('#CE0F3D')
43 | .setTitle(`OSU ${data.name} Profile`)
44 | .setThumbnail(`https://s.ppy.sh/a/${data.id}`)
45 | .setDescription(`:flag_${data.country.toLowerCase()}: **${data.name}**`)
46 | .addFields(
47 | { name: 'Name', value: `${data.name}`, inline: true },
48 | { name: 'Rank', value: `${data.pp.rank}`, inline: true },
49 | { name: 'Level', value: `${data.level}`, inline: true },
50 | { name: 'Accuracy', value: `${data.accuracy}`, inline: true },
51 | { name: 'Joined', value: `${data.raw_joinDate}`, inline: true },
52 | { name: 'Performance Point', value: `${data.pp.raw}`, inline: true }
53 | )
54 | .setFooter({text: `https://osu.ppy.sh/users/${data.id}`, iconURL:`https://s.ppy.sh/a/${data.id}`})
55 | .setTimestamp();
56 |
57 | interaction.reply({embeds: [msgEmbed]});
58 | }
59 | };
60 |
--------------------------------------------------------------------------------
/src/commands/interaction/stats.js:
--------------------------------------------------------------------------------
1 | const os = require('os');
2 | const cpuStat = require('cpu-stat');
3 | const { SlashCommandBuilder } = require('@discordjs/builders');
4 | const { MessageEmbed } = require('discord.js');
5 | const moment = require('moment-timezone');
6 |
7 | module.exports = {
8 | data: new SlashCommandBuilder()
9 | .setName('stats')
10 | .setDescription('Client stats'),
11 | /**
12 | * @param {import("../../../client").interaction} interaction
13 | * @param {import("../../../client").client} client
14 | */
15 | async execute(interaction, client) {
16 | let indonesiaTime = moment().tz('Asia/Jakarta').format();
17 | setInterval(() => {
18 | indonesiaTime -= 2000;
19 | });
20 |
21 | const idTime = indonesiaTime.slice(11, -6);
22 | const idDate = indonesiaTime.slice(0, -15);
23 |
24 | cpuStat.usagePercent((err, percent) => {
25 | if (err) {
26 | return console.log(err);
27 | }
28 |
29 | let totalSeconds = (client.uptime / 1000);
30 | let days = Math.floor(totalSeconds / 86400);
31 | totalSeconds %= 86400;
32 | let hours = Math.floor(totalSeconds / 3600);
33 | totalSeconds %= 3600;
34 | let minutes = Math.floor(totalSeconds / 60);
35 | let seconds = Math.floor(totalSeconds % 60);
36 |
37 | let msgEmbed = new MessageEmbed()
38 |
39 | .setColor('#89e0dc')
40 | .setTitle('Client Stats')
41 | .setThumbnail(`${interaction.client.user.avatarURL({format : 'png', dynamic : true, size : 4096})}`)
42 | .setDescription(`Client ini telah aktif selama **${days} hari, ${hours} jam, ${minutes} menit, dan ${seconds} detik**`)
43 | .addFields(
44 | { name: 'CPU', value: `${os.cpus().map(i => `${i.model}`)[0]}`, inline: true },
45 | { name: 'CPU Usage', value: `${percent.toFixed(2)}%`, inline: true },
46 | { name: 'Memory', value: `${(process.memoryUsage().heapUsed / 1024 / 1024).toFixed(2)}MB / ${(os.totalmem() / 1024 / 1024).toFixed(2)}MB`, inline: true },
47 | { name: 'Architecture', value: `${os.arch()}-based processor`, inline: true },
48 | { name: 'Platform', value: `${os.platform()}`, inline: true },
49 | { name: 'Engine', value: `${process.version}`, inline: true }
50 | )
51 | .setFooter({text: `Direquest oleh ${interaction.member.nickname || interaction.user.username} • ${idTime} ${idDate}`, iconURL: interaction.user.avatarURL({format : 'png', dynamic : true, size : 1024})});
52 |
53 | interaction.reply({embeds: [msgEmbed]});
54 | });
55 | }
56 | };
57 |
--------------------------------------------------------------------------------
/src/commands/message/general/register.js:
--------------------------------------------------------------------------------
1 | const crypto = require('crypto');
2 | const { client } = require('../../../../client');
3 | const { MessageEmbed, MessageCollector } = require('discord.js');
4 |
5 | module.exports = {
6 | name: 'register',
7 | /**
8 | * @param {import("../../../../client").message} message
9 | */
10 | execute(message) {
11 | let channelLog = client.channels.cache.get(process.env.CHANNELLOGID);
12 | if (!message.member.roles.cache.get(process.env.UNREGISTER_ID)) return message.channel.send('**Kamu sudah teregistrasi**')
13 | .then(msg => {
14 | setTimeout(() => msg.delete(), 5000);
15 | });
16 | if (message.member.roles.cache.get(process.env.REGISTER_ID)) return message.channel.send('**Kamu sudah teregistrasi**')
17 | .then(msg => {
18 | setTimeout(() => msg.delete(), 5000);
19 | });
20 | const otpCode = crypto.createHash('sha256').update(message.id).digest('hex');
21 | message.author.send(`**Masukan kode verifikasi: **\`\`\`${otpCode}\`\`\``);
22 | message.reply('**Kode verifikasi terkirim**').then(msg => {
23 | setTimeout(() => msg.delete(), 60000);
24 | });
25 | const collector = new MessageCollector(message.channel, {filter: m => m.author.id === message.author.id, time: 60000});
26 | collector.on('collect', async message => {
27 | if (message.content === otpCode) {
28 | collector.stop();
29 | setTimeout(() => message.delete(), 5000);
30 |
31 | message.member.roles.add(process.env.REGISTER_ID);
32 |
33 | message.reply('**Kode verifikasi diterima**')
34 | .then(msg => {
35 | setTimeout(() => msg.delete(), 5000);
36 | });
37 |
38 | message.member.roles.remove(process.env.UNREGISTER_ID);
39 |
40 | let channelLogEmbed = new MessageEmbed()
41 |
42 | .setColor('#00ff00')
43 | .setAuthor({name: 'Member Joined', iconURL: message.author.avatarURL({format : 'png', dynamic : true, size : 1024})})
44 | .setDescription(`**${client.emojis.cache.get('835987657892298802')} - ${message.author.username} telah join ke server**`)
45 | .setFooter({text: message.author.username, iconURL: message.author.avatarURL({format : 'png', dynamic : true, size : 1024})})
46 | .setTimestamp();
47 |
48 | channelLog.send({embeds: [channelLogEmbed]});
49 | } else if (message.content === `${process.env.PREFIX}register`) {
50 | collector.stop();
51 | message.channel.send('**Kode verifikasi telah digantikan**')
52 | .then(msg => {
53 | setTimeout(() => msg.delete(), 5000);
54 | });
55 | } else if (message.content !== otpCode) {
56 | collector.stop();
57 | message.channel.send('**Kode verifikasi ditolak**')
58 | .then(msg => {
59 | setTimeout(() => msg.delete(), 5000);
60 | });
61 | }
62 | });
63 | }
64 | };
65 |
--------------------------------------------------------------------------------
/src/structures/dmMessage.js:
--------------------------------------------------------------------------------
1 | const { client } = require('../../client');
2 | const { MessageEmbed, MessageCollector } = require('discord.js');
3 |
4 | const reportCooldown = new Set();
5 |
6 | client.on('messageCreate', async message => {
7 |
8 | const args = message.content.slice(process.env.PREFIX.length).trim().split(/ +/);
9 | const command = args.shift().toLowerCase();
10 |
11 | if (message.channel.type === 'DM') {
12 | let dmChannel = client.channels.cache.get(process.env.CHANNELLOGPRIVATE);
13 | let messageEmbed = new MessageEmbed()
14 |
15 | .setTitle('DM Channel')
16 | .setColor('#89e0dc')
17 | .setAuthor({name: message.author.username, iconURL: message.author.avatarURL({format : 'png', dynamic : true, size : 1024})})
18 | .setDescription(message.content)
19 | .setTimestamp();
20 |
21 | dmChannel.send({embeds: [messageEmbed]});
22 | }
23 |
24 | if (command === 'report') {
25 | const reportArgs = args.join(' ');
26 | if (message.guild) return message.react('❎') && message.channel.send('**Declined**');
27 | if (!args[0]) return message.channel.send('**Berikan args**');
28 | if (reportCooldown.has(message.author.id)) {
29 | return message.channel.send('**Kamu telah mengirimkan laporan hari ini, silahkan kirim laporan lain besok.**') && message.react('❎');
30 | } else {
31 | const embedpreview = new MessageEmbed()
32 | .setColor('#ff0000')
33 | .setTitle('Report preview')
34 | .setDescription(`Nama : **${message.author.username}**\nReport ID : **${message.id}**\n\nBug : **${reportArgs}**`)
35 | .setFooter({text: `Direquest oleh ${message.author.username}`, iconURL: message.author.avatarURL({format : 'png', dynamic : true, size : 1024})})
36 | .setTimestamp();
37 | message.channel.send({embeds: [embedpreview]});
38 | message.channel.send('**Please confirm your choice**\n\`\`\`[Yes] or [No]\`\`\`');
39 | const collector = new MessageCollector(message.channel, m => m.author.id === message.author.id, { time: 10000 });
40 | collector.on('collect', message => {
41 | const msgct = message.content.toLowerCase();
42 | if (msgct === 'yes') {
43 | reportCooldown.add(message.author.id);
44 | setTimeout(() => {
45 | reportCooldown.delete(message.author.id);
46 | }, 86400000);
47 | const channeltarget = client.channels.cache.get(process.env.CHANNELLOGPRIVATE);
48 | channeltarget.send(reportArgs);
49 | message.react('✅');
50 |
51 | const channelLog = client.channels.cache.get(process.env.CHANNELLOGID);
52 | const channelLogEmbed = new MessageEmbed()
53 |
54 | .setColor('#ff0000')
55 | .setTitle('Report preview')
56 | .setDescription(`Nama : **${message.author.username}**\nReport ID : **${message.id}**\n\nBug : **${reportArgs}**`)
57 | .setFooter({text: message.author.username, iconURL: message.author.avatarURL({format : 'png', dynamic : true, size : 1024})})
58 | .setTimestamp();
59 |
60 | channelLog.send({embeds: [channelLogEmbed]});
61 | message.channel.send(`**Reported**\n\`\`\`Report ID : ${message.id}\`\`\``);
62 | collector.stop();
63 | } else if (msgct === 'no') {
64 | message.channel.send('**Canceled**');
65 | collector.stop();
66 | }
67 | });
68 | }
69 | }
70 |
71 | });
72 |
--------------------------------------------------------------------------------
/src/commands/interaction/genshin.js:
--------------------------------------------------------------------------------
1 | const genshindb = require('genshin-db');
2 | const { SlashCommandBuilder } = require('@discordjs/builders');
3 | const { MessageEmbed } = require('discord.js');
4 | genshindb.setOptions({v4Prop: true});
5 |
6 | module.exports = {
7 | data: new SlashCommandBuilder()
8 | .setName('genshin')
9 | .setDescription('Genshin impact')
10 | .addStringOption(characters =>
11 | characters.setName('characters')
12 | .setDescription('Characters name')
13 | )
14 | .addStringOption(weapon =>
15 | weapon.setName('weapon')
16 | .setDescription('Weapon name')
17 | ),
18 | /**
19 | * @param {import("../../../client").interaction} interaction
20 | * @param {import("../../../client").client} client
21 | */
22 | async execute(interaction) {
23 | if (interaction.options.get('weapon')) {
24 | const data = genshindb.weapons(interaction.options.get('weapon').value);
25 | const moracosts = data.costs.ascend1[0].count + data.costs.ascend2[0].count + data.costs.ascend3[0].count + data.costs.ascend4[0].count + data.costs.ascend5[0].count + data.costs.ascend6[0].count;
26 |
27 | const embed = new MessageEmbed()
28 |
29 | .setColor('#89e0dc')
30 | .setTitle(data.name)
31 | .setDescription(data.description)
32 | .setThumbnail(data.images.mihoyo_icon)
33 | .addFields(
34 | { name: 'Weapon', value: `${data.weaponText}`, inline: true },
35 | { name: 'Rarity', value: `${data.rarity}✰`, inline: true },
36 | { name: 'Substat', value: `${data.mainStatText}`, inline: true },
37 | { name: 'Refine', value: `${data.r1.description}`, inline: true },
38 | { name: 'Material', value: `${data.costs.ascend6[0].name + ', ' + data.costs.ascend6[1].name + ', ' + data.costs.ascend6[2].name}`, inline: true },
39 | { name: 'Costs', value: `${moracosts}`, inline: true }
40 | )
41 | .setFooter({text: `Direquest oleh ${interaction.member.nickname || interaction.user.username}`, iconURL: interaction.user.avatarURL({format : 'png', dynamic : true, size : 1024})})
42 | .setTimestamp();
43 | interaction.reply({embeds: [embed]});
44 | } else if (interaction.options.get('characters')) {
45 | const data = genshindb.characters(interaction.options.get('characters').value);
46 | const moracosts = data.costs.ascend1[0].count + data.costs.ascend2[0].count + data.costs.ascend3[0].count + data.costs.ascend4[0].count + data.costs.ascend5[0].count + data.costs.ascend6[0].count;
47 |
48 | const embed = new MessageEmbed()
49 |
50 | .setColor('#89e0dc')
51 | .setTitle(data.name)
52 | .setDescription(data.description)
53 | .setThumbnail(data.images.mihoyo_icon)
54 | .addFields(
55 | { name: 'Weapon', value: `${data.weaponText}`, inline: true },
56 | { name: 'Vision', value: `${data?.elementText || '?'}`, inline: true },
57 | { name: 'Rarity', value: `${data.rarity}✰`, inline: true },
58 | { name: 'Substat', value: `${data.substatText}`, inline: true },
59 | { name: 'Region', value: `${data?.region || '?'}`, inline: true },
60 | { name: 'Birthday', value: `${data?.birthday || '?'}`, inline: true },
61 | { name: 'Material', value: `${data.costs.ascend6[0].name + ', ' + data.costs.ascend6[1].name + ', ' + data.costs.ascend6[2].name + ', ' + data.costs.ascend6[3].name + ', ' + (data.costs.ascend6[4]?.name || '-')}`, inline: true },
62 | { name: 'Costs', value: `${moracosts}`, inline: true }
63 | )
64 | .setFooter({text: `Direquest oleh ${interaction.member.nickname || interaction.user.username}`, iconURL: interaction.user.avatarURL({format : 'png', dynamic : true, size : 1024})})
65 | .setTimestamp();
66 |
67 | interaction.reply({embeds: [embed]});
68 | } else {
69 | interaction.reply('**Pilih salah satu option yang disediakan**');
70 | }
71 | }
72 | };
73 |
--------------------------------------------------------------------------------
/src/commands/interaction/help.js:
--------------------------------------------------------------------------------
1 | const { SlashCommandBuilder } = require('@discordjs/builders');
2 | const { MessageEmbed, MessageActionRow, MessageButton } = require('discord.js');
3 | const prefix = process.env.PREFIX;
4 |
5 | module.exports = {
6 | data: new SlashCommandBuilder()
7 | .setName('help')
8 | .setDescription('Help command'),
9 | /**
10 | * @param {import("../../../client").interaction} interaction
11 | * @param {import("../../../client").client} client
12 | */
13 | async execute(interaction, client) {
14 | const msgEmbed = new MessageEmbed()
15 |
16 | .setColor('#89e0dc')
17 | .setTitle('Help commands')
18 | .setDescription(`Prefix = **${prefix}**`)
19 | .addFields(
20 | { name: 'General command', value: 'ping, userinfo, serverinfo, osu, avatar, stats, afk, mal, genshin, weather' },
21 | { name: 'DM command', value: 'report' },
22 | { name: 'Moderator command', value: 'nickname' },
23 | { name: 'Admin command', value: 'warn, kick, ban, mute, unmute, user, add, reroll, end, eval'}
24 | )
25 | .setFooter({text: `Direquest oleh ${interaction.member.nickname || interaction.user.username}`, iconURL: interaction.user.avatarURL({format : 'png', dynamic : true, size : 1024})})
26 | .setTimestamp();
27 |
28 | const button = new MessageActionRow()
29 | .addComponents(
30 | new MessageButton()
31 | .setCustomId('ping')
32 | .setLabel('Ping')
33 | .setStyle('PRIMARY')
34 | )
35 | .addComponents(
36 | new MessageButton()
37 | .setCustomId('userinfo')
38 | .setLabel('User Info')
39 | .setStyle('SECONDARY')
40 | )
41 | .addComponents(
42 | new MessageButton()
43 | .setCustomId('avatar')
44 | .setLabel('Avatar')
45 | .setStyle('SECONDARY')
46 | );
47 |
48 | const btnFilter = i => i.user.id === interaction.user.id;
49 | const collector = interaction.channel.createMessageComponentCollector({ filter: btnFilter, time: 60000 });
50 |
51 | collector.on('collect', async i => {
52 |
53 | if (i.customId === 'ping') {
54 | button.components[0].setDisabled(true);
55 | button.components[1].setDisabled(true);
56 | button.components[2].setDisabled(true);
57 | interaction.editReply({components: [button]});
58 | await i.reply({content: `Pong !! \`${client.ws.ping}ms.\` Latensi \`${Date.now() - i.createdTimestamp}ms.\``});
59 | collector.stop();
60 | }
61 |
62 | if (i.customId === 'userinfo') {
63 | button.components[0].setDisabled(true);
64 | button.components[1].setDisabled(true);
65 | button.components[2].setDisabled(true);
66 | interaction.editReply({components: [button]});
67 | const userInfoEmbed = new MessageEmbed()
68 |
69 | .setColor('#89e0dc')
70 | .setTitle(`${interaction.user.username} Info`)
71 | .setThumbnail(`${interaction.user.avatarURL({format : 'png', dynamic : true, size : 4096})}`)
72 | .setDescription(`Username : **${interaction.user.username}**\n\nNickname : **${interaction.member.nickname || interaction.user.username}**\n\nID : **${interaction.user.id}**\n\nTanggal dibuatnya akun : **${interaction.user.createdAt}**\n\nTanggal join server : **${interaction.member.joinedAt}**\n\nRole : **<@&${interaction.member.roles.highest.id}>**`)
73 | .setFooter({text: `Direquest oleh ${interaction.member.nickname || interaction.user.username}`, iconURL: interaction.user.avatarURL({format : 'png', dynamic : true, size : 1024})})
74 | .setTimestamp();
75 |
76 | await i.reply({embeds: [userInfoEmbed]});
77 | collector.stop();
78 | }
79 |
80 | if (i.customId === 'avatar') {
81 | button.components[0].setDisabled(true);
82 | button.components[1].setDisabled(true);
83 | button.components[2].setDisabled(true);
84 | interaction.editReply({components: [button]});
85 | const avatarEmbed = new MessageEmbed()
86 |
87 | .setColor('#89e0dc')
88 | .setTitle('Avatar')
89 | .setDescription(`Avatarnya ${interaction.user.username}`)
90 | .setImage(`${interaction.user.avatarURL({format : 'png', dynamic : true, size : 4096})}`)
91 | .setFooter({text: `Direquest oleh ${interaction.member.nickname || interaction.user.username}`, iconURL: interaction.user.avatarURL({format : 'png', dynamic : true, size : 1024})});
92 |
93 | await i.reply({embeds: [avatarEmbed]});
94 | collector.stop();
95 | }
96 |
97 | collector.on('end', collected => console.log(collected.size));
98 |
99 | });
100 |
101 | interaction.reply({embeds: [msgEmbed], components: [button]});
102 | setTimeout(() => {
103 | button.components[0].setDisabled(true);
104 | button.components[1].setDisabled(true);
105 | button.components[2].setDisabled(true);
106 | button.components[3].setDisabled(true);
107 | interaction.editReply({components: [button]});
108 | collector.stop();
109 | }, 60000);
110 | }
111 | };
112 |
--------------------------------------------------------------------------------
/src/structures/presenceUpdate.js:
--------------------------------------------------------------------------------
1 | const { client } = require('../../client');
2 |
3 | const getEnv = process.env;
4 |
5 | const removerole = member => {
6 | return member.roles.remove([getEnv.activityRole1, getEnv.activityRole2, getEnv.activityRole3, getEnv.activityRole4, getEnv.activityRole5, getEnv.activityRole6]);
7 | };
8 |
9 | client.on('presenceUpdate', async (updatePresence, newPresence) => {
10 |
11 | const cacheId = updatePresence.guild.roles.cache;
12 |
13 | if (!cacheId.get(getEnv.activityRole1 || getEnv.activityRole2 || getEnv.activityRole3 || getEnv.activityRole4 || getEnv.activityRole5 || getEnv.activityRole6)) return;
14 |
15 | setTimeout(() => {
16 | const presence0 = newPresence?.member?.presence?.activities[0];
17 | const presence1 = newPresence?.member?.presence?.activities[1];
18 |
19 | if (newPresence?.user.bot == false) {
20 | switch (presence0?.name) {
21 | case 'Custom Status':
22 | switch (presence1?.name) {
23 | case 'Honkai: Star Rail':
24 | if (newPresence.member.roles.cache.get(getEnv.activityRole1)) return;
25 | removerole(newPresence.member).then(() => {
26 | newPresence.member.roles.add(getEnv.activityRole1);
27 | });
28 | break;
29 | case 'Genshin Impact':
30 | if (newPresence.member.roles.cache.get(getEnv.activityRole2)) return;
31 | removerole(newPresence.member).then(() => {
32 | newPresence.member.roles.add(getEnv.activityRole2);
33 | });
34 | break;
35 | case 'osu!':
36 | if (newPresence.member.roles.cache.get(getEnv.activityRole3)) return;
37 | removerole(newPresence.member).then(() => {
38 | newPresence.member.roles.add(getEnv.activityRole3);
39 | });
40 | break;
41 | case 'VALORANT':
42 | if (newPresence.member.roles.cache.get(getEnv.activityRole4)) return;
43 | removerole(newPresence.member).then(() => {
44 | newPresence.member.roles.add(getEnv.activityRole4);
45 | });
46 | break;
47 | case 'Counter-Strike 2':
48 | if (newPresence.member.roles.cache.get(getEnv.activityRole5)) return;
49 | removerole(newPresence.member).then(() => {
50 | newPresence.member.roles.add(getEnv.activityRole5);
51 | });
52 | break;
53 | case 'Spotify':
54 | if (newPresence.member.roles.cache.get(getEnv.activityRole6)) return;
55 | removerole(newPresence.member).then(() => {
56 | newPresence.member.roles.add(getEnv.activityRole6);
57 | });
58 | break;
59 | default:
60 | removerole(newPresence.member);
61 | break;
62 | }
63 | break;
64 | case 'Honkai: Star Rail':
65 | if (newPresence.member.roles.cache.get(getEnv.activityRole1)) return;
66 | removerole(newPresence.member).then(() => {
67 | newPresence.member.roles.add(getEnv.activityRole1);
68 | });
69 | break;
70 | case 'Genshin Impact':
71 | if (newPresence.member.roles.cache.get(getEnv.activityRole2)) return;
72 | removerole(newPresence.member).then(() => {
73 | newPresence.member.roles.add(getEnv.activityRole2);
74 | });
75 | break;
76 | case 'osu!':
77 | if (newPresence.member.roles.cache.get(getEnv.activityRole3)) return;
78 | removerole(newPresence.member).then(() => {
79 | newPresence.member.roles.add(getEnv.activityRole3);
80 | });
81 | break;
82 | case 'VALORANT':
83 | if (newPresence.member.roles.cache.get(getEnv.activityRole4)) return;
84 | removerole(newPresence.member).then(() => {
85 | newPresence.member.roles.add(getEnv.activityRole4);
86 | });
87 | break;
88 | case 'Counter-Strike 2':
89 | if (newPresence.member.roles.cache.get(getEnv.activityRole5)) return;
90 | removerole(newPresence.member).then(() => {
91 | newPresence.member.roles.add(getEnv.activityRole5);
92 | });
93 | break;
94 | case 'Spotify':
95 | if (newPresence.member.roles.cache.get(getEnv.activityRole6)) return;
96 | removerole(newPresence.member).then(() => {
97 | newPresence.member.roles.add(getEnv.activityRole6);
98 | });
99 | break;
100 | default:
101 | removerole(newPresence.member);
102 | break;
103 | }
104 | } else {
105 | return;
106 | }
107 | }, 1000);
108 |
109 | });
110 |
--------------------------------------------------------------------------------