mirror of
https://github.com/ershisan99/podcaster.git
synced 2026-01-25 21:02:08 +00:00
feat: add episodes info to podcast page
This commit is contained in:
17
src/services/podcasts/dto/episode.dto.ts
Normal file
17
src/services/podcasts/dto/episode.dto.ts
Normal file
@@ -0,0 +1,17 @@
|
||||
import { Episode } from "../podcasts.types";
|
||||
|
||||
export class EpisodeDto {
|
||||
id: number;
|
||||
releaseDate: string;
|
||||
audioUrl: string;
|
||||
title: string;
|
||||
durationSeconds: number;
|
||||
|
||||
constructor(episode: Episode) {
|
||||
this.id = episode.trackId;
|
||||
this.title = episode.trackName;
|
||||
this.releaseDate = episode.releaseDate;
|
||||
this.audioUrl = episode.episodeUrl;
|
||||
this.durationSeconds = episode.trackTimeMillis / 1000;
|
||||
}
|
||||
}
|
||||
17
src/services/podcasts/dto/podcast-extra.dto.ts
Normal file
17
src/services/podcasts/dto/podcast-extra.dto.ts
Normal file
@@ -0,0 +1,17 @@
|
||||
import { PodcastDetails } from "../podcasts.types";
|
||||
|
||||
export class PodcastExtraDTO {
|
||||
id: number;
|
||||
trackCount: number;
|
||||
images: { small: string; medium: string; large: string };
|
||||
|
||||
constructor(data: PodcastDetails) {
|
||||
this.id = data.trackId;
|
||||
this.trackCount = data.trackCount;
|
||||
this.images = {
|
||||
small: data.artworkUrl60,
|
||||
medium: data.artworkUrl100,
|
||||
large: data.artworkUrl600,
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
import { Entry, ImImage } from "./podcasts.types";
|
||||
import { Entry, ImImage } from "../podcasts.types";
|
||||
|
||||
export class PodcastDTO {
|
||||
id: string;
|
||||
@@ -3,6 +3,7 @@ import { podcastsService } from "./podcasts.service";
|
||||
|
||||
const QUERY_KEYS = {
|
||||
TOP_PODCASTS: "podcasts/top",
|
||||
PODCAST_EPISODES: "podcasts/episodes",
|
||||
} as const;
|
||||
|
||||
export function useTopPodcastsQuery() {
|
||||
@@ -11,3 +12,11 @@ export function useTopPodcastsQuery() {
|
||||
queryFn: () => podcastsService.getTopPodcasts(),
|
||||
});
|
||||
}
|
||||
|
||||
export function usePodcastEpisodesQuery(podcastId?: string) {
|
||||
return useQuery({
|
||||
queryKey: [QUERY_KEYS.PODCAST_EPISODES, podcastId],
|
||||
queryFn: () => podcastsService.getEpisodesByPodcastId(podcastId ?? ""),
|
||||
enabled: !!podcastId,
|
||||
});
|
||||
}
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
import { GetEpisodesResponse, GetTopPodcastsResponse } from "./podcasts.types";
|
||||
import { PodcastDTO } from "./podcast.dto";
|
||||
import { PodcastDTO } from "./dto/podcast.dto";
|
||||
import { EpisodeDto } from "./dto/episode.dto";
|
||||
import { PodcastExtraDTO } from "./dto/podcast-extra.dto";
|
||||
|
||||
class PodcastsService {
|
||||
baseUrl = "https://itunes.apple.com";
|
||||
@@ -23,11 +25,30 @@ class PodcastsService {
|
||||
};
|
||||
url.search = new URLSearchParams(params).toString();
|
||||
|
||||
const response = await fetch(url);
|
||||
const data: GetEpisodesResponse = await response.json();
|
||||
const response: GetEpisodesResponse = await this.fetchWithoutCors(
|
||||
url.toString(),
|
||||
);
|
||||
let podcast: PodcastExtraDTO = {} as PodcastExtraDTO;
|
||||
const episodes: EpisodeDto[] = [];
|
||||
|
||||
//TODO: add dto
|
||||
return data;
|
||||
response.results.forEach((entry) => {
|
||||
if (entry.kind === "podcast-episode") {
|
||||
episodes.push(new EpisodeDto(entry));
|
||||
} else if (entry.kind === "podcast") {
|
||||
podcast = new PodcastExtraDTO(entry);
|
||||
}
|
||||
});
|
||||
|
||||
return { episodes, podcast: podcast };
|
||||
}
|
||||
|
||||
//TODO: move into a separate service
|
||||
private async fetchWithoutCors(url: string) {
|
||||
const response = await fetch(
|
||||
`https://api.allorigins.win/get?url=${encodeURIComponent(url)}`,
|
||||
);
|
||||
const data = await response.json();
|
||||
return JSON.parse(data.contents);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -165,46 +165,72 @@ export interface Id2 {
|
||||
|
||||
export interface GetEpisodesResponse {
|
||||
resultCount: number;
|
||||
results: PodcastDetails[];
|
||||
results: Array<Episode | PodcastDetails>;
|
||||
}
|
||||
|
||||
export interface Episode {
|
||||
country: string;
|
||||
artworkUrl160: string;
|
||||
episodeFileExtension: string;
|
||||
episodeContentType: string;
|
||||
artworkUrl600: string;
|
||||
collectionViewUrl: string;
|
||||
artistIds: number[];
|
||||
feedUrl: string;
|
||||
closedCaptioning: string;
|
||||
collectionId: number;
|
||||
collectionName: string;
|
||||
trackTimeMillis: number;
|
||||
trackId: number;
|
||||
trackName: string;
|
||||
shortDescription: string;
|
||||
description: string;
|
||||
contentAdvisoryRating: string;
|
||||
trackViewUrl: string;
|
||||
previewUrl: string;
|
||||
artworkUrl60: string;
|
||||
episodeUrl: string;
|
||||
releaseDate: string;
|
||||
episodeGuid: string;
|
||||
genres: Genre[];
|
||||
kind: "podcast-episode";
|
||||
wrapperType: string;
|
||||
}
|
||||
|
||||
export interface Genre {
|
||||
name: string;
|
||||
id: string;
|
||||
}
|
||||
|
||||
export interface PodcastDetails {
|
||||
wrapperType: string;
|
||||
kind: string;
|
||||
kind: "podcast";
|
||||
collectionId: number;
|
||||
trackId: number;
|
||||
artistName?: string;
|
||||
artistName: string;
|
||||
collectionName: string;
|
||||
trackName: string;
|
||||
collectionCensoredName?: string;
|
||||
trackCensoredName?: string;
|
||||
collectionCensoredName: string;
|
||||
trackCensoredName: string;
|
||||
collectionViewUrl: string;
|
||||
feedUrl: string;
|
||||
trackViewUrl: string;
|
||||
artworkUrl30?: string;
|
||||
artworkUrl30: string;
|
||||
artworkUrl60: string;
|
||||
artworkUrl100?: string;
|
||||
collectionPrice?: number;
|
||||
trackPrice?: number;
|
||||
collectionHdPrice?: number;
|
||||
artworkUrl100: string;
|
||||
collectionPrice: number;
|
||||
trackPrice: number;
|
||||
collectionHdPrice: number;
|
||||
releaseDate: string;
|
||||
collectionExplicitness?: string;
|
||||
trackExplicitness?: string;
|
||||
trackCount?: number;
|
||||
collectionExplicitness: string;
|
||||
trackExplicitness: string;
|
||||
trackCount: number;
|
||||
trackTimeMillis: number;
|
||||
country: string;
|
||||
currency?: string;
|
||||
primaryGenreName?: string;
|
||||
currency: string;
|
||||
primaryGenreName: string;
|
||||
contentAdvisoryRating: string;
|
||||
artworkUrl600: string;
|
||||
genreIds?: string[];
|
||||
closedCaptioning?: string;
|
||||
shortDescription?: string;
|
||||
episodeUrl?: string;
|
||||
episodeGuid?: string;
|
||||
description?: string;
|
||||
artworkUrl160?: string;
|
||||
episodeContentType?: string;
|
||||
episodeFileExtension?: string;
|
||||
previewUrl?: string;
|
||||
genreIds: string[];
|
||||
genres: string[];
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user