Completed
Push — master ( 5de613...7fed73 )
by Stanislav
05:37 queued 02:33
created

WeburgClient::movieQuery()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 14

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 14
rs 9.7998
c 0
b 0
f 0
cc 1
nc 1
nop 1
1
<?php
2
3
namespace Popstas\Transmission\Console;
4
5
use GuzzleHttp\ClientInterface;
6
use GuzzleHttp\Cookie\CookieJar;
7
8
class WeburgClient
9
{
10
    /**
11
     * @var ClientInterface
12
     */
13
    private $httpClient;
14
15
    private $requestDelay;
16
17
    /**
18
     * WeburgClient constructor.
19
     * @param ClientInterface $httpClient
20
     * @param int $requestDelay
21
     */
22
    public function __construct(ClientInterface $httpClient, $requestDelay = 0)
23
    {
24
        $this->httpClient = $httpClient;
25
        $this->requestDelay = $requestDelay;
26
    }
27
28
    /**
29
     * @param $movieId
30
     * @return array
31
     * @throws \GuzzleHttp\Exception\GuzzleException
32
     */
33
    public function getMovieInfoById($movieId)
34
    {
35
        $movieUrl = $this->getMovieUrl($movieId);
36
        $body = $this->getUrlBody($movieUrl);
37
        $body = iconv('WINDOWS-1251', 'UTF-8', $body);
38
        $info = $this->getMovieInfo($body);
39
        return $info;
40
    }
41
42
    /**
43
     * @param $movieId
44
     * @return array urls of movie (not series)
45
     * @throws \GuzzleHttp\Exception\GuzzleException
46
     */
47
    public function getMovieTorrentUrlsById($movieId)
48
    {
49
        $torrentUrl = $this->getMovieTorrentUrl($movieId);
50
        $body = $this->getUrlBody($torrentUrl);
51
        $torrentsUrls = $this->getTorrentsUrls($body);
52
        return $torrentsUrls;
53
    }
54
55
    /**
56
     * @param $movieId
57
     * @param $hashes array hashes of torrents from movieInfo
58
     * @param int $daysMax torrents older last days will not matched
59
     * @param int $allowedMisses after x misses next checks will broken
60
     * @return array urls of matched torrent files
61
     * @throws \GuzzleHttp\Exception\GuzzleException
62
     */
63
    public function getSeriesTorrents($movieId, $hashes, $daysMax = 1, $allowedMisses = 0)
64
    {
65
        $torrentsUrls = [];
66
        $timestampFrom = strtotime('-' . $daysMax . 'days');
67
68
        $hashes = array_reverse($hashes);
69
        foreach ($hashes as $hash) {
70
            if ($allowedMisses < 0) {
71
                break;
72
            }
73
74
            $torrentUrl = $this->getMovieTorrentUrl($movieId, $hash);
75
            $body = $this->getUrlBody($torrentUrl);
76
77
            if ($this->checkTorrentDate($body, $timestampFrom) === false) {
78
                $allowedMisses--;
79
                continue;
80
            }
81
82
            $torrentsUrls = array_merge($torrentsUrls, $this->getTorrentsUrls($body));
83
        }
84
85
        return $torrentsUrls;
86
    }
87
88
    /**
89
     * @return array
90
     * @throws \GuzzleHttp\Exception\GuzzleException
91
     */
92
    public function getMoviesIds()
93
    {
94
        $moviesUrl = 'https://weburg.net/movies/new/?clever_title=1&template=0&last=0';
95
96
        $jsonRaw = $this->getUrlBody($moviesUrl, [
97
            'Content-Type'     => 'text/html; charset=utf-8',
98
            'User-Agent'       => 'Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:27.0) Gecko/20100101 Firefox/27.0',
99
            'X-Requested-With' => 'XMLHttpRequest',
100
        ]);
101
102
        $moviesJson = json_decode($jsonRaw);
103
104
        $moviesIds = $this->getInfoUrls($moviesJson->items);
105
106
        return $moviesIds;
107
    }
108
109
    /**
110
     * @param $q
111
     * @return bool|string
112
     * @throws \GuzzleHttp\Exception\GuzzleException
113
     */
114
    public function getMovieIdByQuery($q)
115
    {
116
        $results = $this->movieQuery($q);
117
118
        if ($results && $results[0] && $results[0]->object_id) {
119
            return $results[0]->object_id;
120
        }
121
122
        return false;
123
    }
124
125
    /**
126
     * @param $q
127
     * @return mixed
128
     * @throws \GuzzleHttp\Exception\GuzzleException
129
     */
130
    public function movieQuery($q)
131
    {
132
        $resultUrl = 'https://weburg.net/ajax/autocomplete/search/main?' . http_build_query(['q' => $q]);
133
134
        $jsonRaw = $this->getUrlBody($resultUrl, [
135
            'Content-Type' => 'text/html; charset=utf-8',
136
            'User-Agent'   => 'Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:27.0) Gecko/20100101 Firefox/27.0',
137
            // 'X-Requested-With' => 'XMLHttpRequest',
138
        ]);
139
140
        $resultJson = json_decode($jsonRaw);
141
142
        return $resultJson;
143
    }
144
145
    public static function getMovieUrl($movieId)
146
    {
147
        return 'https://weburg.net/movies/info/' . $movieId;
148
    }
149
150
    /**
151
     * @param $url
152
     * @param array $headers
153
     * @return \Psr\Http\Message\ResponseInterface
154
     * @throws \RuntimeException
155
     * @throws \GuzzleHttp\Exception\GuzzleException
156
     */
157
    private function getUrl($url, $headers = [])
158
    {
159
        $jar = new CookieJar();
160
161
        $res = $this->httpClient->request('GET', $url, [
162
            'headers' => $headers,
163
            'cookies' => $jar,
164
        ]);
165
166
        if ($res->getStatusCode() != 200) {
167
            throw new \RuntimeException('Error ' . $res->getStatusCode() . 'while get url ' . $url);
168
        }
169
170
        sleep($this->requestDelay);
171
172
        return $res;
173
    }
174
175
    /**
176
     * @param string $url
177
     * @param array $headers
178
     * @return \Psr\Http\Message\StreamInterface
179
     * @throws \RuntimeException
180
     * @throws \GuzzleHttp\Exception\GuzzleException
181
     */
182
    public function getUrlBody($url, $headers = [])
183
    {
184
        $res = $this->getUrl($url, $headers);
185
        $body = $res->getBody();
186
        return $body;
187
    }
188
189
    /**
190
     * @param $url
191
     * @param $torrentsDir
192
     * @return string path to downloaded file
193
     * @throws \RuntimeException
194
     * @throws \GuzzleHttp\Exception\GuzzleException
195
     */
196
    public function downloadTorrent($url, $torrentsDir)
197
    {
198
        $res = $this->getUrl($url);
199
        $torrentBody = $res->getBody();
200
201
        $disposition = $res->getHeader('content-disposition');
202
        preg_match('/filename="(.*?)"/', $disposition[0], $res);
203
        $filename = $res[1];
204
205
        $filePath = $torrentsDir . '/' . $filename;
206
        file_put_contents($filePath, $torrentBody);
207
208
        return $filePath;
209
    }
210
211
    public static function isTorrentPopular($movieInfo, $commentsMin, $imdbMin, $kinopoiskMin, $votesMin)
212
    {
213
        return $movieInfo['comments'] >= $commentsMin
214
            || $movieInfo['rating_imdb'] >= $imdbMin
215
            || $movieInfo['rating_kinopoisk'] >= $kinopoiskMin
216
            || $movieInfo['rating_votes'] >= $votesMin;
217
    }
218
219
    public static function cleanMovieId($idOrUrl)
220
    {
221
        if (preg_match('/^\d+$/', $idOrUrl)) {
222
            return $idOrUrl;
223
        }
224
        preg_match('/^https?:\/\/weburg\.net\/(series|movies)\/info\/(\d+)$/', $idOrUrl, $res);
225
        $movieId = count($res) ? $res[2] : null;
226
        return $movieId;
227
    }
228
229
    private static function getMovieTorrentUrl($movieId, $hash = '')
230
    {
231
        return 'https://weburg.net/ajax/download/movie?'
232
            . ($hash ? 'hash=' . $hash . '&' : '')
233
            . 'obj_id=' . $movieId;
234
    }
235
236
    private static function getMovieInfo($body)
237
    {
238
        $info = [];
239
240
        $checks = [
241
            'title'            => '<title>(.*?)( — Weburg)?( — Вебург)?<\/title>',
242
            'comments'         => 'Комментариев:&nbsp;(\d+)',
243
            'rating_kinopoisk' => 'external-ratings-link_type_kinopoisk.*?>(\d+\.\d+)',
244
            'rating_imdb'      => 'external-ratings-link_type_imdb.*?>(\d+\.\d+)',
245
            'rating_votes'     => 'count-votes" value="([0-9]+)"',
246
        ];
247
248
        foreach ($checks as $name => $regexp) {
249
            preg_match('/' . $regexp . '/mis', $body, $res);
250
            $info[$name] = count($res) ? $res[1] : null;
251
        }
252
253
        preg_match_all('/js-search-button.*?hash="(.*?)"/mis', $body, $res);
254
        $info['hashes'] = count($res) ? $res[1] : null;
255
256
        return $info;
257
    }
258
259
    /**
260
     * @param $body
261
     * @param $fromTimestamp
262
     * @return bool|string date if matched, false if not
263
     */
264
    private static function checkTorrentDate($body, $fromTimestamp)
265
    {
266
        preg_match('/(\d{2})\.(\d{2})\.(\d{4})/mis', $body, $res);
267
        if (empty($res)) {
268
            return false;
269
        }
270
271
        $torrentTimestamp = mktime(0, 0, 0, $res[2], $res[1], $res[3]);
272
        return $torrentTimestamp >= $fromTimestamp ? $res[0] : false;
273
    }
274
275
    private static function getInfoUrls($body)
276
    {
277
        preg_match_all('/\/movies\/info\/([0-9]+)/', $body, $res);
278
        $moviesIds = array_unique($res[1]);
279
        return $moviesIds;
280
    }
281
282
    /**
283
     * @param $body
284
     * @return array
285
     */
286
    private static function getTorrentsUrls($body)
287
    {
288
        preg_match_all('/(http:\/\/.*?gettorrent.*?)"/', $body, $res);
289
        $torrentsUrls = $res[1];
290
        $torrentsUrls = array_unique($torrentsUrls);
291
        return $torrentsUrls;
292
    }
293
}
294