Subversion Repositories yt_downloader

Rev

Rev 13 | Rev 16 | Go to most recent revision | Only display areas with differences | Regard whitespace | Details | Blame | Last modification | View Log | RSS feed

Rev 13 Rev 14
1
<?php
1
<?php
2
 
2
 
3
// ViaThinkSoft YouTube Downloader Functions 2.1
3
// ViaThinkSoft YouTube Downloader Functions 2.3
4
// Revision: 2022-02-06
4
// Revision: 2022-02-06
5
// Author: Daniel Marschall <www.daniel-marschall.de>
5
// Author: Daniel Marschall <www.daniel-marschall.de>
6
// Licensed under the terms of the Apache 2.0 License
6
// Licensed under the terms of the Apache 2.0 License
7
 
7
 
8
// Get API key:   https://console.developers.google.com/apis/credentials
8
// Get API key:   https://console.developers.google.com/apis/credentials
9
// Test API here: https://developers.google.com/apis-explorer/?hl=de#p/youtube/v3/youtube.playlistItems.list
9
// Test API here: https://developers.google.com/apis-explorer/?hl=de#p/youtube/v3/youtube.playlistItems.list
10
 
10
 
11
$yt_apikey = null;
11
$yt_apikey = null;
12
$yt_apikey_callback = null;
12
$yt_apikey_callback = null;
13
 
13
 
14
function yt_set_apikey($apikey) {
14
function yt_set_apikey($apikey) {
15
        global $yt_apikey;
15
        global $yt_apikey;
16
        $yt_apikey = $apikey;
16
        $yt_apikey = $apikey;
17
}
17
}
18
 
18
 
19
function yt_set_apikey_callback($apikey_callback) {
19
function yt_set_apikey_callback($apikey_callback) {
20
        global $yt_apikey_callback;
20
        global $yt_apikey_callback;
21
        $yt_apikey_callback = $apikey_callback;
21
        $yt_apikey_callback = $apikey_callback;
22
}
22
}
23
 
23
 
24
function yt_get_apikey() {
24
function yt_get_apikey() {
25
        global $yt_apikey, $yt_apikey_callback;
25
        global $yt_apikey, $yt_apikey_callback;
26
 
26
 
27
        if (!empty($yt_apikey_callback)) {
27
        if (!empty($yt_apikey_callback)) {
28
                $apikey = call_user_func($yt_apikey_callback);
28
                $apikey = call_user_func($yt_apikey_callback);
29
                if (!yt_check_apikey_syntax($apikey)) throw new Exception("Invalid API key '$apikey'");
29
                if (!yt_check_apikey_syntax($apikey)) throw new Exception("Invalid API key '$apikey'");
30
        } else if (!empty($yt_apikey)) {
30
        } else if (!empty($yt_apikey)) {
31
                $apikey = $yt_apikey;
31
                $apikey = $yt_apikey;
32
                if (!yt_check_apikey_syntax($apikey)) throw new Exception("Invalid API key '$apikey'");
32
                if (!yt_check_apikey_syntax($apikey)) throw new Exception("Invalid API key '$apikey'");
33
        } else {
33
        } else {
34
                throw new Exception("This function requires a YouTube API key.\n");
34
                throw new Exception("This function requires a YouTube API key.\n");
35
        }
35
        }
36
 
36
 
37
        return $apikey;
37
        return $apikey;
38
}
38
}
39
 
39
 
