Skip to content

Commit 0e5b4f6

Browse files
committed
Add material command
1 parent 0bbd5c2 commit 0e5b4f6

4 files changed

Lines changed: 5309 additions & 1 deletion

File tree

src/commands/misc/material.ts

Lines changed: 160 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,160 @@
1+
import { AutocompleteInteraction, CommandInteraction, Message, MessageEmbed } from "discord.js"
2+
import config from "../../data/config.json"
3+
import client from "../../main"
4+
import Command from "../../utils/Command"
5+
import { CommandSource, Material, SendMessage } from "../../utils/Types"
6+
import { Bookmarkable, Colors, findFuzzyBestCandidates, getLinkToGuide, paginator, sendMessage, simplePaginator } from "../../utils/Utils"
7+
8+
export default class MaterialCommand extends Command {
9+
constructor(name: string) {
10+
super({
11+
name,
12+
category: "Misc",
13+
usage: "material [name]",
14+
help: `Displays material information. If no name is provided, a list of all materials will be displayed.
15+
16+
Note: this command supports fuzzy search.`,
17+
aliases: ["mat"],
18+
options: [{
19+
name: "name",
20+
description: "Material name",
21+
type: "STRING",
22+
autocomplete: true,
23+
required: false
24+
}]
25+
})
26+
}
27+
28+
async autocomplete(source: AutocompleteInteraction): Promise<void> {
29+
const targetNames = Object.keys(client.data.materials)
30+
const search = source.options.getFocused().toString()
31+
32+
if (search == "") {
33+
return await source.respond([
34+
{ name: "List all materials", value: "" },
35+
...targetNames.filter((_, i) => i < 19).map(value => {
36+
return { name: value, value }
37+
})
38+
])
39+
}
40+
41+
await source.respond(findFuzzyBestCandidates(targetNames, search, 20).map(value => {
42+
return { name: value, value }
43+
}))
44+
}
45+
46+
async runInteraction(source: CommandInteraction): Promise<SendMessage | undefined> {
47+
return this.run(source, (source.options.getString("name") ?? "").split(/ +/g))
48+
49+
}
50+
async runMessage(source: Message, args: string[]): Promise<SendMessage | undefined> {
51+
return this.run(source, args)
52+
}
53+
54+
async run(source: CommandSource, args: string[]): Promise<SendMessage | undefined> {
55+
const { data } = client
56+
57+
const name = args.join(" ")
58+
if (name.length == 0) {
59+
const pages = this.getMaterialsPages()
60+
if (pages.length == 0) return sendMessage(source, "No material data loaded")
61+
62+
await simplePaginator(source, (relativePage, currentPage, maxPages) => this.getMaterialsPage(pages, relativePage, currentPage, maxPages), pages.length)
63+
return undefined
64+
}
65+
66+
const material = data.getMaterialByName(name)
67+
if (material == undefined)
68+
return sendMessage(source, "Unable to find material")
69+
70+
const pages: Bookmarkable[] = [{
71+
bookmarkEmoji: "📝",
72+
bookmarkName: "General",
73+
maxPages: 1,
74+
pages: (rp, cp, mp) => this.getMainMaterialPage(material, rp, cp, mp)
75+
}]
76+
if (material.longDesc)
77+
pages.push({
78+
bookmarkEmoji: "-",
79+
bookmarkName: "Lore",
80+
maxPages: 1,
81+
pages: (rp, cp, mp) => this.getLoreMaterialPage(material, rp, cp, mp),
82+
invisible: true
83+
})
84+
85+
await paginator(source, pages)
86+
return undefined
87+
}
88+
89+
90+
getMaterialsPages(): string[] {
91+
const { data } = client
92+
const materials = Object.entries(data.materials)
93+
.map(([name, material]) => `**${material.category}**: ${material.stars?`${material.stars}★ `:""}${data.emoji(name, true)}`)
94+
95+
const pages: string[] = []
96+
let paging = "", c = 0
97+
for (const material of materials) {
98+
if (paging.length + material.length > 1800 || ++c > 15) {
99+
pages.push(paging.trim())
100+
paging = material
101+
c = 1
102+
} else
103+
paging += "\n" + material
104+
}
105+
if (paging.trim().length > 0) pages.push(paging)
106+
return pages
107+
}
108+
109+
getMaterialsPage(pages: string[], relativePage: number, currentPage: number, maxPages: number): MessageEmbed | undefined {
110+
if (relativePage >= pages.length)
111+
return undefined
112+
113+
const embed = new MessageEmbed()
114+
.setTitle("Materials")
115+
.setDescription(pages[relativePage])
116+
.setFooter(`Page ${currentPage} / ${maxPages} - See '${config.prefix}help material' for more info about what you can do`)
117+
.setColor(Colors.GREEN)
118+
119+
return embed
120+
}
121+
122+
getMainMaterialPage(material: Material, relativePage: number, currentPage: number, maxPages: number): MessageEmbed | undefined {
123+
const guides = client.data.getGuides("material", material.name).map(({ guide, page }) => getLinkToGuide(guide, page)).join("\n")
124+
const embed = new MessageEmbed()
125+
.setTitle(`${material.name}: Basic info`)
126+
.setColor(Colors.AQUA)
127+
.setFooter(`Page ${currentPage} / ${maxPages}`)
128+
.setDescription(material.desc)
129+
130+
if (material.category || material.type)
131+
embed.addField("Category", `**${material.category}**: ${material.type}`, true)
132+
133+
if (material.stars)
134+
embed.addField("Rarity", `${material.stars}★`, true)
135+
136+
if (guides)
137+
embed.addField("Guides", guides)
138+
139+
if (material.sources)
140+
embed.addField("Sources", material.sources.join("\n"))
141+
142+
if (material.icon)
143+
embed.setThumbnail(`${client.data.baseURL}${material.icon}`)
144+
145+
return embed
146+
}
147+
148+
getLoreMaterialPage(material: Material, relativePage: number, currentPage: number, maxPages: number): MessageEmbed | undefined {
149+
const embed = new MessageEmbed()
150+
.setColor(Colors.AQUA)
151+
.setFooter(`Page ${currentPage} / ${maxPages}`)
152+
.setTitle(`${material.name}: Description`)
153+
.setDescription(material.longDesc ?? "Unavailable")
154+
155+
if (material.icon)
156+
embed.setThumbnail(`${client.data.baseURL}${material.icon}`)
157+
158+
return embed
159+
}
160+
}

0 commit comments

Comments
 (0)