Skip to content
Permalink

Comparing changes

This is a direct comparison between two commits made in this repository or its related repositories. View the default comparison for this range or learn more about diff comparisons.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also . Learn more about diff comparisons here.
base repository: LuanRT/YouTube.js
Failed to load repositories. Confirm that selected base ref is valid, then try again.
Loading
base: 65c1c44303f96910a1c784e700dca0cc409f1b49
Choose a base ref
..
head repository: LuanRT/YouTube.js
Failed to load repositories. Confirm that selected head ref is valid, then try again.
Loading
compare: 497fe0575a3c4b184bd046e4c5c83656afa011ec
Choose a head ref
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -7,6 +7,7 @@

* **parser:** Add `play_all_button` to `Shelf` ([#345](https://github.com/LuanRT/YouTube.js/issues/345)) ([427db5b](https://github.com/LuanRT/YouTube.js/commit/427db5bbc2bf3e8ec60371d504c2ab1cdae6e918))
* **parser:** add `view_playlist` to `Playlist` ([#348](https://github.com/LuanRT/YouTube.js/issues/348)) ([9cb4530](https://github.com/LuanRT/YouTube.js/commit/9cb45302997771d909487b1ecba6f38655abef48))
* **yt:** add support for movie items and trailers ([#349](https://github.com/LuanRT/YouTube.js/issues/349)) ([9f1c31d](https://github.com/LuanRT/YouTube.js/commit/9f1c31d7a09532e80a187b14acceff31c22579bf))

## [3.3.0](https://github.com/LuanRT/YouTube.js/compare/v3.2.0...v3.3.0) (2023-03-09)

6 changes: 6 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -300,6 +300,9 @@ Retrieves video info, including playback data and even layout elements such as m
- `<info>#getLiveChat()`
- Returns a LiveChat instance.

- `<info>#getTrailerInfo()`
- Returns trailer info in a new `VideoInfo` instance, or `null` if none. Typically available for non-purchased movies or films.

- `<info>#chooseFormat(options)`
- Used to choose streaming data formats.

@@ -324,6 +327,9 @@ Retrieves video info, including playback data and even layout elements such as m
- `<info>#autoplay_video_endpoint`
- Returns the endpoint of the video for Autoplay.

- `<info>#has_trailer`
- Checks if trailer is available.

- `<info>#page`
- Returns original InnerTube response (sanitized).

34 changes: 34 additions & 0 deletions src/parser/classes/GridMovie.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
import Parser from '../index.js';
import Text from './misc/Text.js';
import Thumbnail from './misc/Thumbnail.js';
import NavigationEndpoint from './NavigationEndpoint.js';
import { YTNode } from '../helpers.js';
import MetadataBadge from './MetadataBadge.js';

class GridMovie extends YTNode {
static type = 'GridMovie';

id: string;
title: Text;
thumbnails: Thumbnail[];
duration: Text | null;
endpoint: NavigationEndpoint;
badges: MetadataBadge[];
metadata: Text;
thumbnail_overlays;

constructor(data: any) {
super();
const length_alt = data.thumbnailOverlays.find((overlay: any) => overlay.hasOwnProperty('thumbnailOverlayTimeStatusRenderer'))?.thumbnailOverlayTimeStatusRenderer;
this.id = data.videoId;
this.title = new Text(data.title);
this.thumbnails = Thumbnail.fromResponse(data.thumbnail);
this.duration = data.lengthText ? new Text(data.lengthText) : length_alt?.text ? new Text(length_alt.text) : null;
this.endpoint = new NavigationEndpoint(data.navigationEndpoint);
this.badges = Parser.parseArray<MetadataBadge>(data.badges, MetadataBadge);
this.metadata = new Text(data.metadata);
this.thumbnail_overlays = Parser.parseArray(data.thumbnailOverlays);
}
}

export default GridMovie;
25 changes: 25 additions & 0 deletions src/parser/classes/HorizontalMovieList.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import Parser from '../index.js';
import { YTNode } from '../helpers.js';
import Button from './Button.js';

class HorizontalMovieList extends YTNode {
static type = 'HorizontalMovieList';

items;
previous_button: Button | null;
next_button: Button | null;

constructor(data: any) {
super();
this.items = Parser.parseArray(data.items);
this.previous_button = Parser.parseItem<Button>(data.previousButton, Button);
this.next_button = Parser.parseItem<Button>(data.nextButton, Button);
}

// XXX: alias for consistency
get contents() {
return this.items;
}
}

export default HorizontalMovieList;
32 changes: 32 additions & 0 deletions src/parser/classes/PlayerLegacyDesktopYpcTrailer.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
import { YTNode } from '../helpers.js';
import { Parser, RawNode } from '../index.js';
import YpcTrailer from './YpcTrailer.js';

class PlayerLegacyDesktopYpcTrailer extends YTNode {
static type = 'PlayerLegacyDesktopYpcTrailer';

video_id: string;
title: string;
thumbnail: string;
offer_headline: string;
offer_description: string;
offer_id: string;
offer_button_text: string;
video_message: string;
trailer: YpcTrailer | null;

constructor(data: RawNode) {
super();
this.video_id = data.trailerVideoId;
this.title = data.itemTitle;
this.thumbnail = data.itemThumbnail;
this.offer_headline = data.offerHeadline;
this.offer_description = data.offerDescription;
this.offer_id = data.offerId;
this.offer_button_text = data.offerButtonText;
this.video_message = data.fullVideoMessage;
this.trailer = Parser.parseItem<YpcTrailer>(data.ypcTrailer, YpcTrailer);
}
}

export default PlayerLegacyDesktopYpcTrailer;
17 changes: 17 additions & 0 deletions src/parser/classes/YpcTrailer.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import { YTNode } from '../helpers.js';
import { RawNode } from '../index.js';

class YpcTrailer extends YTNode {
static type = 'YpcTrailer';

video_message: string;
player_response;

constructor(data: RawNode) {
super();
this.video_message = data.fullVideoMessage;
this.player_response = data.unserializedPlayerResponse;
}
}

export default YpcTrailer;
12 changes: 12 additions & 0 deletions src/parser/map.ts
Original file line number Diff line number Diff line change
@@ -194,6 +194,8 @@ import { default as GridChannel } from './classes/GridChannel.js';
export { GridChannel };
import { default as GridHeader } from './classes/GridHeader.js';
export { GridHeader };
import { default as GridMovie } from './classes/GridMovie.js';
export { GridMovie };
import { default as GridPlaylist } from './classes/GridPlaylist.js';
export { GridPlaylist };
import { default as GridVideo } from './classes/GridVideo.js';
@@ -226,6 +228,8 @@ import { default as HorizontalCardList } from './classes/HorizontalCardList.js';
export { HorizontalCardList };
import { default as HorizontalList } from './classes/HorizontalList.js';
export { HorizontalList };
import { default as HorizontalMovieList } from './classes/HorizontalMovieList.js';
export { HorizontalMovieList };
import { default as IconLink } from './classes/IconLink.js';
export { IconLink };
import { default as InteractiveTabbedHeader } from './classes/InteractiveTabbedHeader.js';
@@ -452,6 +456,8 @@ import { default as PlayerErrorMessage } from './classes/PlayerErrorMessage.js';
export { PlayerErrorMessage };
import { default as PlayerLegacyDesktopYpcOffer } from './classes/PlayerLegacyDesktopYpcOffer.js';
export { PlayerLegacyDesktopYpcOffer };
import { default as PlayerLegacyDesktopYpcTrailer } from './classes/PlayerLegacyDesktopYpcTrailer.js';
export { PlayerLegacyDesktopYpcTrailer };
import { default as PlayerLiveStoryboardSpec } from './classes/PlayerLiveStoryboardSpec.js';
export { PlayerLiveStoryboardSpec };
import { default as PlayerMicroformat } from './classes/PlayerMicroformat.js';
@@ -674,6 +680,8 @@ import { default as WatchNextEndScreen } from './classes/WatchNextEndScreen.js';
export { WatchNextEndScreen };
import { default as WatchNextTabbedResults } from './classes/WatchNextTabbedResults.js';
export { WatchNextTabbedResults };
import { default as YpcTrailer } from './classes/YpcTrailer.js';
export { YpcTrailer };
import { default as AnchoredSection } from './classes/ytkids/AnchoredSection.js';
export { AnchoredSection };
import { default as KidsCategoriesHeader } from './classes/ytkids/KidsCategoriesHeader.js';
@@ -780,6 +788,7 @@ const map: Record<string, YTNodeConstructor> = {
Grid,
GridChannel,
GridHeader,
GridMovie,
GridPlaylist,
GridVideo,
GuideCollapsibleEntry,
@@ -796,6 +805,7 @@ const map: Record<string, YTNodeConstructor> = {
HistorySuggestion,
HorizontalCardList,
HorizontalList,
HorizontalMovieList,
IconLink,
InteractiveTabbedHeader,
ItemSection,
@@ -904,6 +914,7 @@ const map: Record<string, YTNodeConstructor> = {
PlayerCaptionsTracklist,
PlayerErrorMessage,
PlayerLegacyDesktopYpcOffer,
PlayerLegacyDesktopYpcTrailer,
PlayerLiveStoryboardSpec,
PlayerMicroformat,
PlayerOverlay,
@@ -1015,6 +1026,7 @@ const map: Record<string, YTNodeConstructor> = {
WatchCardSectionSequence,
WatchNextEndScreen,
WatchNextTabbedResults,
YpcTrailer,
AnchoredSection,
KidsCategoriesHeader,
KidsCategoryTab,
22 changes: 22 additions & 0 deletions src/parser/youtube/VideoInfo.ts
Original file line number Diff line number Diff line change
@@ -21,6 +21,7 @@ import VideoPrimaryInfo from '../classes/VideoPrimaryInfo.js';
import VideoSecondaryInfo from '../classes/VideoSecondaryInfo.js';
import LiveChatWrap from './LiveChat.js';
import NavigationEndpoint from '../classes/NavigationEndpoint.js';
import PlayerLegacyDesktopYpcTrailer from '../classes/PlayerLegacyDesktopYpcTrailer.js';

import type CardCollection from '../classes/CardCollection.js';
import type Endscreen from '../classes/Endscreen.js';
@@ -334,6 +335,20 @@ class VideoInfo {
return new LiveChatWrap(this);
}

/**
* Retrieves trailer info if available (typically for non-purchased movies or films).
* @returns `VideoInfo` for the trailer, or `null` if none.
*/
getTrailerInfo(): VideoInfo | null {
if (this.has_trailer) {
const player_response = this.playability_status.error_screen?.as(PlayerLegacyDesktopYpcTrailer).trailer?.player_response;
if (player_response) {
return new VideoInfo([ { data: player_response } as ApiResponse ], this.#actions, this.#player, this.#cpn);
}
}
return null;
}

/**
* Selects the format that best matches the given options.
* @param options - Options
@@ -395,6 +410,13 @@ class VideoInfo {
return this.autoplay?.sets?.[0]?.autoplay_video || null;
}

/**
* Checks if trailer is available.
*/
get has_trailer(): boolean {
return !!this.playability_status.error_screen?.is(PlayerLegacyDesktopYpcTrailer);
}

/**
* Get songs used in the video.
*/