40
function yt_playlist_items($playlist_id, $maxresults=-1) {
40
function yt_playlist_items($playlist_id, $maxresults=-1) {
41
        $out = array();
41
        $out = array();
42
 
42
 
43
        $next_page_token = '';
43
        $next_page_token = '';
44
 
44
 
45
        do {
45
        do {
46
                $cont = file_get_contents('https://www.googleapis.com/youtube/v3/playlistItems?part=snippet&playlistId='.urlencode($playlist_id).'&maxResults=50'.(($next_page_token!='') ? '&pageToken='.urlencode($next_page_token) : '').'&key='.urlencode(yt_get_apikey()));
46
                $cont = file_get_contents('https://www.googleapis.com/youtube/v3/playlistItems?part=snippet&playlistId='.urlencode($playlist_id).'&maxResults=50'.(($next_page_token!='') ? '&pageToken='.urlencode($next_page_token) : '').'&key='.urlencode(yt_get_apikey()));
47
                if (!$cont) return false;
47
                if (!$cont) return false;
48
 
48
 
49
                $obj = json_decode($cont, true);
49
                $obj = json_decode($cont, true);
50
                if (!$obj) return false;
50
                if (!$obj) return false;
51
 
51
 
52
                if (!isset($obj['items'])) return false;
52
                if (!isset($obj['items'])) return false;
53
 
53
 
54
                foreach ($obj['items'] as $item) {
54
                foreach ($obj['items'] as $item) {
55
                        if ($item['snippet']['resourceId']['kind'] == 'youtube#video') {
55
                        if ($item['snippet']['resourceId']['kind'] == 'youtube#video') {
56
                                $title    = $item['snippet']['title'];
56
                                $title    = $item['snippet']['title'];
57
                                $video_id = $item['snippet']['resourceId']['videoId'];
57
                                $video_id = $item['snippet']['resourceId']['videoId'];
58
                                $out[] = array($video_id, $title);
58
                                $out[] = array($video_id, $title);
59
                                if (($maxresults != -1) && ($maxresults == count($out))) return $out;
59
                                if (($maxresults != -1) && ($maxresults == count($out))) return $out;
60
                        }
60
                        }
61
                }
61
                }
62
 
62
 
63
                $next_page_token = isset($obj['nextPageToken']) ? $obj['nextPageToken'] : '';
63
                $next_page_token = isset($obj['nextPageToken']) ? $obj['nextPageToken'] : '';
64
        } while ($next_page_token != '');
64
        } while ($next_page_token != '');
65
 
65
 
66
        return $out;
66
        return $out;
67
}
67
}
68
 
68
 
69
function yt_get_channel_id($username) {
69
function yt_get_channel_id($username) {
70
        $cont = file_get_contents('https://www.googleapis.com/youtube/v3/channels?key='.urlencode(yt_get_apikey()).'&forUsername='.urlencode($username).'&part=id');
70
        $cont = file_get_contents('https://www.googleapis.com/youtube/v3/channels?key='.urlencode(yt_get_apikey()).'&forUsername='.urlencode($username).'&part=id');
71
        if (!$cont) return false;
71
        if (!$cont) return false;
72
 
72
 
73
        $obj = json_decode($cont, true);
73
        $obj = json_decode($cont, true);
74
        if (!$obj) return false;
74
        if (!$obj) return false;
75
 
75
 
76
        if (!isset($obj['items'])) return false;
76
        if (!isset($obj['items'])) return false;
77
 
77
 
78
        foreach ($obj['items'] as $item) {
78
        foreach ($obj['items'] as $item) {
79
                if ($item['kind'] == 'youtube#channel') {
79
                if ($item['kind'] == 'youtube#channel') {
80
                        return $item['id'];
80
                        return $item['id'];
81
                }
81
                }
82
        }
82
        }
83
}
83
}
84
 
84
 
85
function yt_get_channel_id_and_stats($username) {
85
function yt_get_channel_id_and_stats($username) {
86
        $cont = file_get_contents('https://www.googleapis.com/youtube/v3/channels?key='.urlencode(yt_get_apikey()).'&forUsername='.urlencode($username).'&part=id,statistics');
86
        $cont = file_get_contents('https://www.googleapis.com/youtube/v3/channels?key='.urlencode(yt_get_apikey()).'&forUsername='.urlencode($username).'&part=id,statistics');
87
        if (!$cont) return false;
87
        if (!$cont) return false;
88
 
88
 
89
        $obj = json_decode($cont, true);
89
        $obj = json_decode($cont, true);
90
        if (!$obj) return false;
90
        if (!$obj) return false;
91
 
91
 
92
        if (!isset($obj['items'])) return false;
92
        if (!isset($obj['items'])) return false;
93
 
93
 
94
        foreach ($obj['items'] as $item) {
94
        foreach ($obj['items'] as $item) {
95
                if ($item['kind'] == 'youtube#channel') {
95
                if ($item['kind'] == 'youtube#channel') {
96
                        return array($item['id'], $item['statistics']);
96
                        return array($item['id'], $item['statistics']);
97
                }
97
                }
98
        }
98
        }
99
}
99
}
100
 
100
 
