mirror of
				https://github.com/iv-org/invidious.git
				synced 2025-11-04 06:31:57 +00:00 
			
		
		
		
	Create a search processors module
This commit is contained in:
		@@ -35,6 +35,7 @@ require "./invidious/frontend/*"
 | 
			
		||||
require "./invidious/*"
 | 
			
		||||
require "./invidious/channels/*"
 | 
			
		||||
require "./invidious/user/*"
 | 
			
		||||
require "./invidious/search/*"
 | 
			
		||||
require "./invidious/routes/**"
 | 
			
		||||
require "./invidious/jobs/**"
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -262,7 +262,7 @@ module Invidious::Routes::API::V1::Channels
 | 
			
		||||
    page = env.params.query["page"]?.try &.to_i?
 | 
			
		||||
    page ||= 1
 | 
			
		||||
 | 
			
		||||
    search_results = channel_search(query, page, ucid)
 | 
			
		||||
    search_results = Invidious::Search::Processors.channel(query, page, ucid)
 | 
			
		||||
    JSON.build do |json|
 | 
			
		||||
      json.array do
 | 
			
		||||
        search_results.each do |item|
 | 
			
		||||
 
 | 
			
		||||
@@ -5,35 +5,6 @@ class ChannelSearchException < InfoException
 | 
			
		||||
  end
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
def channel_search(query, page, channel) : Array(SearchItem)
 | 
			
		||||
  response = YT_POOL.client &.get("/channel/#{channel}")
 | 
			
		||||
 | 
			
		||||
  if response.status_code == 404
 | 
			
		||||
    response = YT_POOL.client &.get("/user/#{channel}")
 | 
			
		||||
    response = YT_POOL.client &.get("/c/#{channel}") if response.status_code == 404
 | 
			
		||||
    initial_data = extract_initial_data(response.body)
 | 
			
		||||
    ucid = initial_data.dig?("header", "c4TabbedHeaderRenderer", "channelId").try(&.as_s?)
 | 
			
		||||
    raise ChannelSearchException.new(channel) if !ucid
 | 
			
		||||
  else
 | 
			
		||||
    ucid = channel
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  continuation = produce_channel_search_continuation(ucid, query, page)
 | 
			
		||||
  response_json = YoutubeAPI.browse(continuation)
 | 
			
		||||
 | 
			
		||||
  continuation_items = response_json["onResponseReceivedActions"]?
 | 
			
		||||
    .try &.[0]["appendContinuationItemsAction"]["continuationItems"]
 | 
			
		||||
 | 
			
		||||
  return [] of SearchItem if !continuation_items
 | 
			
		||||
 | 
			
		||||
  items = [] of SearchItem
 | 
			
		||||
  continuation_items.as_a.select(&.as_h.has_key?("itemSectionRenderer")).each do |item|
 | 
			
		||||
    extract_item(item["itemSectionRenderer"]["contents"].as_a[0]).try { |t| items << t }
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  return items
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
def search(query, search_params = produce_search_params(content_type: "all"), region = nil) : Array(SearchItem)
 | 
			
		||||
  return [] of SearchItem if query.empty?
 | 
			
		||||
 | 
			
		||||
@@ -175,11 +146,6 @@ def produce_channel_search_continuation(ucid, query, page)
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
def process_search_query(query, page, user, region)
 | 
			
		||||
  if user
 | 
			
		||||
    user = user.as(Invidious::User)
 | 
			
		||||
    view_name = "subscriptions_#{sha256(user.email)}"
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  channel = nil
 | 
			
		||||
  content_type = "all"
 | 
			
		||||
  date = ""
 | 
			
		||||
