|
1 | 1 | import { SlashCommandBuilder } from "@discordjs/builders"; |
2 | 2 | import { deleteButton } from "../../utils/CommandUtils"; |
3 | | -import { MessageActionRow, MessageEmbed } from "discord.js"; |
| 3 | +import { MessageActionRow, MessageEmbed, MessageSelectMenu } from "discord.js"; |
4 | 4 | import { gunzipSync } from "zlib"; |
5 | 5 | import { XMLParser } from "fast-xml-parser"; |
6 | 6 | import { Command } from "../../interfaces"; |
@@ -34,53 +34,79 @@ const command: Command = { |
34 | 34 | .setRequired(true), |
35 | 35 | ), |
36 | 36 | async execute(interaction) { |
37 | | - const deleteButtonRow = new MessageActionRow().addComponents([deleteButton]); |
| 37 | + const deleteButtonRow = new MessageActionRow().addComponents([deleteButton(interaction.user.id)]); |
38 | 38 | const query = interaction.options.getString("query"); |
39 | 39 | const { index, sitemap } = await getSources(); |
40 | 40 | const search: string[] = index.search(query, { limit: 10 }).map((id) => sitemap[<number>id].loc); |
41 | 41 | const embed = new MessageEmbed() |
42 | 42 | .setColor(MDN_BLUE_COLOR) |
43 | 43 | .setAuthor({ name: "MDN Documentation", iconURL: MDN_ICON_URL }) |
44 | | - .setTitle(`Search for: ${query}`); |
| 44 | + .setTitle(`Search for: ${query.slice(0, 243)}`); |
45 | 45 |
|
46 | 46 | if (!search.length) { |
47 | 47 | embed.setColor(0xff0000).setDescription("No results found..."); |
48 | | - interaction.editReply({ embeds: [embed], components: [deleteButtonRow] }); |
| 48 | + await interaction.reply({ embeds: [embed], ephemeral: true }); |
49 | 49 | return; |
50 | | - } |
| 50 | + } else if (search.length === 1) { |
| 51 | + const resultEmbed = await getSingleMDNSearchResults(search[0]); |
| 52 | + await interaction |
| 53 | + .reply({ |
| 54 | + embeds: [resultEmbed], |
| 55 | + components: [deleteButtonRow], |
| 56 | + }) |
| 57 | + .catch(console.error); |
51 | 58 |
|
52 | | - if (search.length === 1) { |
53 | | - const res = await fetch(`${MDN_BASE_URL + search[0]}/index.json`); |
54 | | - const doc: MdnDoc = (await res.json()).doc; |
55 | | - const docEmbed = embed |
56 | | - .setColor(0xffffff) |
57 | | - .setTitle(doc.pageTitle) |
58 | | - .setURL(`https://developer.mozilla.org/${doc.mdn_url}`) |
59 | | - .setThumbnail(this.MDN_ICON_URL) |
60 | | - .setDescription(doc.summary); |
61 | | - interaction.editReply({ embeds: [docEmbed], components: [deleteButtonRow] }); |
62 | 59 | return; |
63 | | - } |
| 60 | + } else { |
| 61 | + const results = search.map((path) => `**• [${path.replace(/_|-/g, " ")}](${MDN_BASE_URL}${path})**`); |
64 | 62 |
|
65 | | - const results = search.map((path) => `**• [${path.replace(/_|-/g, " ")}](${MDN_BASE_URL}${path})**`); |
66 | | - embed.setDescription(results.join("\n")); |
67 | | - interaction.editReply({ embeds: [embed], components: [deleteButtonRow] }); |
68 | | - return; |
| 63 | + embed.setDescription(results.join("\n")); |
| 64 | + const selectMenuRow = new MessageActionRow().addComponents( |
| 65 | + new MessageSelectMenu() |
| 66 | + .setCustomId("mdnselect/" + interaction.user.id) |
| 67 | + .addOptions( |
| 68 | + search.map((val) => { |
| 69 | + const parsed = val.length >= 99 ? val.split("/").at(-1) : val; |
| 70 | + return { label: parsed, value: parsed }; |
| 71 | + }), |
| 72 | + ) |
| 73 | + .setPlaceholder("Select documentation to send"), |
| 74 | + ); |
| 75 | + await interaction |
| 76 | + .reply({ |
| 77 | + content: "Didn't find an exact match, please select one from below", |
| 78 | + ephemeral: true, |
| 79 | + components: [selectMenuRow], |
| 80 | + }) |
| 81 | + .catch(console.error); |
| 82 | + return; |
| 83 | + } |
69 | 84 | }, |
70 | 85 | }; |
71 | 86 |
|
| 87 | +export async function getSingleMDNSearchResults(searchQuery: string) { |
| 88 | + const res = await fetch(`${MDN_BASE_URL + searchQuery}/index.json`); |
| 89 | + const doc: MdnDoc = (await res.json()).doc; |
| 90 | + |
| 91 | + return new MessageEmbed() |
| 92 | + .setColor(MDN_BLUE_COLOR) |
| 93 | + .setAuthor({ name: "MDN Documentation", iconURL: MDN_ICON_URL }) |
| 94 | + .setColor(0xffffff) |
| 95 | + .setTitle(doc.pageTitle) |
| 96 | + .setURL(`https://developer.mozilla.org/${doc.mdn_url}`) |
| 97 | + .setThumbnail(MDN_ICON_URL) |
| 98 | + .setDescription(doc.summary); |
| 99 | +} |
72 | 100 | async function getSources(): Promise<typeof sources> { |
73 | 101 | if (sources.lastUpdated && Date.now() - sources.lastUpdated < 43200000 /* 12 hours */) return sources; |
74 | 102 |
|
75 | 103 | const res = await fetch("https://developer.mozilla.org/sitemaps/en-us/sitemap.xml.gz"); |
76 | 104 | if (!res.ok) return sources; // Fallback to old sources if the new ones are not available for any reason |
77 | | - |
78 | | - const sitemap: Sitemap<number> = new XMLParser() |
79 | | - .parse(gunzipSync(await res.buffer()).toString()) |
80 | | - .urlset.url.map((entry: SitemapEntry<string>) => ({ |
81 | | - loc: entry.loc.slice(MDN_BASE_URL.length), |
82 | | - lastmod: new Date(entry.lastmod).valueOf(), |
83 | | - })); |
| 105 | + const something = new XMLParser().parse(gunzipSync(await res.buffer()).toString()); |
| 106 | + const sitemap: Sitemap<number> = something.urlset.url.map((entry: SitemapEntry<string>) => ({ |
| 107 | + loc: entry.loc.slice(MDN_BASE_URL.length), |
| 108 | + lastmod: new Date(entry.lastmod).valueOf(), |
| 109 | + })); |
84 | 110 |
|
85 | 111 | const index = new flexsearch.Index(); |
86 | 112 | sitemap.forEach((entry, idx) => index.add(idx, entry.loc)); |
|
0 commit comments