101
function yt_get_channel_stats($channel_id) {
101
function yt_get_channel_stats($channel_id) {
102
        $cont = file_get_contents('https://www.googleapis.com/youtube/v3/channels?key='.urlencode(yt_get_apikey()).'&id='.urlencode($channel_id).'&part=statistics');
102
        $cont = file_get_contents('https://www.googleapis.com/youtube/v3/channels?key='.urlencode(yt_get_apikey()).'&id='.urlencode($channel_id).'&part=statistics');
103
        if (!$cont) return false;
103
        if (!$cont) return false;
104
 
104
 
105
        $obj = json_decode($cont, true);
105
        $obj = json_decode($cont, true);
106
        if (!$obj) return false;
106
        if (!$obj) return false;
107
 
107
 
108
        if (!isset($obj['items'])) return false; //totalResults could be 0
108
        if (!isset($obj['items'])) return false; //totalResults could be 0
109
 
109
 
110
        foreach ($obj['items'] as $item) {
110
        foreach ($obj['items'] as $item) {
111
                if ($item['kind'] == 'youtube#channel') {
111
                if ($item['kind'] == 'youtube#channel') {
112
                        return $item['statistics'];
112
                        return $item['statistics'];
113
                }
113
                }
114
        }
114
        }
115
}
115
}
116
 
116
 
117
function yt_get_playlist_stats($playlist_id) {
117
function yt_get_playlist_stats($playlist_id) {
118
        $cont = file_get_contents('https://www.googleapis.com/youtube/v3/playlists?part=contentDetails&id='.urlencode($playlist_id).'&key='.urlencode(yt_get_apikey()));
118
        $cont = file_get_contents('https://www.googleapis.com/youtube/v3/playlists?part=contentDetails&id='.urlencode($playlist_id).'&key='.urlencode(yt_get_apikey()));
119
        if (!$cont) return false;
119
        if (!$cont) return false;
120
 
120
 
121
        $obj = json_decode($cont, true);
121
        $obj = json_decode($cont, true);
122
        if (!$obj) return false;
122
        if (!$obj) return false;
123
 
123
 
124
        if (!isset($obj['items'])) return false;
124
        if (!isset($obj['items'])) return false;
125
 
125
 
126
        foreach ($obj['items'] as $item) {
126
        foreach ($obj['items'] as $item) {
127
                if ($item['kind'] == 'youtube#playlist') {
127
                if ($item['kind'] == 'youtube#playlist') {
128
                        return $item['contentDetails'];
128
                        return $item['contentDetails'];
129
                }
129
                }
130
        }
130
        }
131
}
131
}
132
 
132
 
133
function yt_channel_items($channel_id, $searchterms='', $maxresults=-1) {
133
function yt_channel_items($channel_id, $searchterms='', $maxresults=-1) {
134
        $out = array();
134
        $out = array();
135
 
135
 
136
        $next_page_token = '';
136
        $next_page_token = '';
137
 
137
 
138
        do {
138
        do {
139
                $cont = file_get_contents('https://www.googleapis.com/youtube/v3/search?part=snippet&channelId='.urlencode($channel_id).(($searchterms!='') ? '&q='.urlencode($searchterms) : '').'&maxResults=50'.(($next_page_token!='') ? '&pageToken='.urlencode($next_page_token) : '').'&key='.urlencode(yt_get_apikey()));
139
                $cont = file_get_contents('https://www.googleapis.com/youtube/v3/search?part=snippet&channelId='.urlencode($channel_id).(($searchterms!='') ? '&q='.urlencode($searchterms) : '').'&maxResults=50'.(($next_page_token!='') ? '&pageToken='.urlencode($next_page_token) : '').'&key='.urlencode(yt_get_apikey()));
140
                if (!$cont) return false;
140
                if (!$cont) return false;
141
 
141
 
142
                $obj = json_decode($cont, true);
142
                $obj = json_decode($cont, true);
143
                if (!$obj) return false;
143
                if (!$obj) return false;
144
 
144
 
145
                if (!isset($obj['items'])) return false;
145
                if (!isset($obj['items'])) return false;
146
 
146
 
147
                foreach ($obj['items'] as $item) {
147
                foreach ($obj['items'] as $item) {
148
                        if ($item['id']['kind'] == 'youtube#video') {
148
                        if ($item['id']['kind'] == 'youtube#video') {
149
                                $title    = $item['snippet']['title'];
149
                                $title    = $item['snippet']['title'];
150
                                $video_id = $item['id']['videoId'];
150
                                $video_id = $item['id']['videoId'];
151
                                $out[] = array($video_id, $title);
151
                                $out[] = array($video_id, $title);
152
                                if (($maxresults != -1) && ($maxresults == count($out))) return $out;
152
                                if (($maxresults != -1) && ($maxresults == count($out))) return $out;
153
                        }
153
                        }
154
                }
154
                }
155
 
155
 
156
                $next_page_token = isset($obj['nextPageToken']) ? $obj['nextPageToken'] : '';
156
                $next_page_token = isset($obj['nextPageToken']) ? $obj['nextPageToken'] : '';
157
        } while ($next_page_token != '');
157
        } while ($next_page_token != '');
158
 
158
 
159
        return $out;
159
        return $out;
160
}
160
}
161
 
