Youtubecom::getUrlToDownload()   A
last analyzed

Complexity

Conditions 4
Paths 4

Size

Total Lines 19
Code Lines 11

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 11
CRAP Score 4

Importance

Changes 0
Metric Value
c 0
b 0
f 0
dl 0
loc 19
ccs 11
cts 11
cp 1
rs 9.2
cc 4
eloc 11
nc 4
nop 1
crap 4
1
<?php
2
namespace Tartana\Host;
3
4
use GuzzleHttp\Psr7\Request;
5
use GuzzleHttp\RequestOptions;
6
use Symfony\Component\DomCrawler\Crawler;
7
use Tartana\Entity\Download;
8
use Tartana\Host\Common\Http;
9
use Tartana\Util;
10
11
class Youtubecom extends Http
12
{
13
14 3
	public function fetchLinkList($link)
15
	{
16 3
		if (!Util::startsWith($link, 'https://www.youtube.com/playlist?')) {
17 1
			return parent::fetchLinkList($link);
18
		}
19
20 2
		$resp = $this->getClient()->request('get', $link);
21
22 2
		$crawler = new Crawler($resp->getBody()->getContents());
23
24
		// Extracting the links which belong to the playlist
25 2
		$links = $crawler->filter('a.pl-video-title-link')->extract([
26
			'href'
27 2
		]);
28
29 2
		$data = [];
30 2
		foreach ($links as $link) {
31 2
			$uri = parse_url($link);
32
33 2
			if (!key_exists('path', $uri) || $uri['path'] != '/watch') {
34 1
				continue;
35
			}
36
37 1
			$params = [];
38 1
			parse_str($uri['query'], $params);
39 1
			if (key_exists('v', $params)) {
40 1
				$data[] = 'https://www.youtube.com/watch?v=' . $params['v'];
41
			}
42
		}
43 2
		return array_unique($data);
44
	}
45
46 4
	public function fetchDownloadInfo(array $downloads)
47
	{
48 4
		foreach ($downloads as $download) {
49
			// Connection check
50
			try {
51 4
				$data = $this->getStreamData($download);
52 3
				if (!empty($data['title']) && empty($download->getFileName())) {
53 1
					$download->setFileName($this->makeSafe($data['title'] . '.mp4'));
54
				}
55
56 3
				if (key_exists('errorcode', $data) && $data['errorcode'] > 0 && key_exists('reason', $data)) {
57 1
					$download->setMessage($data['reason']);
58 3
					$download->setState(Download::STATE_DOWNLOADING_ERROR);
59
				}
60 1
			} catch (\Exception $e) {
61 1
				$this->log('Exception fetching head for connection test: ' . $e->getMessage());
62 1
				$download->setMessage('TARTANA_DOWNLOAD_MESSAGE_INVALID_URL');
63 4
				$download->setState(Download::STATE_DOWNLOADING_ERROR);
64
			}
65
		}
66 4
	}
67
68 3
	protected function getUrlToDownload(Download $download)
69
	{
70 3
		$data = $this->getStreamData($download);
71
72 3
		if (!key_exists('url_encoded_fmt_stream_map', $data)) {
73 1
			return null;
74
		}
75
76 2
		foreach (explode(',', $data['url_encoded_fmt_stream_map']) as $streamData) {
77 2
			parse_str($streamData, $streamData);
78
79 2
			if (key_exists('url', $streamData)) {
80 1
				$url = urldecode($streamData['url']);
81 1
				$this->log('Youtube real url: ' . $url);
82 2
				return $url;
83
			}
84
		}
85 1
		return null;
86
	}
87
88 7
	private function getStreamData(Download $download)
89
	{
90 7
		if (preg_match(
91 7
			'%(?:youtube(?:-nocookie)?\.com/(?:[^/]+/.+/|(?:v|e(?:mbed)?)/|.*[?&]v=)|youtu\.be/)([^"&?/ ]{11})%i',
92 7
			$download->getLink(),
93
			$match
94
		)) {
95
			$headers = [
96 6
				'User-Agent' => 'Mozilla/5.0 (X11; Linux x86_64; rv:10.0) Gecko/20150101 Firefox/44.0 (Chrome)',
97 6
				'Referer' => $download->getLink(),
98 6
				'Accept-Language' => 'en-us,en;q=0.5',
99 6
				'Accept-Encoding' => 'gzip, deflate',
100 6
				'Accept-Charset' => 'ISO-8859-1,utf-8;q=0.7,*;q=0.7',
101 6
				'Accept' => 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8',
102 6
				'Connection' => 'close',
103 6
				'Origin' => 'https://www.youtube.com',
104 6
				'Host' => 'www.youtube.com'
105
			];
106
			// Getting the link information initializing the cookie
107 6
			$this->getClient()->request(
108 6
				'get',
109 6
				$download->getLink() . '&gl=US&hl=en&has_verified=1&bpctr=9999999999',
110
				[
111 6
					RequestOptions::HEADERS => $headers
112
				]
113
			);
114
115
			// Fetching the video information
116 6
			$res = $this->getClient()->request(
117 6
				'get',
118 6
				'http://www.youtube.com/get_video_info?video_id=' . $match[1] . '&el=info&ps=default&eurl=&gl=US&hl=en',
119
				[
120 6
					RequestOptions::HEADERS => $headers
121
				]
122
			);
123
124 5
			parse_str($res->getBody()->getContents(), $videoData);
125 5
			return $videoData;
126
		}
127
128
		return [
129 1
			'title' => '',
130
			'url_encoded_fmt_stream_map' => ''
131
		];
132
	}
133
134
	/**
135
	 *
136
	 * @param string $file
137
	 * @return string
138
	 * @see http://stackoverflow.com/questions/2668854/sanitizing-strings-to-make-them-url-and-filename-safe
139
	 * @see http://stackoverflow.com/a/24812812/356375
140
	 */
141 1
	private function makeSafe($file)
142
	{
143
		// Remove any trailing dots, as those aren't ever valid file names.
144 1
		$file = rtrim($file, '.');
145
146
		$regex = array(
147 1
			'#(\.){2,}#',
148
			'#[^A-Za-z0-9\.\_\- ]#',
149
			'#^\.#'
150
		);
151
152 1
		return trim(preg_replace($regex, '', $file));
153
	}
154
}
155