From e04e5cae50eff8533ff7d8b7c80628c955ab7d9e Mon Sep 17 00:00:00 2001 From: Manuel <30572287+manuel-rw@users.noreply.github.com> Date: Sun, 19 Nov 2023 19:44:30 +0100 Subject: [PATCH] =?UTF-8?q?=E2=99=BB=EF=B8=8F=20Model=20names=20(#246)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/clients/discord/discord.voice.service.ts | 10 ++--- .../jellyfin/jellyfin.playstate.service.ts | 2 +- .../jellyfin/jellyfin.search.service.ts | 38 +++++++++---------- .../jellyfin/jellyfin.websocket.service.ts | 4 +- src/commands/play/play.comands.ts | 4 +- src/commands/playlist/playlist.command.ts | 2 +- src/commands/random/random.command.ts | 4 +- src/commands/volume/volume.command.ts | 4 +- .../{github-release.ts => GithubRelease.ts} | 0 src/models/TryResult.ts | 4 ++ src/models/generic-try-handler.ts | 6 --- src/models/{shared => music}/Playlist.ts | 0 src/models/{shared => music}/Track.ts | 0 ...{AlbumSearchHint.ts => AlbumSearchItem.ts} | 8 ++-- ...istSearchHint.ts => PlaylistSearchItem.ts} | 12 +++--- .../search/{SearchHint.ts => SearchItem.ts} | 8 ++-- src/playback/playback.service.ts | 2 +- src/updates/updates.service.spec.ts | 2 +- src/updates/updates.service.ts | 2 +- src/utils/timeUtils.ts | 2 +- src/utils/trackConverter.ts | 8 ++-- 21 files changed, 60 insertions(+), 62 deletions(-) rename src/models/{github-release.ts => GithubRelease.ts} (100%) create mode 100644 src/models/TryResult.ts delete mode 100644 src/models/generic-try-handler.ts rename src/models/{shared => music}/Playlist.ts (100%) rename src/models/{shared => music}/Track.ts (100%) rename src/models/search/{AlbumSearchHint.ts => AlbumSearchItem.ts} (88%) rename src/models/search/{PlaylistSearchHint.ts => PlaylistSearchItem.ts} (74%) rename src/models/search/{SearchHint.ts => SearchItem.ts} (94%) diff --git a/src/clients/discord/discord.voice.service.ts b/src/clients/discord/discord.voice.service.ts index 6d2cd39..a8806e4 100644 --- a/src/clients/discord/discord.voice.service.ts +++ b/src/clients/discord/discord.voice.service.ts @@ -16,10 +16,10 @@ import { Logger } from '@nestjs/common/services'; import { EventEmitter2, OnEvent } from '@nestjs/event-emitter'; import { Interval } from '@nestjs/schedule'; -import { GuildMember } from 'discord.js'; +import { APIEmbed, GuildMember, InteractionEditReplyOptions, InteractionReplyOptions, MessagePayload } from 'discord.js'; -import { GenericTryHandler } from '../../models/generic-try-handler'; -import { Track } from '../../models/shared/Track'; +import { TryResult } from '../../models/TryResult'; +import { Track } from '../../models/music/Track'; import { PlaybackService } from '../../playback/playback.service'; import { JellyfinStreamBuilderService } from '../jellyfin/jellyfin.stream.builder.service'; import { JellyfinWebSocketService } from '../jellyfin/jellyfin.websocket.service'; @@ -54,7 +54,7 @@ export class DiscordVoiceService { tryJoinChannelAndEstablishVoiceConnection( member: GuildMember, - ): GenericTryHandler { + ): TryResult { if (this.voiceConnection !== undefined) { this.logger.debug( 'Avoided joining the voice channel because voice connection is already defined', @@ -182,7 +182,7 @@ export class DiscordVoiceService { return true; } - disconnect(): GenericTryHandler { + disconnect(): TryResult { if (this.voiceConnection === undefined) { return { success: false, diff --git a/src/clients/jellyfin/jellyfin.playstate.service.ts b/src/clients/jellyfin/jellyfin.playstate.service.ts index ae56dc2..79b6b89 100644 --- a/src/clients/jellyfin/jellyfin.playstate.service.ts +++ b/src/clients/jellyfin/jellyfin.playstate.service.ts @@ -11,7 +11,7 @@ import { getSessionApi } from '@jellyfin/sdk/lib/utils/api/session-api'; import { Injectable, Logger } from '@nestjs/common'; import { OnEvent } from '@nestjs/event-emitter'; import { Interval } from '@nestjs/schedule'; -import { Track } from '../../models/shared/Track'; +import { Track } from '../../models/music/Track'; import { PlaybackService } from '../../playback/playback.service'; diff --git a/src/clients/jellyfin/jellyfin.search.service.ts b/src/clients/jellyfin/jellyfin.search.service.ts index ce9a042..41e5083 100644 --- a/src/clients/jellyfin/jellyfin.search.service.ts +++ b/src/clients/jellyfin/jellyfin.search.service.ts @@ -12,9 +12,9 @@ import { getSearchApi } from '@jellyfin/sdk/lib/utils/api/search-api'; import { Injectable } from '@nestjs/common'; import { Logger } from '@nestjs/common/services'; -import { AlbumSearchHint } from '../../models/search/AlbumSearchHint'; -import { PlaylistSearchHint } from '../../models/search/PlaylistSearchHint'; -import { SearchHint } from '../../models/search/SearchHint'; +import { AlbumSearchItem } from '../../models/search/AlbumSearchItem'; +import { PlaylistSearchItem } from '../../models/search/PlaylistSearchItem'; +import { SearchItem } from '../../models/search/SearchItem'; import { JellyfinService } from './jellyfin.service'; @@ -32,7 +32,7 @@ export class JellyfinSearchService { BaseItemKind.MusicAlbum, BaseItemKind.Playlist, ], - ): Promise { + ): Promise { const api = this.jellyfinService.getApi(); const searchApi = getSearchApi(api); @@ -64,14 +64,14 @@ export class JellyfinSearchService { return SearchHints.map((hint) => this.transformToSearchHintFromHint(hint), - ).filter((x) => x !== null) as SearchHint[]; + ).filter((x) => x !== null) as SearchItem[]; } catch (err) { this.logger.error(`Failed to search on Jellyfin: ${err}`); return []; } } - async getPlaylistitems(id: string): Promise { + async getPlaylistitems(id: string): Promise { const api = this.jellyfinService.getApi(); const searchApi = getPlaylistsApi(api); @@ -95,11 +95,11 @@ export class JellyfinSearchService { } return axiosResponse.data.Items.map((hint) => - SearchHint.constructFromBaseItem(hint), + SearchItem.constructFromBaseItem(hint), ); } - async getAlbumItems(albumId: string): Promise { + async getAlbumItems(albumId: string): Promise { const api = this.jellyfinService.getApi(); const searchApi = getSearchApi(api); const axiosResponse = await searchApi.get({ @@ -125,13 +125,13 @@ export class JellyfinSearchService { return [...axiosResponse.data.SearchHints] .reverse() - .map((hint) => SearchHint.constructFromHint(hint)); + .map((hint) => SearchItem.constructFromHint(hint)); } async getById( id: string, includeItemTypes: BaseItemKind[], - ): Promise { + ): Promise { const api = this.jellyfinService.getApi(); const searchApi = getItemsApi(api); @@ -152,7 +152,7 @@ export class JellyfinSearchService { async getAllById( ids: string[], includeItemTypes: BaseItemKind[] = [BaseItemKind.Audio], - ): Promise { + ): Promise { const api = this.jellyfinService.getApi(); const searchApi = getItemsApi(api); @@ -169,7 +169,7 @@ export class JellyfinSearchService { return data.Items.map((item) => this.transformToSearchHintFromBaseItemDto(item), - ).filter((searchHint) => searchHint !== undefined) as SearchHint[]; + ).filter((searchHint) => searchHint !== undefined) as SearchItem[]; } async getRemoteImageById(id: string, limit = 20): Promise { @@ -233,7 +233,7 @@ export class JellyfinSearchService { } return response.data.Items.map((item) => { - return SearchHint.constructFromBaseItem(item); + return SearchItem.constructFromBaseItem(item); }); } catch (err) { this.logger.error( @@ -246,11 +246,11 @@ export class JellyfinSearchService { private transformToSearchHintFromHint(jellyifnHint: JellyfinSearchHint) { switch (jellyifnHint.Type) { case BaseItemKind[BaseItemKind.Audio]: - return SearchHint.constructFromHint(jellyifnHint); + return SearchItem.constructFromHint(jellyifnHint); case BaseItemKind[BaseItemKind.MusicAlbum]: - return AlbumSearchHint.constructFromHint(jellyifnHint); + return AlbumSearchItem.constructFromHint(jellyifnHint); case BaseItemKind[BaseItemKind.Playlist]: - return PlaylistSearchHint.constructFromHint(jellyifnHint); + return PlaylistSearchItem.constructFromHint(jellyifnHint); default: this.logger.warn( `Received unexpected item type from Jellyfin search: ${jellyifnHint.Type}`, @@ -262,11 +262,11 @@ export class JellyfinSearchService { private transformToSearchHintFromBaseItemDto(baseItemDto: BaseItemDto) { switch (baseItemDto.Type) { case BaseItemKind[BaseItemKind.Audio]: - return SearchHint.constructFromBaseItem(baseItemDto); + return SearchItem.constructFromBaseItem(baseItemDto); case BaseItemKind[BaseItemKind.MusicAlbum]: - return AlbumSearchHint.constructFromBaseItem(baseItemDto); + return AlbumSearchItem.constructFromBaseItem(baseItemDto); case BaseItemKind[BaseItemKind.Playlist]: - return PlaylistSearchHint.constructFromBaseItem(baseItemDto); + return PlaylistSearchItem.constructFromBaseItem(baseItemDto); default: this.logger.warn( `Received unexpected item type from Jellyfin search: ${baseItemDto.Type}`, diff --git a/src/clients/jellyfin/jellyfin.websocket.service.ts b/src/clients/jellyfin/jellyfin.websocket.service.ts index 28912aa..995e89a 100644 --- a/src/clients/jellyfin/jellyfin.websocket.service.ts +++ b/src/clients/jellyfin/jellyfin.websocket.service.ts @@ -6,7 +6,7 @@ import { import { Injectable, Logger, OnModuleDestroy } from '@nestjs/common'; import { EventEmitter2 } from '@nestjs/event-emitter'; import { Cron } from '@nestjs/schedule'; -import { convertToTracks } from 'src/utils/trackConverter'; +import { flatMapTrackItems } from 'src/utils/trackConverter'; import { WebSocket } from 'ws'; @@ -105,7 +105,7 @@ export class JellyfinWebSocketService implements OnModuleDestroy { `Processing ${ids.length} ids received via websocket and adding them to the queue`, ); const searchHints = await this.jellyfinSearchService.getAllById(ids); - const tracks = convertToTracks(searchHints, this.jellyfinSearchService); + const tracks = flatMapTrackItems(searchHints, this.jellyfinSearchService); this.playbackService.getPlaylistOrDefault().enqueueTracks(tracks); break; case SessionMessageType[SessionMessageType.Playstate]: diff --git a/src/commands/play/play.comands.ts b/src/commands/play/play.comands.ts index 70900ac..97e7842 100644 --- a/src/commands/play/play.comands.ts +++ b/src/commands/play/play.comands.ts @@ -23,7 +23,7 @@ import { import { DiscordMessageService } from '../../clients/discord/discord.message.service'; import { DiscordVoiceService } from '../../clients/discord/discord.voice.service'; import { JellyfinSearchService } from '../../clients/jellyfin/jellyfin.search.service'; -import { SearchHint } from '../../models/search/SearchHint'; +import { SearchItem } from '../../models/search/SearchItem'; import { PlaybackService } from '../../playback/playback.service'; import { formatMillisecondsAsHumanReadable } from '../../utils/timeUtils'; @@ -55,7 +55,7 @@ export class PlayItemCommand { const baseItems = PlayCommandParams.getBaseItemKinds(dto.type); - let item: SearchHint | undefined; + let item: SearchItem | undefined; if (dto.name.startsWith('native-')) { item = await this.jellyfinSearchService.getById( dto.name.replace('native-', ''), diff --git a/src/commands/playlist/playlist.command.ts b/src/commands/playlist/playlist.command.ts index b683018..5a66e8d 100644 --- a/src/commands/playlist/playlist.command.ts +++ b/src/commands/playlist/playlist.command.ts @@ -20,7 +20,7 @@ import { } from 'discord.js'; import { DiscordMessageService } from '../../clients/discord/discord.message.service'; -import { Track } from '../../models/shared/Track'; +import { Track } from '../../models/music/Track'; import { PlaybackService } from '../../playback/playback.service'; import { chunkArray } from '../../utils/arrayUtils'; import { diff --git a/src/commands/random/random.command.ts b/src/commands/random/random.command.ts index 7001dae..1958420 100644 --- a/src/commands/random/random.command.ts +++ b/src/commands/random/random.command.ts @@ -9,7 +9,7 @@ import { 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 { SearchItem } from 'src/models/search/SearchItem'; import { PlaybackService } from 'src/playback/playback.service'; import { RandomCommandParams } from './random.params'; import { defaultMemberPermissions } from 'src/utils/environment'; @@ -65,7 +65,7 @@ export class EnqueueRandomItemsCommand { }); } - private async getTracks(hints: SearchHint[]) { + private async getTracks(hints: SearchItem[]) { const promises = await Promise.all( hints.flatMap(async (item) => { const tracks = await item.toTracks(this.jellyfinSearchService); diff --git a/src/commands/volume/volume.command.ts b/src/commands/volume/volume.command.ts index bf5fb5b..7ddcb9f 100644 --- a/src/commands/volume/volume.command.ts +++ b/src/commands/volume/volume.command.ts @@ -8,7 +8,7 @@ import { CommandInteraction } from 'discord.js'; import { DiscordMessageService } from 'src/clients/discord/discord.message.service'; import { DiscordVoiceService } from 'src/clients/discord/discord.voice.service'; import { PlaybackService } from 'src/playback/playback.service'; -import { sleep } from 'src/utils/timeUtils'; +import { sleepAsync } from 'src/utils/timeUtils'; import { VolumeCommandParams } from './volume.params'; import { defaultMemberPermissions } from 'src/utils/environment'; @@ -56,7 +56,7 @@ export class VolumeCommand { this.discordVoiceService.changeVolume(volume); // Discord takes some time to react. Confirmation message should appear after actual change - await sleep(1500); + await sleepAsync(1500); await interaction.editReply({ embeds: [ diff --git a/src/models/github-release.ts b/src/models/GithubRelease.ts similarity index 100% rename from src/models/github-release.ts rename to src/models/GithubRelease.ts diff --git a/src/models/TryResult.ts b/src/models/TryResult.ts new file mode 100644 index 0000000..f7cd9c6 --- /dev/null +++ b/src/models/TryResult.ts @@ -0,0 +1,4 @@ +export interface TryResult { + success: boolean; + reply: T; +} diff --git a/src/models/generic-try-handler.ts b/src/models/generic-try-handler.ts deleted file mode 100644 index 78130a9..0000000 --- a/src/models/generic-try-handler.ts +++ /dev/null @@ -1,6 +0,0 @@ -import { InteractionEditReplyOptions, MessagePayload } from 'discord.js'; - -export interface GenericTryHandler { - success: boolean; - reply: string | MessagePayload | InteractionEditReplyOptions; -} diff --git a/src/models/shared/Playlist.ts b/src/models/music/Playlist.ts similarity index 100% rename from src/models/shared/Playlist.ts rename to src/models/music/Playlist.ts diff --git a/src/models/shared/Track.ts b/src/models/music/Track.ts similarity index 100% rename from src/models/shared/Track.ts rename to src/models/music/Track.ts diff --git a/src/models/search/AlbumSearchHint.ts b/src/models/search/AlbumSearchItem.ts similarity index 88% rename from src/models/search/AlbumSearchHint.ts rename to src/models/search/AlbumSearchItem.ts index a4c01cb..e9a6fbf 100644 --- a/src/models/search/AlbumSearchHint.ts +++ b/src/models/search/AlbumSearchItem.ts @@ -1,12 +1,12 @@ import { SearchHint as JellyfinSearchHint } from '@jellyfin/sdk/lib/generated-client/models'; -import { Track } from '../shared/Track'; +import { Track } from '../music/Track'; import { JellyfinSearchService } from '../../clients/jellyfin/jellyfin.search.service'; -import { SearchHint } from './SearchHint'; +import { SearchItem } from './SearchItem'; import { trimStringToFixedLength } from 'src/utils/stringUtils/stringUtils'; -export class AlbumSearchHint extends SearchHint { +export class AlbumSearchItem extends SearchItem { override toString(): string { return `🎶 ${this.name}`; } @@ -22,7 +22,7 @@ export class AlbumSearchHint extends SearchHint { artist = hint.AlbumArtist + " - " } - return new AlbumSearchHint( + return new AlbumSearchItem( hint.Id, trimStringToFixedLength(artist + hint.Name, 70), hint.RunTimeTicks / 10000, diff --git a/src/models/search/PlaylistSearchHint.ts b/src/models/search/PlaylistSearchItem.ts similarity index 74% rename from src/models/search/PlaylistSearchHint.ts rename to src/models/search/PlaylistSearchItem.ts index 519e7d1..960833e 100644 --- a/src/models/search/PlaylistSearchHint.ts +++ b/src/models/search/PlaylistSearchItem.ts @@ -1,13 +1,13 @@ import { SearchHint as JellyfinSearchHint } from '@jellyfin/sdk/lib/generated-client/models'; -import { Track } from '../shared/Track'; +import { Track } from '../music/Track'; import { JellyfinSearchService } from '../../clients/jellyfin/jellyfin.search.service'; -import { SearchHint } from './SearchHint'; -import { convertToTracks } from 'src/utils/trackConverter'; +import { SearchItem } from './SearchItem'; +import { flatMapTrackItems } from 'src/utils/trackConverter'; import { trimStringToFixedLength } from 'src/utils/stringUtils/stringUtils'; -export class PlaylistSearchHint extends SearchHint { +export class PlaylistSearchItem extends SearchItem { override toString(): string { return `🎧 ${this.name}`; } @@ -19,7 +19,7 @@ export class PlaylistSearchHint extends SearchHint { ); } - return new PlaylistSearchHint( + return new PlaylistSearchItem( hint.Id, trimStringToFixedLength(hint.Name, 50), hint.RunTimeTicks / 10000, @@ -30,6 +30,6 @@ export class PlaylistSearchHint extends SearchHint { searchService: JellyfinSearchService, ): Promise { const playlistItems = await searchService.getPlaylistitems(this.id); - return convertToTracks(playlistItems, searchService); + return flatMapTrackItems(playlistItems, searchService); } } diff --git a/src/models/search/SearchHint.ts b/src/models/search/SearchItem.ts similarity index 94% rename from src/models/search/SearchHint.ts rename to src/models/search/SearchItem.ts index 2f46a5d..b7f1836 100644 --- a/src/models/search/SearchHint.ts +++ b/src/models/search/SearchItem.ts @@ -5,10 +5,10 @@ import { import { z } from 'zod'; import { JellyfinSearchService } from '../../clients/jellyfin/jellyfin.search.service'; -import { Track } from '../shared/Track'; +import { Track } from '../music/Track'; import { trimStringToFixedLength } from 'src/utils/stringUtils/stringUtils'; -export class SearchHint { +export class SearchItem { constructor( protected readonly id: string, protected readonly name: string, @@ -54,7 +54,7 @@ export class SearchHint { artist += " - " } } - return new SearchHint( + return new SearchItem( result.data.Id, trimStringToFixedLength(artist + result.data.Name, 70), result.data.RunTimeTicks / 10000, @@ -67,7 +67,7 @@ export class SearchHint { 'Unable to construct search hint from base item, required properties were undefined', ); } - return new SearchHint( + return new SearchItem( baseItem.Id, trimStringToFixedLength(baseItem.Name, 50), baseItem.RunTimeTicks / 10000, diff --git a/src/playback/playback.service.ts b/src/playback/playback.service.ts index df96f2d..c42f695 100644 --- a/src/playback/playback.service.ts +++ b/src/playback/playback.service.ts @@ -1,7 +1,7 @@ import { Injectable, Logger } from '@nestjs/common'; import { EventEmitter2, OnEvent } from '@nestjs/event-emitter'; -import { Playlist } from '../models/shared/Playlist'; +import { Playlist } from '../models/music/Playlist'; @Injectable() export class PlaybackService { diff --git a/src/updates/updates.service.spec.ts b/src/updates/updates.service.spec.ts index a72d899..2bb4160 100644 --- a/src/updates/updates.service.spec.ts +++ b/src/updates/updates.service.spec.ts @@ -3,7 +3,7 @@ import axios from 'axios'; import { Client, GuildMember } from 'discord.js'; import { Constants } from '../utils/constants'; import { DiscordMessageService } from '../clients/discord/discord.message.service'; -import { GithubRelease } from '../models/github-release'; +import { GithubRelease } from '../models/GithubRelease'; import { useDefaultMockerToken } from '../utils/tests/defaultMockerToken'; import { UpdatesService } from './updates.service'; import { InjectionToken } from '@nestjs/common'; diff --git a/src/updates/updates.service.ts b/src/updates/updates.service.ts index 0072458..f6c40d3 100644 --- a/src/updates/updates.service.ts +++ b/src/updates/updates.service.ts @@ -6,7 +6,7 @@ import axios from 'axios'; import { formatRelative, parseISO } from 'date-fns'; import { ActionRowBuilder, ButtonStyle, Client } from 'discord.js'; import { DiscordMessageService } from '../clients/discord/discord.message.service'; -import { GithubRelease } from '../models/github-release'; +import { GithubRelease } from '../models/GithubRelease'; import { Constants } from '../utils/constants'; @Injectable() diff --git a/src/utils/timeUtils.ts b/src/utils/timeUtils.ts index 3224eb2..007715b 100644 --- a/src/utils/timeUtils.ts +++ b/src/utils/timeUtils.ts @@ -16,6 +16,6 @@ export const formatMillisecondsAsHumanReadable = ( return duration; }; -export function sleep(ms: number) { +export function sleepAsync(ms: number) { return new Promise((resolve) => setTimeout(resolve, ms)); } diff --git a/src/utils/trackConverter.ts b/src/utils/trackConverter.ts index 4754a96..06536b0 100644 --- a/src/utils/trackConverter.ts +++ b/src/utils/trackConverter.ts @@ -1,9 +1,9 @@ import { JellyfinSearchService } from 'src/clients/jellyfin/jellyfin.search.service'; -import { SearchHint } from 'src/models/search/SearchHint'; -import { Track } from 'src/models/shared/Track'; +import { SearchItem } from 'src/models/search/SearchItem'; +import { Track } from 'src/models/music/Track'; -export const convertToTracks = ( - hints: SearchHint[], +export const flatMapTrackItems = ( + hints: SearchItem[], jellyfinSearchService: JellyfinSearchService, ): Track[] => { let tracks: Track[] = [];