161
 
162
// Acceptable order values are: date, rating, relevance(default), title, videoCount, viewCount
162
// Acceptable order values are: date, rating, relevance(default), title, videoCount, viewCount
163
function yt_search_items($searchterms, $order='', $maxresults=-1) {
163
function yt_search_items($searchterms, $order='', $maxresults=-1) {
164
        $out = array();
164
        $out = array();
165
 
165
 
166
        $next_page_token = '';
166
        $next_page_token = '';
167
 
167
 
168
        do {
168
        do {
169
                $cont = file_get_contents('https://www.googleapis.com/youtube/v3/search?part=snippet&q='.urlencode($searchterms).(($order!='') ? '&order='.urlencode($order) : '').'&maxResults=50'.(($next_page_token!='') ? '&pageToken='.urlencode($next_page_token) : '').'&key='.urlencode(yt_get_apikey()));
169
                $cont = file_get_contents('https://www.googleapis.com/youtube/v3/search?part=snippet&q='.urlencode($searchterms).(($order!='') ? '&order='.urlencode($order) : '').'&maxResults=50'.(($next_page_token!='') ? '&pageToken='.urlencode($next_page_token) : '').'&key='.urlencode(yt_get_apikey()));
170
                if (!$cont) return false;
170
                if (!$cont) return false;
171
 
171
 
172
                $obj = json_decode($cont, true);
172
                $obj = json_decode($cont, true);
173
                if (!$obj) return false;
173
                if (!$obj) return false;
174
 
174
 
175
                if (!isset($obj['items'])) return false;
175
                if (!isset($obj['items'])) return false;
176
 
176
 
177
                foreach ($obj['items'] as $item) {
177
                foreach ($obj['items'] as $item) {
178
                        if ($item['id']['kind'] == 'youtube#video') {
178
                        if ($item['id']['kind'] == 'youtube#video') {
179
                                $title    = $item['snippet']['title'];
179
                                $title    = $item['snippet']['title'];
180
                                $video_id = $item['id']['videoId'];
180
                                $video_id = $item['id']['videoId'];
181
                                $out[] = array($video_id, $title);
181
                                $out[] = array($video_id, $title);
182
                                if (($maxresults != -1) && ($maxresults == count($out))) return $out;
182
                                if (($maxresults != -1) && ($maxresults == count($out))) return $out;
183
                        }
183
                        }
184
                }
184
                }
185
 
185
 
186
                $next_page_token = isset($obj['nextPageToken']) ? $obj['nextPageToken'] : '';
186
                $next_page_token = isset($obj['nextPageToken']) ? $obj['nextPageToken'] : '';
187
        } while ($next_page_token != '');
187
        } while ($next_page_token != '');
188
 
188
 
189
        return $out;
189
        return $out;
190
}
190
}
191
 
191
 
