kopia lustrzana https://github.com/iv-org/invidious
				
				
				
			Add Search::Query class to handle search queries
							rodzic
							
								
									1e3425fdee
								
							
						
					
					
						commit
						a813955ad3
					
				| 
						 | 
				
			
			@ -79,6 +79,11 @@ module Invidious::Search
 | 
			
		|||
    )
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def is_default? : Bool
 | 
			
		||||
      return @date.none? && @type.all? && @duration.none? && \
 | 
			
		||||
         @features.none? && @sort.relevance?
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    # -------------------
 | 
			
		||||
    #  Invidious params
 | 
			
		||||
    # -------------------
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -0,0 +1,149 @@
 | 
			
		|||
module Invidious::Search
 | 
			
		||||
  class Query
 | 
			
		||||
    enum Type
 | 
			
		||||
      # Types related to YouTube
 | 
			
		||||
      Regular # Youtube search page
 | 
			
		||||
      Channel # Youtube channel search box
 | 
			
		||||
 | 
			
		||||
      # Types specific to Invidious
 | 
			
		||||
      Subscriptions # Search user subscriptions
 | 
			
		||||
      Playlist      # "Add playlist item" search
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    @type : Type = Type::Regular
 | 
			
		||||
 | 
			
		||||
    @raw_query : String
 | 
			
		||||
    @query : String = ""
 | 
			
		||||
 | 
			
		||||
    property filters : Filters = Filters.new
 | 
			
		||||
    property page : Int32
 | 
			
		||||
    property region : String?
 | 
			
		||||
    property channel : String = ""
 | 
			
		||||
 | 
			
		||||
    # Return true if @raw_query is either `nil` or empty
 | 
			
		||||
    private def empty_raw_query?
 | 
			
		||||
      return @raw_query.empty?
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    # Same as `empty_raw_query?`, but named for external use
 | 
			
		||||
    def empty?
 | 
			
		||||
      return self.empty_raw_query?
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    # Getter for the query string.
 | 
			
		||||
    # It is named `text` to reduce confusion (`search_query.text` makes more
 | 
			
		||||
    # sense than `search_query.query`)
 | 
			
		||||
    def text
 | 
			
		||||
      return @query
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    # Initialize a new search query.
 | 
			
		||||
    # Parameters are used to get the query string, the page number
 | 
			
		||||
    # and the search filters (if any). Type tells this function
 | 
			
		||||
    # where it is being called from (See `Type` above).
 | 
			
		||||
    def initialize(
 | 
			
		||||
      params : HTTP::Params,
 | 
			
		||||
      @type : Type = Type::Regular,
 | 
			
		||||
      @region : String? = nil
 | 
			
		||||
    )
 | 
			
		||||
      # Get the raw search query string (common to all search types). In
 | 
			
		||||
      # Regular search mode, also look for the `search_query` URL parameter
 | 
			
		||||
      if @type.regular?
 | 
			
		||||
        @raw_query = params["q"]? || params["search_query"]? || ""
 | 
			
		||||
      else
 | 
			
		||||
        @raw_query = params["q"]? || ""
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
      # Get the page number (also common to all search types)
 | 
			
		||||
      @page = params["page"]?.try &.to_i? || 1
 | 
			
		||||
 | 
			
		||||
      # Stop here is raw query in empty
 | 
			
		||||
      # NOTE: maybe raise in the future?
 | 
			
		||||
      return if self.empty_raw_query?
 | 
			
		||||
 | 
			
		||||
      # Specific handling
 | 
			
		||||
      case @type
 | 
			
		||||
      when .playlist?, .channel?
 | 
			
		||||
        # In "add playlist item" mode, filters are parsed from the query
 | 
			
		||||
        # string itself (legacy), and the channel is ignored.
 | 
			
		||||
        #
 | 
			
		||||
        # In "channel search" mode, filters are ignored, but we still parse
 | 
			
		||||
        # the query prevent transmission of legacy filters to youtube.
 | 
			
		||||
        #
 | 
			
		||||
        @filters, @query, @channel, _ = Filters.from_legacy_filters(@raw_query || "")
 | 
			
		||||
        #
 | 
			
		||||
      when .subscriptions?, .regular?
 | 
			
		||||
        if params["sp"]?
 | 
			
		||||
          # Parse the `sp` URL parameter (youtube compatibility)
 | 
			
		||||
          @filters = Filters.from_yt_params(params)
 | 
			
		||||
          @query = @raw_query || ""
 | 
			
		||||
        else
 | 
			
		||||
          # Parse invidious URL parameters (sort, date, etc...)
 | 
			
		||||
          @filters = Filters.from_iv_params(params)
 | 
			
		||||
          @channel = params["channel"]? || ""
 | 
			
		||||
 | 
			
		||||
          if @filters.default? && @raw_query.includes?(':')
 | 
			
		||||
            # Parse legacy filters from query
 | 
			
		||||
            @filters, @query, @channel, subs = Filters.from_legacy_filters(@raw_query || "")
 | 
			
		||||
          else
 | 
			
		||||
            @query = @raw_query || ""
 | 
			
		||||
          end
 | 
			
		||||
 | 
			
		||||
          if !@channel.empty?
 | 
			
		||||
            # Switch to channel search mode (filters will be ignored)
 | 
			
		||||
            @type = Type::Channel
 | 
			
		||||
          elsif subs
 | 
			
		||||
            # Switch to subscriptions search mode
 | 
			
		||||
            @type = Type::Subscriptions
 | 
			
		||||
          end
 | 
			
		||||
        end
 | 
			
		||||
      end
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    # Run the search query using the corresponding search processor.
 | 
			
		||||
    # Returns either the results or an empty array of `SearchItem`.
 | 
			
		||||
    def process(user : Invidious::User? = nil) : Array(SearchItem) | Array(ChannelVideo)
 | 
			
		||||
      items = [] of SearchItem
 | 
			
		||||
 | 
			
		||||
      # Don't bother going further if search query is empty
 | 
			
		||||
      return items if self.empty_raw_query?
 | 
			
		||||
 | 
			
		||||
      case @type
 | 
			
		||||
      when .regular?, .playlist?
 | 
			
		||||
        all_items = search(@query, @filters, @page, @region)
 | 
			
		||||
        items = unnest_items(all_items)
 | 
			
		||||
        #
 | 
			
		||||
      when .channel?
 | 
			
		||||
        items = Processors.channel(@query, @page, @channel)
 | 
			
		||||
        #
 | 
			
		||||
      when .subscriptions?
 | 
			
		||||
        if user
 | 
			
		||||
          items = Processors.subscriptions(self, user.as(Invidious::User))
 | 
			
		||||
        end
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
      return items
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    # TODO: clean code
 | 
			
		||||
    private def unnest_items(all_items) : Array(SearchItem)
 | 
			
		||||
      items = [] of SearchItem
 | 
			
		||||
 | 
			
		||||
      # Light processing to flatten search results out of Categories.
 | 
			
		||||
      # They should ideally be supported in the future.
 | 
			
		||||
      all_items.each do |i|
 | 
			
		||||
        if i.is_a? Category
 | 
			
		||||
          i.contents.each do |nest_i|
 | 
			
		||||
            if !nest_i.is_a? Video
 | 
			
		||||
              items << nest_i
 | 
			
		||||
            end
 | 
			
		||||
          end
 | 
			
		||||
        else
 | 
			
		||||
          items << i
 | 
			
		||||
        end
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
      return items
 | 
			
		||||
    end
 | 
			
		||||
  end
 | 
			
		||||
end
 | 
			
		||||
		Ładowanie…
	
		Reference in New Issue