amyjr/src/commands/musicsearch.ts

106 linhas
3,9 KiB
TypeScript

import {
ActionRowBuilder,
ApplicationIntegrationType, ButtonBuilder, ButtonStyle,
ChatInputCommandInteraction,
InteractionContextType,
MessageFlags,
SlashCommandBuilder,
type MessageActionRowComponentBuilder
} from "discord.js";
import { NO_EXTRA_CONFIG } from "../config.ts";
import { getSongOnPreferredProvider, lobotomizedSongButton, musicCache, nowPlayingView } from "../music.ts";
import * as z from 'zod';
import { hash } from "crypto";
import { declareCommand } from "../command.ts";
const itunesResponseShape = z.object({
results: z.array(z.object({
artistId: z.number(),
artistName: z.string(),
trackViewUrl: z.string(),
trackName: z.string(),
collectionName: z.string(),
collectionCensoredName: z.string().optional(),
censoredTrackName: z.string().optional(),
}))
})
export default declareCommand({
async run(interaction: ChatInputCommandInteraction, config) {
await interaction.deferReply()
const search = interaction.options.getString("search")!
const lobotomized = interaction.options.getBoolean("lobotomized") ?? true
let link = ""
if (search.trim().match(/^https?:\/\//)) {
link = search.trim()
} else {
const paramsObj = { entity: "song", term: search };
const searchParams = new URLSearchParams(paramsObj);
const itunesResponse = await fetch(`https://itunes.apple.com/search?${searchParams.toString()}`);
const itunesJson = await itunesResponse.json();
const itunesinfo = itunesResponseShape.parse(itunesJson);
const itunesSong = itunesinfo.results[0];
link = itunesSong.trackViewUrl
}
let preferredApi, songlink, isCached = false
if (musicCache[link]) {
preferredApi = musicCache[link].preferredApi
songlink = musicCache[link].songlink
isCached = true
} else {
songlink = await fetch(`https://api.song.link/v1-alpha.1/links?url=${link}`).then(a => a.json())
preferredApi = getSongOnPreferredProvider(songlink, link)!
}
if (lobotomized) {
const emoji = await interaction.client.application.emojis.create({
attachment: preferredApi.thumbnailUrl,
name: hash("md5", preferredApi.thumbnailUrl),
});
const components = [
new ActionRowBuilder<MessageActionRowComponentBuilder>()
.addComponents(
new ButtonBuilder()
.setStyle(ButtonStyle.Secondary)
.setLabel("expand")
.setCustomId(link),
),
];
await interaction.followUp({
content: `### ${preferredApi.title} ${emoji}\n-# by ${preferredApi.artist}`,
components,
})
await emoji.delete()
return
}
const components = nowPlayingView(songlink, preferredApi)
await interaction.followUp({
components,
flags: [MessageFlags.IsComponentsV2],
})
},
button: lobotomizedSongButton,
dependsOn: NO_EXTRA_CONFIG,
slashCommand: new SlashCommandBuilder()
.setName("musicinfo")
.setDescription("search yo music")
.setIntegrationTypes([
ApplicationIntegrationType.UserInstall
])
.addStringOption(option => {
return option.setName("search").setDescription("shit you wanna search").setRequired(true);
})
.addBooleanOption(option => {
return option.setName("lobotomized").setDescription("smol").setRequired(false);
})
.setContexts([
InteractionContextType.BotDM,
InteractionContextType.Guild,
InteractionContextType.PrivateChannel
])
})