192
function getVideoIDFromURL($url) {
192
function getVideoIDFromURL($url) {
193
        // Extract video ID from the URL
193
        // Extract video ID from the URL
194
 
194
 
195
        $vid = false;
195
        $vid = false;
196
        $m = null;
196
        $m = null;
197
 
197
 
198
        # Usual format
198
        # Usual format
199
        if (($vid === false) && (preg_match("@https{0,1}://(www\\.|)youtube\\.com/watch(.*)(/|&|\\?)v=([a-zA-Z0-9_-]{11})@ismU", $url, $m))) {
199
        if (($vid === false) && (preg_match("@https{0,1}://(www\\.|)youtube\\.com/watch(.*)(/|&|\\?)v=([a-zA-Z0-9_-]{11})@ismU", $url, $m))) {
200
                $vid = $m[4];
200
                $vid = $m[4];
201
        }
201
        }
202
 
202
 
203
        # Short format
203
        # Short format
204
        if (($vid === false) && (preg_match("@https{0,1}://(www\\.|)youtu\\.be/([a-zA-Z0-9_-]{11})@ismU", $url, $m))) {
204
        if (($vid === false) && (preg_match("@https{0,1}://(www\\.|)youtu\\.be/([a-zA-Z0-9_-]{11})@ismU", $url, $m))) {
205
                $vid = $m[2];
205
                $vid = $m[2];
206
        }
206
        }
207
 
207
 
208
        # YouTube "Shorts"
208
        # YouTube "Shorts"
209
        if (($vid === false) && (preg_match("@https{0,1}://(www\\.|)youtube\\.com/shorts/([a-zA-Z0-9_-]{11})@ismU", $url, $m))) {
209
        if (($vid === false) && (preg_match("@https{0,1}://(www\\.|)youtube\\.com/shorts/([a-zA-Z0-9_-]{11})@ismU", $url, $m))) {
210
                $vid = $m[2];
210
                $vid = $m[2];
211
        }
211
        }
212
 
212
 
213
        return $vid;
213
        return $vid;
214
}
214
}
215
 
215
 
216
function getPlaylistIDFromURL($url) {
216
function getPlaylistIDFromURL($url) {
217
        $pid = false;
217
        $pid = false;
218
 
218
 
219
        # Usual format
219
        # Usual format
220
        $m = null;
220
        $m = null;
221
        if (($pid === false) && (preg_match("@https{0,1}://(www\\.|)youtube\\.com/(.*)(/|&|\\?)list=(.+)&@ismU", $url.'&', $m))) {
221
        if (($pid === false) && (preg_match("@https{0,1}://(www\\.|)youtube\\.com/(.*)(/|&|\\?)list=(.+)&@ismU", $url.'&', $m))) {
222
                $pid = $m[4];
222
                $pid = $m[4];
223
        }
223
        }
224
 
224
 
225
        return $pid;
225
        return $pid;
226
}
226
}
227
 
227
 
228
function yt_check_apikey_syntax($apikey) {
228
function yt_check_apikey_syntax($apikey) {
229
        return preg_match('@^[a-zA-Z0-9]{39}$@', $apikey);
229
        return preg_match('@^[a-zA-Z0-9]{39}$@', $apikey);
230
}
230
}
231
 
231
 
232
function yt_check_video_id($video_id) {
232
function yt_check_video_id($video_id) {
233
        return preg_match('@^[a-zA-Z0-9\-_]{11}$@', $video_id);
233
        return preg_match('@^[a-zA-Z0-9\-_]{11}$@', $video_id);
234
}
234
}
235
 
235
 
236
function yt_get_channel_id_from_custom_url($custom_url) {
236
function yt_get_channel_id_from_custom_url($custom_url) {
237
        // TODO: is there any API possibility??? API only accepts username and id ?!
237
        // TODO: is there any API possibility??? API only accepts username and id ?!
238
 
238
 
239
        // https://www.youtube.com/c/SASASMR
239
        // https://www.youtube.com/c/SASASMR
240
        // <link rel="canonical" href="https://www.youtube.com/channel/UCp4LfMtDfoa29kTlLnqQ5Mg">
240
        // <link rel="canonical" href="https://www.youtube.com/channel/UCp4LfMtDfoa29kTlLnqQ5Mg">
241
        // https://www.youtube.com/impaulsive
241
        // https://www.youtube.com/impaulsive
242
        // <link rel="canonical" href="https://www.youtube.com/channel/UCGeBogGDZ9W3dsGx-mWQGJA">
242
        // <link rel="canonical" href="https://www.youtube.com/channel/UCGeBogGDZ9W3dsGx-mWQGJA">
243
 
243
 
244
        $cont = file_get_contents($custom_url);
244
        $cont = file_get_contents($custom_url);
245
        if ($cont === false) {
245
        if ($cont === false) {
246
                throw new Exception("Cannot open $custom_url using file_get_contents.");
246
                throw new Exception("Cannot open $custom_url using file_get_contents.");
247
        }
247
        }
248
        if (!preg_match('@<link rel="canonical" href="https://www.youtube.com/channel/([^"]+)">@ismU', $cont, $m)) {
248
        if (!preg_match('@<link rel="canonical" href="https://www.youtube.com/channel/([^"]+)">@ismU', $cont, $m)) {
249
                return false;
249
                return false;
250
        }
250
        }
251
 
251
 
252
        return $m[1];
252
        return $m[1];
253
}
253
}
254
 
