1
1
require " http"
2
2
require " xml"
3
+ require " json"
4
+
3
5
4
6
module Youtube
5
7
extend self
@@ -19,6 +21,8 @@ module Youtube
19
21
" official video" , " official music video" ,
20
22
]
21
23
24
+ alias NODES_CLASS = Array (Hash (String , String ))
25
+
22
26
# Finds a youtube url based off of the given information.
23
27
# The query to youtube is constructed like this:
24
28
# "<song_name> <artist_name> <search terms>"
@@ -63,7 +67,7 @@ module Youtube
63
67
# ...
64
68
# ]
65
69
private def rank_videos (song_name : String , artist_name : String ,
66
- query : String , nodes : Array (XML :: Node )) : Array (Hash (String , Int32 ))
70
+ query : String , nodes : Array (Hash ( String , String ) )) : Array (Hash (String , Int32 ))
67
71
points = [] of Hash (String , Int32 )
68
72
index = 0
69
73
@@ -149,32 +153,45 @@ module Youtube
149
153
150
154
# Finds valid video links from a `HTTP::Client.get` request
151
155
# Returns an `Array` of `XML::Node`
152
- private def get_video_link_nodes (doc : String ) : Array (XML ::Node )
153
- nodes = XML .parse(doc).xpath_nodes(" //a" )
154
- valid_nodes = [] of XML ::Node
156
+ private def get_video_link_nodes (response_body : String ) : NODES_CLASS
157
+ yt_initial_data : JSON ::Any = JSON .parse(" {}" )
155
158
156
- nodes.each do |node |
157
- if video_link_node?(node )
158
- valid_nodes.push(node )
159
+ response_body.each_line do |line |
160
+ if line.includes?( " window[ \" ytInitialData \" ] " )
161
+ yt_initial_data = JSON .parse(line.split( " = " )[ 1 ][ 0 .. - 2 ] )
159
162
end
160
163
end
161
164
162
- return valid_nodes
163
- end
164
-
165
- # Tests if the provided `XML::Node` has a valid link to a video
166
- # Returns a `Bool`
167
- private def video_link_node? (node : XML ::Node ) : Bool
168
- # If this passes, then the node links to a playlist, not a video
169
- if node[" href" ]?
170
- return false if node[" href" ].includes?(" &list=" )
165
+ if yt_initial_data == JSON .parse(" {}" )
166
+ puts " Youtube has changed the way it organizes its webpage, submit a bug"
167
+ puts " on https://github.com/cooperhammond/irs"
168
+ exit(1 )
171
169
end
172
170
173
- VALID_LINK_CLASSES .each do |valid_class |
174
- if node[" class" ]?
175
- return true if node[" class" ].includes?(valid_class)
171
+ # where the vid metadata lives
172
+ yt_initial_data = yt_initial_data[" contents" ][" twoColumnSearchResultsRenderer" ][" primaryContents" ][" sectionListRenderer" ][" contents" ]
173
+
174
+ video_metadata = [] of Hash (String , String )
175
+
176
+ i = 0
177
+ while true
178
+ begin
179
+ # video title
180
+ raw_metadata = yt_initial_data[0 ][" itemSectionRenderer" ][" contents" ][i][" videoRenderer" ]
181
+
182
+ metadata = {} of String => String
183
+
184
+ metadata[" title" ] = raw_metadata[" title" ][" runs" ][0 ][" text" ].as_s
185
+ metadata[" href" ] = raw_metadata[" navigationEndpoint" ][" commandMetadata" ][" webCommandMetadata" ][" url" ].as_s
186
+
187
+ video_metadata.push(metadata)
188
+ rescue IndexError
189
+ break
190
+ rescue Exception
176
191
end
192
+ i += 1
177
193
end
178
- return false
194
+
195
+ return video_metadata
179
196
end
180
197
end
0 commit comments