-
Notifications
You must be signed in to change notification settings - Fork 171
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
7bbe2ea
commit cda535b
Showing
15 changed files
with
245 additions
and
2 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
export * from './playlist.controller' |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,84 @@ | ||
import { OpenAPIHono, createRoute, z } from '@hono/zod-openapi' | ||
import { AlbumModel } from '#modules/albums/models' | ||
import { PlaylistService } from '#modules/playlists/services' | ||
|
||
export class PlaylistController { | ||
public controller: OpenAPIHono | ||
private playlistService: PlaylistService | ||
|
||
constructor() { | ||
this.controller = new OpenAPIHono() | ||
this.playlistService = new PlaylistService() | ||
} | ||
|
||
public initRoutes() { | ||
this.controller.openapi( | ||
createRoute({ | ||
method: 'get', | ||
path: '/playlists', | ||
tags: ['Playlist'], | ||
summary: 'Retrieve a playlist by ID or link', | ||
description: 'Retrieve a playlist by providing either an ID or a direct link to the playlist on JioSaavn.', | ||
operationId: 'getPlaylistByIdOrLink', | ||
request: { | ||
query: z.object({ | ||
id: z.string().optional().openapi({ | ||
title: 'Playlist ID', | ||
description: 'The unique ID of the playlist', | ||
type: 'string', | ||
example: '82914609', | ||
default: '82914609' | ||
}), | ||
link: z | ||
.string() | ||
.url() | ||
.optional() | ||
.transform((value) => value?.match(/jiosaavn\.com\/featured\/[^/]+\/([^/]+)$/)?.[1]) | ||
.openapi({ | ||
title: 'Playlist Link', | ||
description: 'A direct link to the playlist on JioSaavn', | ||
type: 'string', | ||
example: 'https://www.jiosaavn.com/featured/its-indie-english/AMoxtXyKHoU_', | ||
default: 'https://www.jiosaavn.com/featured/its-indie-english/AMoxtXyKHoU_' | ||
}) | ||
}) | ||
}, | ||
responses: { | ||
200: { | ||
description: 'Successful response with playlist details', | ||
content: { | ||
'application/json': { | ||
schema: z.object({ | ||
success: z.boolean().openapi({ | ||
description: 'Indicates the success status of the request.', | ||
type: 'boolean', | ||
example: true | ||
}), | ||
data: AlbumModel.openapi({ | ||
title: 'Album Details', | ||
description: 'The detailed information of the playlist.' | ||
}) | ||
}) | ||
} | ||
} | ||
}, | ||
400: { description: 'Bad request due to missing or invalid query parameters.' }, | ||
404: { description: 'The playlist could not be found with the provided ID or link.' } | ||
} | ||
}), | ||
async (ctx) => { | ||
const { id, link } = ctx.req.valid('query') | ||
|
||
if (!link && !id) { | ||
return ctx.json({ success: false, message: 'Either playlist ID or link is required' }, 400) | ||
} | ||
|
||
const response = link | ||
? await this.playlistService.getPlaylistByLink(link) | ||
: await this.playlistService.getPlaylistById(id!) | ||
|
||
return ctx.json({ success: true, data: response }) | ||
} | ||
) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
export * from './playlist.helper' |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
import type { z } from 'zod' | ||
import type { PlaylistAPIResponseModel, PlaylistModel } from '#modules/playlists/models' | ||
import { createArtistMap, createSongPayload } from '#modules/songs/helpers' | ||
import { createImageLinks } from '#common/helpers' | ||
|
||
export const createPlaylistPayload = ( | ||
album: z.infer<typeof PlaylistAPIResponseModel> | ||
): z.infer<typeof PlaylistModel> => ({ | ||
id: album.id, | ||
name: album.title, | ||
description: album.header_desc, | ||
type: album.type, | ||
year: Number(album.year || 0), | ||
playCount: Number(album.play_count), | ||
language: album.language, | ||
explicitContent: album.explicit_content === '1', | ||
url: album.perma_url, | ||
songCount: Number(album.list_count || 0), | ||
artists: album.more_info.artists?.map(createArtistMap), | ||
image: createImageLinks(album.image), | ||
...(album.list && { songs: album.list.map((song) => createSongPayload(song)) }) | ||
}) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
export * from './playlist.model' |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,66 @@ | ||
import { z } from 'zod' | ||
import { DownloadLinkModel } from '#common/models' | ||
import { SongAPIResponseModel, SongArtistMapModel, SongModel } from '#modules/songs/models' | ||
|
||
export const PlaylistAPIResponseModel = z.object({ | ||
id: z.string(), | ||
title: z.string(), | ||
subtitle: z.string(), | ||
header_desc: z.string(), | ||
type: z.string(), | ||
perma_url: z.string(), | ||
image: z.string(), | ||
language: z.string(), | ||
year: z.string(), | ||
play_count: z.string(), | ||
explicit_content: z.string(), | ||
list_count: z.string(), | ||
list_type: z.string(), | ||
list: z.array(SongAPIResponseModel), | ||
more_info: z.object({ | ||
uid: z.string(), | ||
is_dolby_content: z.boolean(), | ||
subtype: z.array(z.string()).default([]), | ||
last_updated: z.string(), | ||
username: z.string(), | ||
firstname: z.string(), | ||
lastname: z.string(), | ||
is_followed: z.string(), | ||
isFY: z.boolean(), | ||
follower_count: z.string(), | ||
fan_count: z.string(), | ||
playlist_type: z.string(), | ||
share: z.string(), | ||
sub_types: z.array(z.string()), | ||
images: z.array(z.string()), | ||
H2: z.string().nullable(), | ||
subheading: z.string(), | ||
video_count: z.string(), | ||
artists: z.array( | ||
z.object({ | ||
id: z.string(), | ||
name: z.string(), | ||
role: z.string(), | ||
image: z.string(), | ||
type: z.string(), | ||
perma_url: z.string() | ||
}) | ||
) | ||
}) | ||
}) | ||
|
||
export const PlaylistModel = z.object({ | ||
id: z.string(), | ||
name: z.string(), | ||
description: z.string(), | ||
year: z.number(), | ||
type: z.string(), | ||
playCount: z.number(), | ||
language: z.string(), | ||
explicitContent: z.boolean(), | ||
songCount: z.number(), | ||
url: z.string(), | ||
image: z.array(DownloadLinkModel), | ||
songs: z.array(SongModel), | ||
artists: z.array(SongArtistMapModel) | ||
}) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
export * from './playlist.service' |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
import { GetPlaylistByIdUseCase, GetPlaylistByLinkUseCase } from '#modules/playlists/use-cases' | ||
|
||
export class PlaylistService { | ||
private readonly getPlaylistByIdUseCase: GetPlaylistByIdUseCase | ||
private readonly getPlaylistByLinkUseCase: GetPlaylistByLinkUseCase | ||
|
||
constructor() { | ||
this.getPlaylistByIdUseCase = new GetPlaylistByIdUseCase() | ||
this.getPlaylistByLinkUseCase = new GetPlaylistByLinkUseCase() | ||
} | ||
|
||
getPlaylistById = (playlistId: string) => { | ||
return this.getPlaylistByIdUseCase.execute(playlistId) | ||
} | ||
|
||
getPlaylistByLink = (token: string) => { | ||
return this.getPlaylistByLinkUseCase.execute(token) | ||
} | ||
} |
19 changes: 19 additions & 0 deletions
19
src/modules/playlists/use-cases/get-playlist-by-id/get-playlist-by-id.use-case.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
import { HTTPException } from 'hono/http-exception' | ||
import type { z } from 'zod' | ||
import type { IUseCase } from '#common/types' | ||
import type { PlaylistAPIResponseModel, PlaylistModel } from '#modules/playlists/models' | ||
import { useFetch } from '#common/helpers' | ||
import { Endpoints } from '#common/constants' | ||
import { createPlaylistPayload } from '#modules/playlists/helpers' | ||
|
||
export class GetPlaylistByIdUseCase implements IUseCase<string, z.infer<typeof PlaylistModel>> { | ||
constructor() {} | ||
|
||
async execute(id: string) { | ||
const response = await useFetch<z.infer<typeof PlaylistAPIResponseModel>>(Endpoints.playlists.id, { listid: id }) | ||
|
||
if (!response) throw new HTTPException(404, { message: 'playlist not found' }) | ||
|
||
return createPlaylistPayload(response) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
export * from './get-playlist-by-id.use-case' |
22 changes: 22 additions & 0 deletions
22
src/modules/playlists/use-cases/get-playlist-by-link/get-playlist-by-link.use-case.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
import { HTTPException } from 'hono/http-exception' | ||
import type { z } from 'zod' | ||
import type { IUseCase } from '#common/types' | ||
import type { PlaylistAPIResponseModel, PlaylistModel } from '#modules/playlists/models' | ||
import { useFetch } from '#common/helpers' | ||
import { Endpoints } from '#common/constants' | ||
import { createPlaylistPayload } from '#modules/playlists/helpers' | ||
|
||
export class GetPlaylistByLinkUseCase implements IUseCase<string, z.infer<typeof PlaylistModel>> { | ||
constructor() {} | ||
|
||
async execute(token: string) { | ||
const response = await useFetch<z.infer<typeof PlaylistAPIResponseModel>>(Endpoints.albums.link, { | ||
token, | ||
type: 'playlist' | ||
}) | ||
|
||
if (!response) throw new HTTPException(404, { message: 'playlist not found' }) | ||
|
||
return createPlaylistPayload(response) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
export * from './get-playlist-by-link.use-case' |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
export * from './get-playlist-by-id' | ||
export * from './get-playlist-by-link' |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,11 +1,13 @@ | ||
import { App } from './app' | ||
import { AlbumController, ArtistController, SearchController, SongController } from '#modules/index' | ||
import { PlaylistController } from '#modules/playlists/controllers' | ||
|
||
const app = new App([ | ||
new SearchController(), | ||
new SongController(), | ||
new AlbumController(), | ||
new ArtistController() | ||
new ArtistController(), | ||
new PlaylistController() | ||
]).getApp() | ||
|
||
export default app |