Add API endpoint for Clips

This commit is contained in:
ChunkyProgrammer 2023-11-14 23:35:11 -05:00
parent 8c22e6a640
commit b344d98c25
4 changed files with 67 additions and 13 deletions

View file

@ -363,4 +363,47 @@ module Invidious::Routes::API::V1::Videos
end end
end end
end end
def self.clips(env)
locale = env.get("preferences").as(Preferences).locale
env.response.content_type = "application/json"
clip_id = env.params.url["id"]
region = env.params.query["region"]?
proxy = {"1", "true"}.any? &.== env.params.query["local"]?
response = YoutubeAPI.resolve_url("https://www.youtube.com/clip/#{clip_id}")
return error_json(400, "Invalid clip ID") if response["error"]?
video_id = response.dig?("endpoint", "watchEndpoint", "videoId").try &.as_s
return error_json(400, "Invalid clip ID") if video_id.nil?
start_time = nil
end_time = nil
clip_title = nil
if params = response.dig?("endpoint", "watchEndpoint", "params").try &.as_s
start_time, end_time, clip_title = parse_clip_parameters(params)
end
begin
video = get_video(video_id, region: region)
rescue ex : NotFoundException
return error_json(404, ex)
rescue ex
return error_json(500, ex)
end
return JSON.build do |json|
json.object do
json.field "startTime", start_time
json.field "endTime", end_time
json.field "clipTitle", clip_title
json.field "video" do
Invidious::JSONify::APIv1.video(video, json, locale: locale, proxy: proxy)
end
end
end
end
end end

View file

@ -276,19 +276,9 @@ module Invidious::Routes::Watch
if video_id = response.dig?("endpoint", "watchEndpoint", "videoId") if video_id = response.dig?("endpoint", "watchEndpoint", "videoId")
if params = response.dig?("endpoint", "watchEndpoint", "params").try &.as_s if params = response.dig?("endpoint", "watchEndpoint", "params").try &.as_s
decoded_protobuf = params.try { |i| URI.decode_www_form(i) } start_time, end_time, _ = parse_clip_parameters(params)
.try { |i| Base64.decode(i) } env.params.query["start"] = start_time.to_s
.try { |i| IO::Memory.new(i) } env.params.query["end"] = end_time.to_s
.try { |i| Protodec::Any.parse(i) }
start_time = decoded_protobuf
.try(&.["50:0:embedded"]["2:1:varint"].as_i64)
end_time = decoded_protobuf
.try(&.["50:0:embedded"]["3:2:varint"].as_i64)
env.params.query["start"] = (start_time / 1000).to_s
env.params.query["end"] = (end_time / 1000).to_s
end end
return env.redirect "/watch?v=#{video_id}&#{env.params.query}" return env.redirect "/watch?v=#{video_id}&#{env.params.query}"

View file

@ -235,6 +235,7 @@ module Invidious::Routing
get "/api/v1/captions/:id", {{namespace}}::Videos, :captions get "/api/v1/captions/:id", {{namespace}}::Videos, :captions
get "/api/v1/annotations/:id", {{namespace}}::Videos, :annotations get "/api/v1/annotations/:id", {{namespace}}::Videos, :annotations
get "/api/v1/comments/:id", {{namespace}}::Videos, :comments get "/api/v1/comments/:id", {{namespace}}::Videos, :comments
get "/api/v1/clips/:id", {{namespace}}::Videos, :clips
# Feeds # Feeds
get "/api/v1/trending", {{namespace}}::Feeds, :trending get "/api/v1/trending", {{namespace}}::Feeds, :trending

View file

@ -0,0 +1,20 @@
require "json"
# returns start_time, end_time and clip_title
def parse_clip_parameters(params) : {Float64, Float64, String}
decoded_protobuf = params.try { |i| URI.decode_www_form(i) }
.try { |i| Base64.decode(i) }
.try { |i| IO::Memory.new(i) }
.try { |i| Protodec::Any.parse(i) }
start_time = decoded_protobuf
.try(&.["50:0:embedded"]["2:1:varint"].as_i64)
end_time = decoded_protobuf
.try(&.["50:0:embedded"]["3:2:varint"].as_i64)
clip_title = decoded_protobuf
.try(&.["50:0:embedded"]["4:3:string"].as_s)
return (start_time / 1000), (end_time / 1000), clip_title
end