@@ -215,16 +181,11 @@ def process_search_query(query, page, user, region)
 | 
			
		||||
  search_query = (query.split(" ") - operators).join(" ")
 | 
			
		||||
 | 
			
		||||
  if channel
 | 
			
		||||
    items = channel_search(search_query, page, channel)
 | 
			
		||||
    items = Invidious::Search::Processors.channel(search_query, page, channel)
 | 
			
		||||
  elsif subscriptions
 | 
			
		||||
    if view_name
 | 
			
		||||
      items = PG_DB.query_all("SELECT id,title,published,updated,ucid,author,length_seconds FROM (
 | 
			
		||||
      SELECT *,
 | 
			
		||||
      to_tsvector(#{view_name}.title) ||
 | 
			
		||||
      to_tsvector(#{view_name}.author)
 | 
			
		||||
      as document
 | 
			
		||||
      FROM #{view_name}
 | 
			
		||||
      ) v_search WHERE v_search.document @@ plainto_tsquery($1) LIMIT 20 OFFSET $2;", search_query, (page - 1) * 20, as: ChannelVideo)
 | 
			
		||||
    if user
 | 
			
		||||
      user = user.as(Invidious::User)
 | 
			
		||||
      items = Invidious::Search::Processors.subscriptions(query, page, user)
 | 
			
		||||
    else
 | 
			
		||||
      items = [] of ChannelVideo
 | 
			
		||||
    end
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										54
									
								
								src/invidious/search/processors.cr
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										54
									
								
								src/invidious/search/processors.cr
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,54 @@
 | 
			
		||||
module Invidious::Search
 | 
			
		||||
  module Processors
 | 
			
		||||
    extend self
 | 
			
		||||
 | 
			
		||||
    # Search a youtube channel
 | 
			
		||||
    # TODO: clean code, and rely more on YoutubeAPI
 | 
			
		||||
    def channel(query, page, channel) : Array(SearchItem)
 | 
			
		||||
      response = YT_POOL.client &.get("/channel/#{channel}")
 | 
			
		||||
 | 
			
		||||
      if response.status_code == 404
 | 
			
		||||
        response = YT_POOL.client &.get("/user/#{channel}")
 | 
			
		||||
        response = YT_POOL.client &.get("/c/#{channel}") if response.status_code == 404
 | 
			
		||||
        initial_data = extract_initial_data(response.body)
 | 
			
		||||
        ucid = initial_data.dig?("header", "c4TabbedHeaderRenderer", "channelId").try(&.as_s?)
 | 
			
		||||
        raise ChannelSearchException.new(channel) if !ucid
 | 
			
		||||
      else
 | 
			
		||||
        ucid = channel
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
      continuation = produce_channel_search_continuation(ucid, query, page)
 | 
			
		||||
      response_json = YoutubeAPI.browse(continuation)
 | 
			
		||||
 | 
			
		||||
      continuation_items = response_json["onResponseReceivedActions"]?
 | 
			
		||||
        .try &.[0]["appendContinuationItemsAction"]["continuationItems"]
 | 
			
		||||
 | 
			
		||||
      return [] of SearchItem if !continuation_items
 | 
			
		||||
 | 
			
		||||
      items = [] of SearchItem
 | 
			
		||||
      continuation_items.as_a.select(&.as_h.has_key?("itemSectionRenderer")).each do |item|
 | 
			
		||||
        extract_item(item["itemSectionRenderer"]["contents"].as_a[0]).try { |t| items << t }
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
      return items
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    # Search inside of user subscriptions
 | 
			
		||||
    def subscriptions(query, page, user : Invidious::User) : Array(ChannelVideo)
 | 
			
		||||
      view_name = "subscriptions_#{sha256(user.email)}"
 | 
			
		||||
 | 
			
		||||
      return PG_DB.query_all("
 | 
			
		||||
        SELECT id,title,published,updated,ucid,author,length_seconds
 | 
			
		||||
        FROM (
 | 
			
		||||
          SELECT *,
 | 
			
		||||
          to_tsvector(#{view_name}.title) ||
 | 
			
		||||
          to_tsvector(#{view_name}.author)
 | 
			
		||||
          as document
 | 
			
		||||
          FROM #{view_name}
 | 
			
		||||
        ) v_search WHERE v_search.document @@ plainto_tsquery($1) LIMIT 20 OFFSET $2;",
 | 
			
		||||
        query, (page - 1) * 20,
 | 
			
		||||
        as: ChannelVideo
 | 
			
		||||
      )
 | 
			
		||||
    end
 | 
			
		||||
  end
 | 
			
		||||
end
 | 
			
		||||
		Reference in New Issue
	
	Block a user