mirror of
				https://github.com/cooperhammond/irs.git
				synced 2025-11-03 18:14:51 +00:00 
			
		
		
		
	Updated to new YT standards
This commit is contained in:
		
							parent
							
								
									10bd5fd969
								
							
						
					
					
						commit
						d7a4044d77
					
				| 
						 | 
					@ -146,7 +146,8 @@ class Song
 | 
				
			||||||
      FileUtils.mkdir_p(strpath)
 | 
					      FileUtils.mkdir_p(strpath)
 | 
				
			||||||
    end
 | 
					    end
 | 
				
			||||||
    safe_filename = @filename.gsub(/[\/]/, "").gsub("  ", " ")
 | 
					    safe_filename = @filename.gsub(/[\/]/, "").gsub("  ", " ")
 | 
				
			||||||
    File.rename("./" + @filename, (path / safe_filename).to_s)
 | 
					    FileUtils.cp("./" + @filename, (path / safe_filename).to_s)
 | 
				
			||||||
 | 
					    FileUtils.rm("./" + @filename)
 | 
				
			||||||
  end
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  # Provide metadata so that it doesn't have to find it. Useful for overwriting
 | 
					  # Provide metadata so that it doesn't have to find it. Useful for overwriting
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,5 +1,7 @@
 | 
				
			||||||
require "http"
 | 
					require "http"
 | 
				
			||||||
require "xml"
 | 
					require "xml"
 | 
				
			||||||
 | 
					require "json"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
module Youtube
 | 
					module Youtube
 | 
				
			||||||
  extend self
 | 
					  extend self
 | 
				
			||||||
| 
						 | 
					@ -19,6 +21,8 @@ module Youtube
 | 
				
			||||||
    "official video", "official music video",
 | 
					    "official video", "official music video",
 | 
				
			||||||
  ]
 | 
					  ]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  alias NODES_CLASS = Array(Hash(String, String))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  # Finds a youtube url based off of the given information.
 | 
					  # Finds a youtube url based off of the given information.
 | 
				
			||||||
  # The query to youtube is constructed like this:
 | 
					  # The query to youtube is constructed like this:
 | 
				
			||||||
  #   "<song_name> <artist_name> <search terms>"
 | 
					  #   "<song_name> <artist_name> <search terms>"
 | 
				
			||||||
| 
						 | 
					@ -63,7 +67,7 @@ module Youtube
 | 
				
			||||||
  #   ...
 | 
					  #   ...
 | 
				
			||||||
  # ]
 | 
					  # ]
 | 
				
			||||||
  private def rank_videos(song_name : String, artist_name : String,
 | 
					  private def rank_videos(song_name : String, artist_name : String,
 | 
				
			||||||
                          query : String, nodes : Array(XML::Node)) : Array(Hash(String, Int32))
 | 
					                          query : String, nodes : Array(Hash(String, String))) : Array(Hash(String, Int32))
 | 
				
			||||||
    points = [] of Hash(String, Int32)
 | 
					    points = [] of Hash(String, Int32)
 | 
				
			||||||
    index = 0
 | 
					    index = 0
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -149,32 +153,45 @@ module Youtube
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  # Finds valid video links from a `HTTP::Client.get` request
 | 
					  # Finds valid video links from a `HTTP::Client.get` request
 | 
				
			||||||
  # Returns an `Array` of `XML::Node`
 | 
					  # Returns an `Array` of `XML::Node`
 | 
				
			||||||
  private def get_video_link_nodes(doc : String) : Array(XML::Node)
 | 
					  private def get_video_link_nodes(response_body : String) : NODES_CLASS
 | 
				
			||||||
    nodes = XML.parse(doc).xpath_nodes("//a")
 | 
					    yt_initial_data : JSON::Any = JSON.parse("{}")
 | 
				
			||||||
    valid_nodes = [] of XML::Node
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
    nodes.each do |node|
 | 
					    response_body.each_line do |line|
 | 
				
			||||||
      if video_link_node?(node)
 | 
					      if line.includes?("window[\"ytInitialData\"]")
 | 
				
			||||||
        valid_nodes.push(node)
 | 
					        yt_initial_data = JSON.parse(line.split(" = ")[1][0..-2])
 | 
				
			||||||
      end
 | 
					      end
 | 
				
			||||||
    end
 | 
					    end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    return valid_nodes
 | 
					    if yt_initial_data == JSON.parse("{}")
 | 
				
			||||||
  end
 | 
					      puts "Youtube has changed the way it organizes its webpage, submit a bug"
 | 
				
			||||||
 | 
					      puts "on https://github.com/cooperhammond/irs"
 | 
				
			||||||
  # Tests if the provided `XML::Node` has a valid link to a video
 | 
					      exit(1)
 | 
				
			||||||
  # Returns a `Bool`
 | 
					 | 
				
			||||||
  private def video_link_node?(node : XML::Node) : Bool
 | 
					 | 
				
			||||||
    # If this passes, then the node links to a playlist, not a video
 | 
					 | 
				
			||||||
    if node["href"]?
 | 
					 | 
				
			||||||
      return false if node["href"].includes?("&list=")
 | 
					 | 
				
			||||||
    end
 | 
					    end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    VALID_LINK_CLASSES.each do |valid_class|
 | 
					    # where the vid metadata lives
 | 
				
			||||||
      if node["class"]?
 | 
					    yt_initial_data = yt_initial_data["contents"]["twoColumnSearchResultsRenderer"]["primaryContents"]["sectionListRenderer"]["contents"]
 | 
				
			||||||
        return true if node["class"].includes?(valid_class)
 | 
					
 | 
				
			||||||
 | 
					    video_metadata = [] of Hash(String, String)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    i = 0
 | 
				
			||||||
 | 
					    while true
 | 
				
			||||||
 | 
					      begin
 | 
				
			||||||
 | 
					        # video title
 | 
				
			||||||
 | 
					        raw_metadata = yt_initial_data[0]["itemSectionRenderer"]["contents"][i]["videoRenderer"]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        metadata = {} of String => String
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        metadata["title"] = raw_metadata["title"]["runs"][0]["text"].as_s
 | 
				
			||||||
 | 
					        metadata["href"] = raw_metadata["navigationEndpoint"]["commandMetadata"]["webCommandMetadata"]["url"].as_s
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					        video_metadata.push(metadata)
 | 
				
			||||||
 | 
					      rescue IndexError
 | 
				
			||||||
 | 
					        break
 | 
				
			||||||
 | 
					      rescue Exception
 | 
				
			||||||
      end
 | 
					      end
 | 
				
			||||||
 | 
					      i += 1
 | 
				
			||||||
    end
 | 
					    end
 | 
				
			||||||
    return false
 | 
					
 | 
				
			||||||
 | 
					    return video_metadata
 | 
				
			||||||
  end
 | 
					  end
 | 
				
			||||||
end
 | 
					end
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in a new issue