Last active
September 20, 2022 10:14
-
-
Save iamnotacoder-djs/e3a146945d58eae2a2a3c91214039ca8 to your computer and use it in GitHub Desktop.
Discord.js@14.3.0 Autocomplete Option Example
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
* Пример использования 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 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
* Пример использования 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