254
 
255
function yt_get_channel_id_from_url($channel_url) {
255
function yt_get_channel_id_from_url($channel_url) {
256
        $m = null;
256
        $m = null;
257
        if (preg_match("@https{0,1}://(www\\.|)youtube\\.com/user/(.*)(/|&|\\?)@ismU", $channel_url.'&', $m)) {
257
        if (preg_match("@https{0,1}://(www\\.|)youtube\\.com/user/(.*)(/|&|\\?)@ismU", $channel_url.'&', $m)) {
258
                // Username (deprecated feature. Not every channel has a username associated with it)
258
                // Username (deprecated feature. Not every channel has a username associated with it)
259
                // https://www.youtube.com/user/USERNAME
259
                // https://www.youtube.com/user/USERNAME
260
                $username = $m[2];
260
                $username = $m[2];
261
                $channel_id = yt_get_channel_id($username);
261
                $channel_id = yt_get_channel_id($username);
262
                return $channel_id;
262
                return $channel_id;
263
        } else if (preg_match("@https{0,1}://(www\\.|)youtube\\.com/channel/(.*)(/|&|\\?)@ismU", $channel_url.'&', $m)) {
263
        } else if (preg_match("@https{0,1}://(www\\.|)youtube\\.com/channel/(.*)(/|&|\\?)@ismU", $channel_url.'&', $m)) {
264
                // Real channel ID
264
                // Real channel ID
265
                // https://www.youtube.com/channel/ID
265
                // https://www.youtube.com/channel/ID
266
                $channel_id = $m[2];
266
                $channel_id = $m[2];
267
                return $channel_id;
267
                return $channel_id;
268
        } else if (preg_match("@https{0,1}://(www\\.|)youtube\\.com/(c/){0,1}(.*)(/|&|\\?)@ismU", $channel_url.'&', $m)) {
268
        } else if (preg_match("@https{0,1}://(www\\.|)youtube\\.com/(c/){0,1}(.*)(/|&|\\?)@ismU", $channel_url.'&', $m)) {
269
                // Channel custom URL
269
                // Channel custom URL
270
                // https://www.youtube.com/NAME or https://www.youtube.com/c/NAME
270
                // https://www.youtube.com/NAME or https://www.youtube.com/c/NAME
271
                return yt_get_channel_id_from_custom_url($channel_url);
271
                return yt_get_channel_id_from_custom_url($channel_url);
272
        } else {
272
        } else {
273
                return false;
273
                return false;
274
        }
274
        }
275
}
275
}
276
 
276
 
277
// Examples:
277
// Examples:
278
//yt_set_apikey(trim(file_get_contents(__DIR__ . '/.yt_api_key')));
278
//yt_set_apikey(trim(file_get_contents(__DIR__ . '/.yt_api_key')));
279
//print_r(yt_playlist_items('PL9GbGAd-gY1pyxZJIX5MOdYdRbdweVAID'));
279
//print_r(yt_playlist_items('PL9GbGAd-gY1pyxZJIX5MOdYdRbdweVAID'));
280
//print_r(yt_channel_items('UCjPjcMEAN64opOoNQE9GykA'));
280
//print_r(yt_channel_items('UCjPjcMEAN64opOoNQE9GykA'));
281
//print_r(yt_channel_items('UCjPjcMEAN64opOoNQE9GykA', 'Knight'));
281
//print_r(yt_channel_items('UCjPjcMEAN64opOoNQE9GykA', 'Knight'));
282
//print_r(yt_search_items('Wesley Willis', 'date', 10));
282
//print_r(yt_search_items('Wesley Willis', 'date', 10));
283
 
283