mirror of
https://github.com/BluemediaDev/muse.git
synced 2025-05-11 12:21:37 +02:00
Migrate to slash commands (#431)
Co-authored-by: Federico fuji97 Rapetti <fuji1097@gmail.com>
This commit is contained in:
parent
e883275d83
commit
56a469a999
51 changed files with 1270 additions and 1294 deletions
2
src/utils/constants.ts
Normal file
2
src/utils/constants.ts
Normal file
|
@ -0,0 +1,2 @@
|
|||
export const ONE_HOUR_IN_SECONDS = 60 * 60;
|
||||
export const ONE_MINUTE_IN_SECONDS = 1 * 60;
|
|
@ -5,7 +5,7 @@ export default (error?: string | Error): string => {
|
|||
if (typeof error === 'string') {
|
||||
str = `🚫 ${error}`;
|
||||
} else if (error instanceof Error) {
|
||||
str = `🚫 ope: ${error.name}`;
|
||||
str = `🚫 ope: ${error.message}`;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
70
src/utils/get-youtube-and-spotify-suggestions-for.ts
Normal file
70
src/utils/get-youtube-and-spotify-suggestions-for.ts
Normal file
|
@ -0,0 +1,70 @@
|
|||
import {ApplicationCommandOptionChoice} from 'discord.js';
|
||||
import SpotifyWebApi from 'spotify-web-api-node';
|
||||
import getYouTubeSuggestionsFor from './get-youtube-suggestions-for.js';
|
||||
|
||||
const filterDuplicates = <T extends {name: string}>(items: T[]) => {
|
||||
const results: T[] = [];
|
||||
|
||||
for (const item of items) {
|
||||
if (!results.some(result => result.name === item.name)) {
|
||||
results.push(item);
|
||||
}
|
||||
}
|
||||
|
||||
return results;
|
||||
};
|
||||
|
||||
const getYouTubeAndSpotifySuggestionsFor = async (query: string, spotify: SpotifyWebApi, limit = 10): Promise<ApplicationCommandOptionChoice[]> => {
|
||||
const [youtubeSuggestions, spotifyResults] = await Promise.all([
|
||||
getYouTubeSuggestionsFor(query),
|
||||
spotify.search(query, ['track', 'album'], {limit: 5}),
|
||||
]);
|
||||
|
||||
const totalYouTubeResults = youtubeSuggestions.length;
|
||||
|
||||
const spotifyAlbums = filterDuplicates(spotifyResults.body.albums?.items ?? []);
|
||||
const spotifyTracks = filterDuplicates(spotifyResults.body.tracks?.items ?? []);
|
||||
|
||||
const totalSpotifyResults = spotifyAlbums.length + spotifyTracks.length;
|
||||
|
||||
// Number of results for each source should be roughly the same.
|
||||
// If we don't have enough Spotify suggestions, prioritize YouTube results.
|
||||
const maxSpotifySuggestions = Math.floor(limit / 2);
|
||||
const numOfSpotifySuggestions = Math.min(maxSpotifySuggestions, totalSpotifyResults);
|
||||
|
||||
const maxYouTubeSuggestions = limit - numOfSpotifySuggestions;
|
||||
const numOfYouTubeSuggestions = Math.min(maxYouTubeSuggestions, totalYouTubeResults);
|
||||
|
||||
const suggestions: ApplicationCommandOptionChoice[] = [];
|
||||
|
||||
suggestions.push(
|
||||
...youtubeSuggestions
|
||||
.slice(0, numOfYouTubeSuggestions)
|
||||
.map(suggestion => ({
|
||||
name: `YouTube: ${suggestion}`,
|
||||
value: suggestion,
|
||||
}),
|
||||
));
|
||||
|
||||
const maxSpotifyAlbums = Math.floor(numOfSpotifySuggestions / 2);
|
||||
const numOfSpotifyAlbums = Math.min(maxSpotifyAlbums, spotifyResults.body.albums?.items.length ?? 0);
|
||||
const maxSpotifyTracks = numOfSpotifySuggestions - numOfSpotifyAlbums;
|
||||
|
||||
suggestions.push(
|
||||
...spotifyAlbums.slice(0, maxSpotifyAlbums).map(album => ({
|
||||
name: `Spotify: 💿 ${album.name}${album.artists.length > 0 ? ` - ${album.artists[0].name}` : ''}`,
|
||||
value: `spotify:album:${album.id}`,
|
||||
})),
|
||||
);
|
||||
|
||||
suggestions.push(
|
||||
...spotifyTracks.slice(0, maxSpotifyTracks).map(track => ({
|
||||
name: `Spotify: 🎵 ${track.name}${track.artists.length > 0 ? ` - ${track.artists[0].name}` : ''}`,
|
||||
value: `spotify:track:${track.id}`,
|
||||
})),
|
||||
);
|
||||
|
||||
return suggestions;
|
||||
};
|
||||
|
||||
export default getYouTubeAndSpotifySuggestionsFor;
|
15
src/utils/get-youtube-suggestions-for.ts
Normal file
15
src/utils/get-youtube-suggestions-for.ts
Normal file
|
@ -0,0 +1,15 @@
|
|||
import got from 'got';
|
||||
|
||||
const getYouTubeSuggestionsFor = async (query: string): Promise<string[]> => {
|
||||
const [_, suggestions] = await got('https://suggestqueries.google.com/complete/search?client=firefox&ds=yt&q=', {
|
||||
searchParams: {
|
||||
client: 'firefox',
|
||||
ds: 'yt',
|
||||
q: query,
|
||||
},
|
||||
}).json<[string, string[]]>();
|
||||
|
||||
return suggestions;
|
||||
};
|
||||
|
||||
export default getYouTubeSuggestionsFor;
|
|
@ -1,81 +0,0 @@
|
|||
import {TextChannel, Message, MessageReaction} from 'discord.js';
|
||||
import delay from 'delay';
|
||||
|
||||
const INITAL_DELAY = 500;
|
||||
const PERIOD = 500;
|
||||
|
||||
export default class {
|
||||
public isStopped = true;
|
||||
private readonly channel: TextChannel;
|
||||
private readonly text: string;
|
||||
private msg!: Message;
|
||||
|
||||
constructor(channel: TextChannel, text = 'cows! count \'em') {
|
||||
this.channel = channel;
|
||||
this.text = text;
|
||||
}
|
||||
|
||||
async start(): Promise<void> {
|
||||
this.msg = await this.channel.send(this.text);
|
||||
|
||||
const icons = ['🐮', '🐴', '🐄'];
|
||||
|
||||
const reactions: MessageReaction[] = [];
|
||||
|
||||
let i = 0;
|
||||
let isRemoving = false;
|
||||
|
||||
this.isStopped = false;
|
||||
|
||||
(async () => {
|
||||
await delay(INITAL_DELAY);
|
||||
|
||||
while (!this.isStopped) {
|
||||
if (reactions.length === icons.length) {
|
||||
isRemoving = true;
|
||||
}
|
||||
|
||||
// eslint-disable-next-line no-await-in-loop
|
||||
await delay(PERIOD);
|
||||
|
||||
if (isRemoving) {
|
||||
const reactionToRemove = reactions.shift();
|
||||
|
||||
if (reactionToRemove) {
|
||||
// eslint-disable-next-line no-await-in-loop
|
||||
await reactionToRemove.users.remove(this.msg.client.user!.id);
|
||||
} else {
|
||||
isRemoving = false;
|
||||
}
|
||||
} else {
|
||||
if (!this.isStopped) {
|
||||
// eslint-disable-next-line no-await-in-loop
|
||||
reactions.push(await this.msg.react(icons[i % icons.length]));
|
||||
}
|
||||
|
||||
i++;
|
||||
}
|
||||
}
|
||||
})();
|
||||
}
|
||||
|
||||
async stop(str = 'u betcha'): Promise<Message> {
|
||||
const wasAlreadyStopped = this.isStopped;
|
||||
|
||||
this.isStopped = true;
|
||||
|
||||
const editPromise = str ? this.msg.edit(str) : null;
|
||||
const reactPromise = str && !wasAlreadyStopped ? (async () => {
|
||||
await this.msg.fetch();
|
||||
await Promise.all(this.msg.reactions.cache.map(async react => {
|
||||
if (react.me) {
|
||||
await react.users.remove(this.msg.client.user!.id);
|
||||
}
|
||||
}));
|
||||
})() : null;
|
||||
|
||||
await Promise.all([editPromise, reactPromise]);
|
||||
|
||||
return this.msg;
|
||||
}
|
||||
}
|
|
@ -9,6 +9,7 @@ const logBanner = () => {
|
|||
paypalUser: 'codetheweb',
|
||||
githubSponsor: 'codetheweb',
|
||||
madeByPrefix: 'Made with 🎶 by ',
|
||||
buildDate: process.env.BUILD_DATE ? new Date(process.env.BUILD_DATE) : undefined,
|
||||
}).join('\n'));
|
||||
console.log('\n');
|
||||
};
|
||||
|
|
44
src/utils/update-permissions-for-guild.ts
Normal file
44
src/utils/update-permissions-for-guild.ts
Normal file
|
@ -0,0 +1,44 @@
|
|||
import {ApplicationCommandPermissionData, Guild} from 'discord.js';
|
||||
import {prisma} from './db.js';
|
||||
|
||||
const COMMANDS_TO_LIMIT_TO_GUILD_OWNER = ['config'];
|
||||
|
||||
const updatePermissionsForGuild = async (guild: Guild) => {
|
||||
const settings = await prisma.setting.findUnique({
|
||||
where: {
|
||||
guildId: guild.id,
|
||||
},
|
||||
});
|
||||
|
||||
if (!settings) {
|
||||
throw new Error('could not find settings for guild');
|
||||
}
|
||||
|
||||
const permissions: ApplicationCommandPermissionData[] = [
|
||||
{
|
||||
id: guild.ownerId,
|
||||
type: 'USER',
|
||||
permission: true,
|
||||
},
|
||||
{
|
||||
id: guild.roles.everyone.id,
|
||||
type: 'ROLE',
|
||||
permission: false,
|
||||
},
|
||||
];
|
||||
const commands = await guild.commands.fetch();
|
||||
|
||||
await guild.commands.permissions.set({fullPermissions: commands.map(command => ({
|
||||
id: command.id,
|
||||
permissions: COMMANDS_TO_LIMIT_TO_GUILD_OWNER.includes(command.name) ? permissions : [
|
||||
...permissions,
|
||||
...(settings.roleId ? [{
|
||||
id: settings.roleId,
|
||||
type: 'ROLE' as const,
|
||||
permission: true,
|
||||
}] : []),
|
||||
],
|
||||
}))});
|
||||
};
|
||||
|
||||
export default updatePermissionsForGuild;
|
Loading…
Add table
Add a link
Reference in a new issue