You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
137 lines
3.4 KiB
137 lines
3.4 KiB
import map from 'lodash/map'
|
|
import last from 'lodash/last'
|
|
import uniq from 'lodash/uniq'
|
|
import filter from 'lodash/filter'
|
|
import reduce from 'lodash/reduce'
|
|
import concat from 'lodash/concat'
|
|
import orderBy from 'lodash/orderBy'
|
|
import isEmpty from 'lodash/isEmpty'
|
|
import groupBy from 'lodash/groupBy'
|
|
|
|
import type {
|
|
Videos,
|
|
Episodes,
|
|
Episode,
|
|
} from 'requests'
|
|
|
|
import type { Chapters, Urls } from 'features/MultiSourcePlayer/types'
|
|
|
|
import type { PlaylistOption } from '../../types'
|
|
import { FULL_GAME_KEY } from '../../helpers/buildPlaylists'
|
|
|
|
const getUniquePeriods = (videos: Videos) => uniq(map(videos, ({ period }) => period))
|
|
|
|
type Video = {
|
|
duration: number,
|
|
period: number,
|
|
urls: Urls,
|
|
}
|
|
|
|
const getVideoByPeriod = (videos: Videos, period: number) => {
|
|
const videosWithSamePeriod = filter(videos, { period })
|
|
if (isEmpty(videosWithSamePeriod)) return null
|
|
|
|
const urls = reduce(
|
|
videosWithSamePeriod,
|
|
(acc: Urls, video) => ({
|
|
...acc,
|
|
[video.quality]: video.url,
|
|
}),
|
|
{},
|
|
)
|
|
const [video] = videosWithSamePeriod
|
|
return {
|
|
duration: video.duration,
|
|
period: video.period,
|
|
urls,
|
|
}
|
|
}
|
|
|
|
const getVideoByPeriods = (videos: Videos, periods: Array<number>) => (
|
|
reduce(
|
|
periods,
|
|
(acc: Array<Video>, period) => {
|
|
const video = getVideoByPeriod(videos, period)
|
|
return video ? concat(acc, video) : acc
|
|
},
|
|
[],
|
|
)
|
|
)
|
|
|
|
const getFullMatchChapters = (videos: Array<Video>) => {
|
|
const sortedVideos = orderBy(videos, ({ period }) => period)
|
|
return reduce(
|
|
sortedVideos,
|
|
(acc: Chapters, video) => {
|
|
const prevVideoEndMs = last(acc)?.endMs || 0
|
|
const endMs = prevVideoEndMs + video.duration
|
|
const nextChapter = {
|
|
duration: video.duration,
|
|
endMs,
|
|
endOffsetMs: endMs,
|
|
period: video.period,
|
|
startMs: prevVideoEndMs,
|
|
startOffsetMs: 0,
|
|
urls: video.urls,
|
|
}
|
|
return concat(acc, nextChapter)
|
|
},
|
|
[],
|
|
)
|
|
}
|
|
|
|
const getEpisodeUrls = (urls: Urls, episode: Episode) => reduce(
|
|
urls,
|
|
(
|
|
acc: Urls,
|
|
url,
|
|
qulaity,
|
|
) => {
|
|
acc[qulaity] = `${url}#t=${episode.s},${episode.e}`
|
|
return acc
|
|
},
|
|
{},
|
|
)
|
|
|
|
const getPlaylistChapters = (videos: Array<Video>, episodes: Episodes) => {
|
|
const groupedByPeriods = groupBy(videos, ({ period }) => period)
|
|
return reduce(
|
|
episodes,
|
|
(acc: Chapters, episode) => {
|
|
const video = groupedByPeriods[episode.h]?.[0]
|
|
if (!video || episode.s >= episode.e) return acc
|
|
|
|
const episodeDuration = (episode.e - episode.s) * 1000
|
|
const prevVideoEndMs = last(acc)?.endMs || 0
|
|
const nextChapter = {
|
|
duration: episodeDuration,
|
|
endMs: prevVideoEndMs + episodeDuration,
|
|
endOffsetMs: episode.e * 1000,
|
|
period: video.period,
|
|
startMs: prevVideoEndMs,
|
|
startOffsetMs: episode.s * 1000,
|
|
urls: getEpisodeUrls(video.urls, episode),
|
|
}
|
|
return concat(acc, nextChapter)
|
|
},
|
|
[],
|
|
)
|
|
}
|
|
|
|
type Args = {
|
|
episodes: Episodes,
|
|
selectedPlaylist?: PlaylistOption,
|
|
videos: Videos,
|
|
}
|
|
|
|
export const buildChapters = ({
|
|
episodes,
|
|
selectedPlaylist,
|
|
videos,
|
|
}: Args) => {
|
|
const periods = getUniquePeriods(videos)
|
|
const highQualityVideos = getVideoByPeriods(videos, periods)
|
|
return selectedPlaylist?.id === FULL_GAME_KEY
|
|
? getFullMatchChapters(highQualityVideos)
|
|
: getPlaylistChapters(highQualityVideos, episodes)
|
|
}
|
|
|