Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions Taskfile.yml
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,11 @@ tasks:
cmds:
- docker-compose down --remove-orphans -v

clean:network:
desc: "Remove container and volumes for network mode"
cmds:
- docker-compose -f docker-compose.network.yml down --remove-orphans -v

#########################################
# Jukebox-Types Package
#########################################
Expand Down
4 changes: 4 additions & 0 deletions src/jukebox/juke-session/dto/membership.dto.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import { EntityDtoBase } from 'src/config/dtos'
import { JukeSessionMembership } from '../entities/membership.entity'
import { JukeSessionDto } from './juke-session.dto'
import { IsNotEmpty, IsNumber } from 'class-validator'
import { QueuedTrack } from 'src/jukebox/queue/entities/queued-track.entity'

export class JukeSessionMembershipInlineDto {
@Expose()
Expand All @@ -21,6 +22,9 @@ export class JukeSessionMembershipDto extends EntityDtoBase<JukeSessionMembershi
user_id: number

@Expose()
@Transform(({ obj }) =>
obj.queued_tracks ? obj.queued_tracks.map((track: QueuedTrack) => track.id) : [],
)
queued_tracks: number[]
}

Expand Down
5 changes: 4 additions & 1 deletion src/jukebox/juke-session/juke-session.controller.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import {
Body,
Controller,
DefaultValuePipe,
Delete,
Get,
Param,
Expand All @@ -10,7 +11,7 @@ import {
UseGuards,
UseInterceptors,
} from '@nestjs/common'
import { ApiBearerAuth, ApiOperation, ApiTags } from '@nestjs/swagger'
import { ApiBearerAuth, ApiOperation, ApiQuery, ApiTags } from '@nestjs/swagger'
import { AuthInterceptor } from 'src/auth/auth.interceptor'
import { NumberPipe } from 'src/pipes/int-pipe.pipe'
import { UserDto } from 'src/shared'
Expand Down Expand Up @@ -146,6 +147,8 @@ export class JukeSessionController {
@ApiOperation({
summary: '[MEMBER] (PAGINATED: 0-indexed) Get members/memberships of a juke session',
})
@ApiQuery({ name: 'page', required: false, type: Number, schema: { default: 0, minimum: 0 } })
@ApiQuery({ name: 'rows', required: false, type: Number, schema: { default: 7, minimum: 1 } })
getJukeSessionMembers(
@Param('jukebox_id', new NumberPipe('jukebox_id')) jukeboxId: number,
@Param('id', new NumberPipe('id')) id: number,
Expand Down
1 change: 1 addition & 0 deletions src/jukebox/juke-session/juke-session.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -275,6 +275,7 @@ export class JukeSessionService {
): Promise<JukeSessionMembershipDto> {
const membership = await this.membershipRepo.findOne({
where: { user_id: userId, juke_session: { id: jukeSessionId } },
relations: { juke_session: true, queued_tracks: true },
})
if (!membership) {
throw new NotFoundException(`User ${userId} is not a member of juke session ${jukeSessionId}`)
Expand Down
16 changes: 16 additions & 0 deletions src/jukebox/juke-session/tests/juke-session.controller.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -277,4 +277,20 @@ describe('JukeSessionController', () => {

expect(membership.user_id).toEqual(testUserId)
})

it('should get queued tracks for a member', async () => {
const session = await createTestJukeSession()
const testUserId = 4
const membership = await controller.addJukeSessionMemberByJoinCode(
jukebox.id,
session.join_code,
{
user_id: testUserId,
},
)
await queueService.queueTrack(session.id, { queued_by: { id: membership.id }, track })

const membershipWithQueued = await controller.getJukeSessionMember(jukebox.id, membership.id)
expect(membershipWithQueued.queued_tracks[0]).toEqual(track.id)
})
})
9 changes: 8 additions & 1 deletion src/spotify/spotify.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import { Axios } from 'axios'
import { JukeboxSearchDto } from 'src/jukebox/dto/jukebox-search.dto'
import { SpotifyTokensDto } from './dto/spotify-tokens.dto'
import { SpotifyBaseService } from './spotify-base.service'
import { MaxInt } from '@spotify/web-api-ts-sdk'

export interface ISpotifyService {
setPlayerDevice(spotifyAuth: SpotifyTokensDto, deviceId: string): Promise<void>
Expand Down Expand Up @@ -60,11 +61,17 @@ export class SpotifyService extends SpotifyBaseService implements ISpotifyServic
return sdk.player.getUsersQueue()
}

async searchTracks(spotifyAuth: SpotifyTokensDto, searchQuery: JukeboxSearchDto) {
async searchTracks(
spotifyAuth: SpotifyTokensDto,
searchQuery: JukeboxSearchDto,
limit: MaxInt<50> = 10,
) {
const sdk = this.getSdk(spotifyAuth)
return sdk.search(
`${searchQuery.trackQuery} artist:${searchQuery.artistQuery} album:${searchQuery.albumQuery}`,
['track'],
undefined,
limit,
)
}

Expand Down
15 changes: 11 additions & 4 deletions src/track/track.controller.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { Body, Controller, Get, NotImplementedException, Query, UseGuards } from '@nestjs/common'
import { ApiBearerAuth, ApiOperation, ApiTags } from '@nestjs/swagger'
import { ApiBearerAuth, ApiOperation, ApiQuery, ApiTags } from '@nestjs/swagger'
import { JukeboxSearchDto } from 'src/jukebox/dto/jukebox-search.dto'
import { Roles } from 'src/utils/decorators/roles.decorator'
import { RolesGuard } from 'src/utils/guards/roles.guard'
Expand All @@ -15,8 +15,15 @@ export class TrackController {
@UseGuards(RolesGuard)
@Get()
@ApiOperation({ summary: '[MEMBER] Search tracks from the Spotify API' })
searchTracks(@Query('jukeboxId') jukeboxId: string, @Body() body: JukeboxSearchDto) {
// return this.trackService.searchTracks(+jukeboxId, body)
throw new NotImplementedException()
@ApiQuery({ name: 'trackQuery', required: false, schema: { type: 'string', default: '' } })
@ApiQuery({ name: 'albumQuery', required: false, schema: { type: 'string', default: '' } })
@ApiQuery({ name: 'artistQuery', required: false, schema: { type: 'string', default: '' } })
searchTracks(
@Query('jukeboxId') jukeboxId: string,
@Query('trackQuery') trackQuery: string = '',
@Query('albumQuery') albumQuery: string = '',
@Query('artistQuery') artistQuery: string = '',
) {
return this.trackService.searchTracks(+jukeboxId, { trackQuery, albumQuery, artistQuery })
}
}
7 changes: 7 additions & 0 deletions src/track/track.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import { SpotifyService } from 'src/spotify/spotify.service'
import { Repository } from 'typeorm'
import { CreateTrackDto, TrackDto } from './dto/track.dto'
import { Track } from './entities/track.entity'
import { JukeboxSearchDto } from 'src/jukebox/dto/jukebox-search.dto'

@Injectable()
export class TrackService {
Expand Down Expand Up @@ -36,6 +37,12 @@ export class TrackService {
return plainToInstance(TrackDto, track)
}

async searchTracks(jukeboxId: number, searchQuery: JukeboxSearchDto): Promise<TrackDto> {
const link = await this.accountLinkService.getActiveAccount(jukeboxId)
const search = await this.spotifyService.searchTracks(link.spotify_account, searchQuery)
return plainToInstance(TrackDto, search)
}

// findAll() {
// return `This action returns all track`
// }
Expand Down