mirror of
https://github.com/informaticker/discord-jellyfin-bot.git
synced 2024-11-24 18:41:57 +01:00
✨ Add enqueue random items command (#130)
This commit is contained in:
parent
2141880b44
commit
2c15e38b94
@ -39,7 +39,7 @@ export class DiscordMessageService {
|
||||
}: {
|
||||
title: string;
|
||||
description?: string;
|
||||
authorUrl?: string;
|
||||
authorUrl?: string | undefined;
|
||||
mixin?: (embedBuilder: EmbedBuilder) => EmbedBuilder;
|
||||
}): APIEmbed {
|
||||
let embedBuilder = new EmbedBuilder()
|
||||
|
@ -170,6 +170,30 @@ export class JellyfinSearchService {
|
||||
}
|
||||
}
|
||||
|
||||
async getRandomTracks(limit: number) {
|
||||
const api = this.jellyfinService.getApi();
|
||||
const searchApi = getItemsApi(api);
|
||||
|
||||
try {
|
||||
const response = await searchApi.getItems({
|
||||
includeItemTypes: [BaseItemKind.Audio],
|
||||
limit: limit,
|
||||
sortBy: ['random'],
|
||||
userId: this.jellyfinService.getUserId(),
|
||||
recursive: true,
|
||||
});
|
||||
|
||||
return response.data.Items.map((item) => {
|
||||
return SearchHint.constructFromBaseItem(item);
|
||||
});
|
||||
} catch (err) {
|
||||
this.logger.error(
|
||||
`Unabele to retrieve random items from Jellyfin: ${err}`,
|
||||
);
|
||||
return [];
|
||||
}
|
||||
}
|
||||
|
||||
private transformToSearchHint(jellyifnHint: JellyfinSearchHint) {
|
||||
switch (jellyifnHint.Type) {
|
||||
case BaseItemKind[BaseItemKind.Audio]:
|
||||
|
@ -15,6 +15,7 @@ import { StatusCommand } from './status.command';
|
||||
import { StopPlaybackCommand } from './stop.command';
|
||||
import { SummonCommand } from './summon.command';
|
||||
import { PlaylistInteractionCollector } from './playlist/playlist.interaction-collector';
|
||||
import { EnqueueRandomItemsCommand } from './random/random.command';
|
||||
|
||||
@Module({
|
||||
imports: [
|
||||
@ -28,6 +29,7 @@ import { PlaylistInteractionCollector } from './playlist/playlist.interaction-co
|
||||
PlaylistInteractionCollector,
|
||||
HelpCommand,
|
||||
StatusCommand,
|
||||
EnqueueRandomItemsCommand,
|
||||
PlaylistCommand,
|
||||
DisconnectCommand,
|
||||
PausePlaybackCommand,
|
||||
|
77
src/commands/random/random.command.ts
Normal file
77
src/commands/random/random.command.ts
Normal file
@ -0,0 +1,77 @@
|
||||
import { SlashCommandPipe } from '@discord-nestjs/common';
|
||||
import { Command, Handler, IA, InteractionEvent } from '@discord-nestjs/core';
|
||||
import { Injectable } from '@nestjs/common';
|
||||
import {
|
||||
CommandInteraction,
|
||||
GuildMember,
|
||||
InteractionReplyOptions,
|
||||
} from 'discord.js';
|
||||
import { DiscordMessageService } from 'src/clients/discord/discord.message.service';
|
||||
import { DiscordVoiceService } from 'src/clients/discord/discord.voice.service';
|
||||
import { JellyfinSearchService } from 'src/clients/jellyfin/jellyfin.search.service';
|
||||
import { SearchHint } from 'src/models/search/SearchHint';
|
||||
import { Track } from 'src/models/shared/Track';
|
||||
import { PlaybackService } from 'src/playback/playback.service';
|
||||
import { RandomCommandParams } from './random.params';
|
||||
|
||||
@Command({
|
||||
name: 'random',
|
||||
description: 'Enqueues a random selection of tracks to your playlist',
|
||||
})
|
||||
@Injectable()
|
||||
export class EnqueueRandomItemsCommand {
|
||||
constructor(
|
||||
private readonly playbackService: PlaybackService,
|
||||
private readonly discordVoiceService: DiscordVoiceService,
|
||||
private readonly discordMessageService: DiscordMessageService,
|
||||
private readonly jellyfinSearchService: JellyfinSearchService,
|
||||
) {}
|
||||
|
||||
@Handler()
|
||||
async handler(
|
||||
@InteractionEvent(SlashCommandPipe) dto: RandomCommandParams,
|
||||
@IA() interaction: CommandInteraction,
|
||||
): Promise<void> {
|
||||
await interaction.deferReply();
|
||||
|
||||
const guildMember = interaction.member as GuildMember;
|
||||
|
||||
const tryResult =
|
||||
this.discordVoiceService.tryJoinChannelAndEstablishVoiceConnection(
|
||||
guildMember,
|
||||
);
|
||||
|
||||
if (!tryResult.success) {
|
||||
const replyOptions = tryResult.reply as InteractionReplyOptions;
|
||||
await interaction.editReply({
|
||||
embeds: replyOptions.embeds,
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
const items = await this.jellyfinSearchService.getRandomTracks(dto.count);
|
||||
const tracks = await this.getTracks(items);
|
||||
|
||||
this.playbackService.getPlaylistOrDefault().enqueueTracks(tracks);
|
||||
|
||||
await interaction.editReply({
|
||||
embeds: [
|
||||
this.discordMessageService.buildMessage({
|
||||
title: `Added ${tracks.length} tracks to your playlist`,
|
||||
description: 'Use ``/playlist`` to see them',
|
||||
}),
|
||||
],
|
||||
});
|
||||
}
|
||||
|
||||
private async getTracks(hints: SearchHint[]) {
|
||||
const promises = await Promise.all(
|
||||
hints.flatMap(async (item) => {
|
||||
const tracks = await item.toTracks(this.jellyfinSearchService);
|
||||
return tracks;
|
||||
}),
|
||||
);
|
||||
|
||||
return promises.flatMap((x) => x);
|
||||
}
|
||||
}
|
12
src/commands/random/random.params.ts
Normal file
12
src/commands/random/random.params.ts
Normal file
@ -0,0 +1,12 @@
|
||||
import { Param, ParamType } from '@discord-nestjs/core';
|
||||
|
||||
export class RandomCommandParams {
|
||||
@Param({
|
||||
required: false,
|
||||
description: 'Count of items to search for',
|
||||
type: ParamType.INTEGER,
|
||||
minValue: 0,
|
||||
maxValue: 10000,
|
||||
})
|
||||
count = 20;
|
||||
}
|
@ -1,7 +1,10 @@
|
||||
import { SearchHint as JellyfinSearchHint } from '@jellyfin/sdk/lib/generated-client/models';
|
||||
import {
|
||||
BaseItemDto,
|
||||
SearchHint as JellyfinSearchHint,
|
||||
} from '@jellyfin/sdk/lib/generated-client/models';
|
||||
|
||||
import { Track } from '../shared/Track';
|
||||
import { JellyfinSearchService } from '../../clients/jellyfin/jellyfin.search.service';
|
||||
import { Track } from '../shared/Track';
|
||||
|
||||
export class SearchHint {
|
||||
constructor(
|
||||
@ -28,4 +31,12 @@ export class SearchHint {
|
||||
static constructFromHint(hint: JellyfinSearchHint) {
|
||||
return new SearchHint(hint.Id, hint.Name, hint.RunTimeTicks / 10000);
|
||||
}
|
||||
|
||||
static constructFromBaseItem(baseItem: BaseItemDto) {
|
||||
return new SearchHint(
|
||||
baseItem.Id,
|
||||
baseItem.Name,
|
||||
baseItem.RunTimeTicks / 10000,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user