Skip to content
This repository was archived by the owner on Nov 27, 2024. It is now read-only.

Commit

Permalink
InnerTube v2 update (#153)
Browse files Browse the repository at this point in the history
* Update InnerTube

* Fix errors and warnings in Utils and Database classes

* Add a GetLocals method since the new InnerTube doesn't have it

* Fix errors in API endpoints

* fix this error i caused

* Fix the errors in the contexts

* Implement recommendations endpoint

* Fix empty ctor excuses

* Reimplement autocomplete

* Fix some API stuff

* Fix contexts

* Fix all controllers except YoutubeController.cs

* Update YoutubeController.cs

* Fix all views

* Disable authorization

* Implement some renderers for the search view

* Move renderer cshtml files to their own directory

* Move ContainerRenderer to its own file

as its mostly the same in multiple places, this should reduce the amount of repeated code

* forgot to update these two

* small css fixes

* Implement the renderers for the watch page

* kuylar vs. her own code, round 2

* New badges!

* Playlist first video IDs

* Shelf titles

* changed like 2 stuff

* Fix playlists

* Round 3

* Round... 4?

* Channel avatars

* idrk why that exploded

* Fix the player box aspect ratio

* Update null renderers

* posts in search

* Implement search chips

* hate css

* Round 5!

* Fix authentication

* Fix namespaces

* Add parserLanguage to where its needed

* Fix the like counter

* Fix ToKMB

* Implement ResolveUrl where needed

* Update the channel header

* Round 6

* Implement the featured tab of the channel

* Implement the shorts tab in channel

* Implement the community tab

* Finish all channel tabs

* fix Utils.cs

* Update LTPlayer

* Fix the custom CSS

* Fix the player returning the wrong video URLs

* Fix the issues in the player

* Fix the wrongly called subscribe button

* Fix search chips

* fix the ugly filters button

* fix the player overflowing sideways on mobile

* Clamp player aspect ratios

* Add a message if only format 18 is available

* Fix the non-JS player overflowing to the side

* Fix nullref in mixes

* Make the mobile comment panel scrollable

* Make the comments not overscroll to the recommendations

* Fix mobile guide z-index

* Add a redirect for /{videoId}

* Fix trailers

* Round- wait we skipped 7? whatever Round 8

* Add UI for trailers

* Fix the HLS manifest url validity checker

* Fix chips

* Fix broken if statements (two of them)

* Fix community posts

* hey look - a place to get a nullreferenceexception!

* Add a small thing

* Remove unused file

* Add the about tab to channels

* Fix the max-lines property

* Make the tagline always max out at a single line. Also make it a normal text instead of a hyperlink to /about

* Fix community posts in search results

* Fix localization in channel posts

* Implement search sidebars

* Final round, if no other bugs come up

* Implement exception renderers

* Make the subscription feed API use renderercontainers

* Add a null check to the playlist panel

* Fix nullrefs in video caching

* Fix nullable ints in the database exploding the playlists

* Fix video player obstructing other elements

* Fix broken html tags in video titles

* Add localization to the premiere trailer text

* Add a &page param to search endpoints

* Make stats in channel about page wider

* Fix playlists

* Fix wrong hyperlinks

* Add editable to PlaylistVideoRendererData

* Fix the avatar in the video player

* Fix titles turning into 6px line of dots and dashes

Even though LTv3 has localization, it won't support morse code

* Remove underline from channel tagline

* RecognitionShelfRenderer

* Update InnerTube for bug fixes

* but we stay silly

* Add movieRenderer

* API: Serialize enums to strings

* API: Make the UserData folllow the rest of the naming scheme

* That breaks the entire program and wipes the database clean. Use JsonProperty instead

* API: Add editable field to playlists

* API: Fix all the nullrefs in the playlist endpoint

* API: Add exact publish date to the subscription feed videos

* Make sure the search page doesnt explode when the sidebar throws an exception

* Fix the trailer screen eating all the mouse events

* Make it so videos without valid HLS manifests has UseHls = false

* Fix the comment headers

* Make the version have the major version in it

* Fix wrong renderer name

* Fix nullref in /api/playlist with LT playlists

* Add video player error messages to the channel page

* Fix messagerenderer in playlist sidebar

* Implement all sidebars

* Add query corrector

* guess whos stupid

* Fix playlist APIs

* Fix channel continuation API

* Bump InnerTube

* Fix MPD manifests

* Fix the whole video page crashing if there are no storyboards

* yea

* Delete the nojs quality switcher as YouTube now only provides itag 18

* Add the new shelf renderer

* Fix the promoted video player

* Fix the age restriction button
  • Loading branch information
kuylar authored Aug 6, 2024
1 parent 9acb04d commit ca11d15
Show file tree
Hide file tree
Showing 71 changed files with 5,241 additions and 3,542 deletions.
4 changes: 2 additions & 2 deletions Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,10 @@ COPY ["LightTube/LightTube.csproj", "LightTube/"]
RUN dotnet restore -a $TARGETARCH "LightTube/LightTube.csproj"
COPY . .
WORKDIR "/src/LightTube"
RUN dotnet build "LightTube.csproj" -a $TARGETARCH -c Release -o /app/build /p:Version=`date +0.%Y.%m.%d`
RUN dotnet build "LightTube.csproj" -a $TARGETARCH -c Release -o /app/build /p:Version=`date +3.%Y.%m.%d`

FROM build AS publish
RUN dotnet publish "LightTube.csproj" -a $TARGETARCH -c Release -o /app/publish /p:Version=`date +0.%Y.%m.%d`
RUN dotnet publish "LightTube.csproj" -a $TARGETARCH -c Release -o /app/publish /p:Version=`date +3.%Y.%m.%d`

FROM base AS final
WORKDIR /app
Expand Down
209 changes: 136 additions & 73 deletions LightTube/ApiModels/ApiChannel.cs
Original file line number Diff line number Diff line change
@@ -1,84 +1,147 @@
using InnerTube;
using InnerTube.Models;
using InnerTube.Protobuf;
using InnerTube.Renderers;
using LightTube.Database.Models;
using LightTube.Localization;
using Endpoint = InnerTube.Protobuf.Endpoint;

namespace LightTube.ApiModels;

public class ApiChannel
{
public string Id { get; }
public string Title { get; }
public IEnumerable<Thumbnail> Avatars { get; }
public IEnumerable<Thumbnail> Banner { get; }
public IEnumerable<Badge> Badges { get; }
public IEnumerable<ChannelLink> PrimaryLinks { get; }
public IEnumerable<ChannelLink> SecondaryLinks { get; }
public string SubscriberCountText { get; }
public IEnumerable<string> EnabledTabs { get; }
public IEnumerable<IRenderer> Contents { get; }
public string? Continuation { get; }
public ChannelHeader? Header { get; }
public ChannelTab[] Tabs { get; }
public ChannelMetadata? Metadata { get; }
public RendererContainer[] Contents { get; }

public ApiChannel(InnerTubeChannelResponse channel)
{
if (channel.Header != null)
{
Id = channel.Header.Id;
Title = channel.Header.Title;
Avatars = channel.Header.Avatars;
Banner = channel.Header.Banner;
Badges = channel.Header.Badges;
PrimaryLinks = channel.Header.PrimaryLinks;
SecondaryLinks = channel.Header.SecondaryLinks;
SubscriberCountText = channel.Header.SubscriberCountText;
}
else
{
Id = channel.Metadata.Id;
Title = channel.Metadata.Title;
Avatars = channel.Metadata.Avatar;
Banner = [];
Badges = [];
PrimaryLinks = [];
SecondaryLinks = [];
SubscriberCountText = "Unavailable";
}
public ApiChannel(InnerTubeChannel channel)
{
Header = channel.Header;
Tabs = channel.Tabs.ToArray();
Metadata = channel.Metadata;
Contents = channel.Contents;
}

EnabledTabs = channel.EnabledTabs.Select(x => x.ToString());
Contents = channel.Contents;
Continuation =
(channel.Contents.FirstOrDefault(x => x is ContinuationItemRenderer) as ContinuationItemRenderer)?.Token;
}
public ApiChannel(ContinuationResponse continuation)
{
Header = null;
Tabs = [];
Metadata = null;
List<RendererContainer> renderers = new();
renderers.AddRange(continuation.Results);
if (continuation.ContinuationToken != null)
renderers.Add(new RendererContainer
{
Type = "continuation",
OriginalType = "continuationItemRenderer",
Data = new ContinuationRendererData
{
ContinuationToken = continuation.ContinuationToken
}
});
Contents = renderers.ToArray();
}

public ApiChannel(InnerTubeContinuationResponse channel)
{
Id = "";
Title = "";
Avatars = [];
Banner = [];
Badges = [];
PrimaryLinks = [];
SecondaryLinks = [];
SubscriberCountText = "Unavailable";
EnabledTabs = [];
Contents = channel.Contents;
Continuation = channel.Continuation;
}

public ApiChannel(DatabaseUser channel)
{
Id = channel.LTChannelID;
Title = channel.UserID;
Avatars = [];
Banner = [];
Badges = [];
PrimaryLinks = [];
SecondaryLinks = [];
SubscriberCountText = "LightTube account";
EnabledTabs =
[
ChannelTabs.Playlists.ToString()
];
Contents = [channel.PlaylistRenderers()];
Continuation = null;
}
public ApiChannel(DatabaseUser channel, LocalizationManager localization)
{
Header = new ChannelHeader(new PageHeaderRenderer
{
PageTitle = channel.UserID,
Content = new RendererWrapper
{
PageHeaderViewModel = new PageHeaderViewModel
{
Image = new RendererWrapper
{
DecoratedAvatarViewModel = new DecoratedAvatarViewModel
{
Avatar = new RendererWrapper
{
AvatarViewModel = new AvatarViewModel
{
Image = new Image()
}
}
},
ImageBannerViewModel = new ImageBannerViewModel
{
Image = new Image()
}
},
Metadata = new RendererWrapper
{
ContentMetadataViewModel = new ContentMetadataViewModel
{
MetadataRows =
{
new ContentMetadataViewModel.Types.MetadataRow
{
MetadataParts =
{
new ContentMetadataViewModel.Types.MetadataRow.Types.
AttributedDescriptionWrapper
{
Text = new AttributedDescription
{
Content = $"@LT_{channel.UserID}"
}
}
}
},
new ContentMetadataViewModel.Types.MetadataRow
{
MetadataParts =
{
new ContentMetadataViewModel.Types.MetadataRow.Types.
AttributedDescriptionWrapper
{
Text = new AttributedDescription
{
Content = "LightTube Channel"
}
},
new ContentMetadataViewModel.Types.MetadataRow.Types.
AttributedDescriptionWrapper
{
Text = new AttributedDescription
{
Content = ""
}
}
}
}
}
}
},
Description = new RendererWrapper
{
DescriptionPreviewViewModel = new DescriptionPreviewViewModel
{
Content = new AttributedDescription
{
Content = ""
}
}
}
}
}
}, channel.LTChannelID, "en");
Tabs =
[
new ChannelTab(new TabRenderer
{
Endpoint = new Endpoint
{
BrowseEndpoint = new BrowseEndpoint
{
Params = "EglwbGF5bGlzdHPyBgQKAkIA"
}
},
Title = "Playlists",
Selected = true
})
];
Metadata = null;
Contents = channel.PlaylistRenderers(localization).ToArray();
}
}
7 changes: 7 additions & 0 deletions LightTube/ApiModels/ApiLocals.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
namespace LightTube.ApiModels;

public class ApiLocals
{
public Dictionary<string, string> Languages { get; set; }
public Dictionary<string, string> Regions { get; set; }
}
119 changes: 41 additions & 78 deletions LightTube/ApiModels/ApiPlaylist.cs
Original file line number Diff line number Diff line change
@@ -1,91 +1,54 @@
using InnerTube;
using InnerTube.Models;
using InnerTube.Protobuf;
using InnerTube.Renderers;
using LightTube.Database;
using LightTube.Database.Models;
using LightTube.Localization;
using Endpoint = InnerTube.Protobuf.Endpoint;

namespace LightTube.ApiModels;

public class ApiPlaylist
{
public string Id { get; }
public IEnumerable<string> Alerts { get; }
public string Title { get; }
public string Description { get; }
public IEnumerable<Badge> Badges { get; }
public Channel Channel { get; }
public IEnumerable<Thumbnail> Thumbnails { get; }
public string LastUpdated { get; }
public string VideoCountText { get; }
public string ViewCountText { get; }
public PlaylistContinuationInfo? Continuation { get; }
public IEnumerable<PlaylistVideoRenderer> Videos { get; }
public string Id { get; }
public string[] Alerts { get; }
public RendererContainer[] Contents { get; }
public RendererContainer[] Chips { get; }
public string? Continuation { get; }
public PlaylistSidebar? Sidebar { get; }
public bool Editable { get; }

public ApiPlaylist(InnerTubePlaylist playlist)
{
Id = playlist.Id;
Alerts = playlist.Alerts;
Title = playlist.Sidebar.Title;
Description = playlist.Sidebar.Description;
Badges = playlist.Sidebar.Badges;
Channel = playlist.Sidebar.Channel;
Thumbnails = playlist.Sidebar.Thumbnails;
LastUpdated = playlist.Sidebar.LastUpdated;
VideoCountText = playlist.Sidebar.VideoCountText;
ViewCountText = playlist.Sidebar.ViewCountText;
Continuation = playlist.Continuation;
Videos = playlist.Videos;
}
public ApiPlaylist(InnerTubePlaylist playlist)
{
Id = playlist.Id;
Alerts = playlist.Alerts;
Contents = playlist.Contents;
Chips = playlist.Chips;
Continuation = playlist.Continuation;
Sidebar = playlist.Sidebar;
Editable = false;
}

public ApiPlaylist(InnerTubeContinuationResponse playlist)
{
Id = "";
Alerts = [];
Title = "";
Description = "";
Badges = [];
Channel = new Channel();
Thumbnails = [];
LastUpdated = "";
VideoCountText = "";
ViewCountText = "";
Continuation = playlist.Continuation is not null ? InnerTube.Utils.UnpackPlaylistContinuation(playlist.Continuation) : null;
Videos = playlist.Contents.Cast<PlaylistVideoRenderer>();
}
public ApiPlaylist(ContinuationResponse playlist)
{
Id = "";
Alerts = [];
Contents = playlist.Results;
Chips = [];
Continuation = playlist.ContinuationToken;
Sidebar = null;
Editable = false;
}

public ApiPlaylist(DatabasePlaylist playlist)
{
Id = playlist.Id;
Alerts = [];
Title = playlist.Name;
Description = playlist.Description;
Badges = [];
DatabaseUser user = DatabaseManager.Users.GetUserFromId(playlist.Author).Result!;
Channel = new Channel
{
Id = user.LTChannelID,
Title = user.UserID,
Avatar = null,
Subscribers = null,
Badges = []
};
Thumbnails =
[
new Thumbnail
{
Width = null,
Height = null,
Url = new Uri($"https://i.ytimg.com/vi/{playlist.VideoIds.FirstOrDefault()}/hqdefault.jpg")
}
];
LastUpdated = $"Last updated on {playlist.LastUpdated:MMM d, yyyy}";
VideoCountText = playlist.VideoIds.Count switch
{
0 => "No videos",
1 => "1 video",
_ => $"{playlist.VideoIds.Count} videos"
};
ViewCountText = "LightTube playlist";
Continuation = null;
Videos = DatabaseManager.Playlists.GetPlaylistVideos(playlist.Id, false);
}
public ApiPlaylist(DatabasePlaylist playlist, DatabaseUser author, LocalizationManager localization, DatabaseUser? user)
{
Id = playlist.Id;
Alerts = [];
Contents = DatabaseManager.Playlists.GetPlaylistVideoRenderers(playlist.Id, playlist.Author == user?.UserID, localization).ToArray();
Chips = [];
Continuation = null;
Sidebar = new PlaylistSidebar(playlist.GetHeaderRenderer(author, localization), "en");
Editable = playlist.Author == user?.UserID;
}
}
Loading

0 comments on commit ca11d15

Please sign in to comment.