Skip to content

Instantly share code, notes, and snippets.

@iamnotacoder-djs
Last active September 20, 2022 10:14
Show Gist options
  • Save iamnotacoder-djs/e3a146945d58eae2a2a3c91214039ca8 to your computer and use it in GitHub Desktop.
Save iamnotacoder-djs/e3a146945d58eae2a2a3c91214039ca8 to your computer and use it in GitHub Desktop.
Discord.js@14.3.0 Autocomplete Option Example
/**
* Пример использования Autocomplete-опции Slash-команды на базе шаблона (хандлера) DiscordBotIda:
* https://github.com/idaspin/DiscordBotIda/
* Установка: установить модуль rss-parser; Перенести файл Habrahabr.js в папку /commands/
*/
'use strict';
const BaseCommand = require('../structures/BaseCommand'),
{ ApplicationCommandType, ApplicationCommandOptionType, AttachmentBuilder, EmbedBuilder, Collection } = require('discord.js'),
Parser = require('rss-parser'),
parser = new Parser();
class Habrahabr extends BaseCommand {
name = "habrahabr";
usage = "Habrahabr feed search";
type = [ Config.CommandType.SLASH_APPLICATION ];
slash = {
name: this.name,
description: this.usage,
type: ApplicationCommandType.ChatInput,
options: [
{
name: "request",
description: "Request field",
type: ApplicationCommandOptionType.String,
autocomplete: true,
required: true,
nameLocalizations: {
"ru": "запрос",
"uk": "запит",
"en-US": "request",
"en-GB": "request"
},
descriptionLocalizations: {
"ru": "Поле запроса",
"uk": "Поле запиту",
"en-US": "Request field",
"en-GB": "Request field"
}
}
],
nameLocalizations: {
"ru": "хабр",
"uk": "хабр",
"en-US": "habrahabr",
"en-GB": "habrahabr"
},
descriptionLocalizations: {
"ru": "Поиск по ленте Хабрахабра",
"uk": "Пошук стрічки Хабрахабр",
"en-US": "Habrahabr feed search",
"en-GB": "Habrahabr feed search"
}
};
data = new Collection();
constructor() {
super();
this.loadData();
}
async loadData() {
let feed = await parser.parseURL('http://habrahabr.ru/rss/news');
for (let item of feed.items) {
let id = item.guid.match(/\d/g)?.join('');
item.id = id;
this.data.set(id, item);
}
}
async autocomplete(client, interaction) {
const focusedValue = interaction.options.getFocused().toLowerCase();
if (focusedValue.length == 0) return await interaction.respond([]);
const rankedIndex = this.data.map((entry) => {
let points = 0;
if (entry.title.toLowerCase() == focusedValue) {
points += 100;
}
if (entry.title.toLowerCase().startsWith(focusedValue)) {
points += 20;
}
if (entry.contentSnippet.toLowerCase().startsWith(focusedValue)) {
points += 10;
}
if (entry.title.toLowerCase().includes(` ${focusedValue}`)) {
points += 2;
}
if (entry.contentSnippet.toLowerCase().includes(` ${focusedValue}`)) {
points += 1;
}
return {...entry, points};
})
.filter((a) => a.points != 0) // Отсекаем статьи без совпадений
.sort((a, b) => b.points - a.points) // Сортируем
.map((m) => ({ name: m.title.substring(0, 100), value: m.id })) // Готовим Respond
.slice(0, 25); // Отсекаем лишние опции
await interaction.respond(rankedIndex);
}
async execute(client, command) {
const m = this.data.get(command.options.getString("request"));
if (!m) {
return command.reply({
content: `Ничего не найдено`,
ephemeral: true
});
}
command.reply({
embeds: [
new EmbedBuilder()
.setTitle(m.title)
.setDescription(m.contentSnippet.replace('Читать далее', `[Читать далее](${m.guid})`))
.setURL(m.guid)
.setColor(Config.embed_color)
]
});
}
}
module.exports = Habrahabr
/**
* Пример использования Autocomplete-опции Slash-команды в рамках кода "Бот в одном файле".
*/
const { Client, EmbedBuilder, IntentsBitField, SlashCommandBuilder, SlashCommandStringOption, InteractionType } = require("discord.js"), // ^14.3.0
client = new Client({
intents: [ IntentsBitField.Flags.Guilds, IntentsBitField.Flags.GuildMessages, IntentsBitField.Flags.DirectMessages ]
});
const articles = [
{
author: "777621732231348254",
image: 'https://avatars.dzeninfra.ru/get-zen_doc/5231833/pub_62da870ac9ee5c0a87a8f8e8_62da87748708be14cbc8fa72/scale_2400',
title: 'Кнопка «Добавить на сервер» для бота',
text: `Технически, эта кнопка является не более чем обычной ссылкой на любой удобный создателю данного бота сайт. Текст кнопки изменить нельзя.
Так сообщение гласит “Добавить бота на сервер”, чтобы не получить блокировку и не обманывать ожидания пользователей стоит поместить в кнопку: либо обычную инвайт-ссылку. Либо официальный сайт бота.
Заходим на [Discord Developers Portal](https://discord.com/developers/applications).
Во вкладке OAuth2 находим подзаголовок Default Auth Link. В выпадающем-меню метода установки нажимаем Custom URL, и вводим в появившееся поле текста нужную нам ссылку.
Если твоя задача — просто пригласить бота на сервер по нажатию на кнопку. Есть более удобный способ это сделать: In-app Auth. Здесь с помощью чек-боксов задаешь scope’s бота: bot - добавление бот-аккаунта в гильдию и ~~application.commands - доступ к созданию Slash и Контекстных команд.~~ Ну и настраиваешь Permissions (привилегии бота на сервере).
Используя эту возможность, ты можешь освободить немного лишнего места из описания бота и поместить в био более важную информацию.`,
timestamp: '1637586376'
},
{
author: "370432461475151873",
title: 'JS > Полезные ссылки',
text: `\`Ниже находятся ссылки на различную документацию, связанную с js/node.js/discord.js\`
[Учебник по самому языку на русском](https://learn.javascript.ru/)
[Раздел про регулярные выражения](https://learn.javascript.ru/regular-expressions)
[Разделы для того, чтобы сделать "кулдаун"
setTimeout и setInterval](https://learn.javascript.ru/settimeout-setinterval)
[Map и Set](https://learn.javascript.ru/map-set)
[Классы](https://learn.javascript.ru/classes)
[Как стать настоящим ниндзя (особенно полезно, если вы будете просить помощи с вашим кодом)](https://learn.javascript.ru/ninja-code)
[Документация по языку](https://developer.mozilla.org/ru/docs/Web/JavaScript)
[Протестировать регулярные выражения и шпора](https://regex101.com/)
[Документация по Node.js](https://nodejs.org/ru/docs/)
[Документация для самой используемой библиотеки для discord api на JavaScript](https://discord.js.org/#/docs/main/stable/general/welcome)
[Примеры и гайды по библиотеке](https://discordjs.guide/)
[Ограничения дискорда](https://discord.com/developers/docs/resources/channel#embed-limits%3E) `,
timestamp: '1641301576'
},
{
author: "406028548034396160",
title: 'TypeScript > Полезные ссылки',
text: `\`Примечание: прежде чем изучать TypeScript, изучите основы JavaScript.\`
[Официальный сайт](https://www.typescriptlang.org/)
[Установка](https://www.typescriptlang.org/download)
[Документация (русский)](http://typescript-lang.ru/docs/)
[Документация (английский)](https://www.typescriptlang.org/docs)
[Книга (русский)](https://typescript-definitive-guide.ru/pdf/tdg.pdf)
[Поиграться с языком](https://www.typescriptlang.org/play)
[Сервер](https://discord.gg/typescript)
[Основы языка (русский, текстовый)]( https://tproger.ru/translations/course-on-typescript/)
[Основы языка (русский, видео)](https://youtu.be/nyIpDs2DJ_c)
[Основы языка (английский, видео)](https://youtu.be/d56mG7DezGs)
[Продвинутый уровень (русский, видео)](https://youtu.be/7NU6K4170As)
[Задачки на типы](https://github.com/type-challenges/type-challenges)`,
timestamp: '1655298376'
},
{
author: "431904802918891531",
title: 'Форматирование временных меток в Discord',
text: `Для создания интерактивных временных меток используй тег: \`<t:TIMESTAMP:FLAG>\`
**Доступные флаги (FLAG)**
> t: Short time (напр. 9:41)
> T: Long Time (напр. 9:41:30)
> d: Short Date (напр. 06.122021)
> D: Long Date (напр. 30 Октября 2021)
> f (по умолчанию): Short Date/Time (напр. 30 Октября 2021 9:41)
> F: Long Date/Time (напр. воскресенье, 10 октября 2021 г., 16:13)
> R: Относительное время (напр. 2 месяца назад, 31 минуту назад)
<t:1633871583:F>
\`<t:1633871583:F>\`
Если используешь timestamp, полученный от Discord.js или из класса Date (напр. \`Date.now()\`), необходимо извлечь миллисекунды из числа: \`\`\`js${"\nconst date = Math.round(Date.now() / 1000);\nchannel.send(`${date}`);"}\`\`\`
Хотя код можно уместить и в одну строку:
\`\`\`js${"\nchannel.send(`${~~(Date.now()/1000)}`);"}\`\`\`
[Онлайн конвертер даты для Discord-разметки](http://iamnotacoder.ru/discord-datetime/)`,
timestamp: '1656680776'
}
];
client.login("TOKEN")
.then(() => {
client.application.commands.set([
new SlashCommandBuilder()
.setName('articles')
.setDescription('Article search')
.addStringOption(
new SlashCommandStringOption()
.setName('request')
.setDescription('Request field')
.setRequired(true)
.setAutocomplete(true)
)
]);
});
client.on('interactionCreate', (interaction) => {
if ((interaction.isChatInputCommand() || interaction.isContextMenuCommand() || interaction?.type == InteractionType.ApplicationCommandAutocomplete)) {
if (interaction.commandName === "articles") {
if (interaction?.type == InteractionType.ApplicationCommandAutocomplete) {
const focusedValue = interaction.options.getFocused();
let filtered = articles.filter(choice => choice.title.includes(focusedValue) || choice.text.includes(focusedValue));
filtered = filtered.map(choice => ({ name: choice.title, value: choice.timestamp }));
interaction.respond(filtered.slice(0, 25));
}
if (interaction.isChatInputCommand()) {
let timestamp = interaction.options.getString("request"),
article = articles.find((v) => v.timestamp === timestamp),
reply = {
embeds: [
new EmbedBuilder()
.setColor("#FFFFFF")
.setTitle(article.title)
.setDescription(`${article.text}${Number.isInteger(article.timestamp) ? ` \n\n Автор: <@${article.author}>` : ``}`)
.setTimestamp(parseInt(article.timestamp) * 1000)
.setImage(article.image == '' ? null: article.image)
]
};
interaction.reply(reply);
}
}
}
});
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment