Completed
Push — master ( 9492ba...5fed73 )
by Stanislav
306:28
created

WeburgDownload::execute()   B

Complexity

Conditions 5
Paths 10

Size

Total Lines 56

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 56
rs 8.6488
c 0
b 0
f 0
cc 5
nc 10
nop 2

How to fix   Long Method   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
3
namespace Popstas\Transmission\Console\Command;
4
5
use Popstas\Transmission\Console\WeburgClient;
6
use Symfony\Component\Console\Helper\ProgressBar;
7
use Symfony\Component\Console\Input\ArrayInput;
8
use Symfony\Component\Console\Input\InputInterface;
9
use Symfony\Component\Console\Input\InputOption;
10
use Symfony\Component\Console\Output\OutputInterface;
11
12
class WeburgDownload extends Command
13
{
14
    protected function configure()
15
    {
16
        parent::configure();
17
        $this
18
            ->setName('weburg-download')
19
            ->setAliases(['wd'])
20
            ->setDescription('Download torrents from weburg.net')
21
            ->addOption('download-torrents-dir', null, InputOption::VALUE_OPTIONAL, 'Torrents destination directory')
22
            ->addOption('days', null, InputOption::VALUE_OPTIONAL, 'Max age of series torrent')
23
            ->addOption('popular', null, InputOption::VALUE_NONE, 'Download only popular')
24
            ->addOption('series', null, InputOption::VALUE_NONE, 'Download only tracked series')
25
            ->addOption('yes', 'y', InputOption::VALUE_NONE, 'Don\'t ask confirmation')
26
            ->addArgument('movie-id', null, 'Movie ID or URL')
27
            ->setHelp(<<<EOT
28
## Download torrents from Weburg.net
29
30
You can automatically download popular torrents from http://weburg.net/movies/new out of the box, use command:
31
```
32
transmission-cli weburg-download --download-torrents-dir=/path/to/torrents/directory
33
```
34
35
or define `download-torrents-dir` in config and just:
36
```
37
transmission-cli weburg-download
38
```
39
40
You can automatically download new series, for add series to tracked list see `transmission-cli weburg-series-add`.
41
It is pretty simple:
42
```
43
transmission-cli weburg-series-add http://weburg.net/series/info/12345
44
```
45
46
After that command `weburg-download` also will download series from list for last day.
47
If you don't want to download popular torrents, but only new series, use command:
48
```
49
transmission-cli weburg-download --download-torrents-dir=/path/to/torrents/directory --series
50
```
51
52
## Add downloaded torrents to Transmission
53
54
After download all torrents, command call `torrent-add` command for each transmission-host from config.
55
If was defined `--transmission-host` option, then `torrent-add` will called only for this host.
56
EOT
57
            );
58
    }
59
60
    protected function execute(InputInterface $input, OutputInterface $output)
61
    {
62
        $config = $this->getApplication()->getConfig();
63
        $weburgClient = $this->getApplication()->getWeburgClient();
64
65
        try {
66
            list($torrentsDir, $downloadDir) = $this->getTorrentsDirectory($input);
67
68
            $daysMax = $config->overrideConfig($input, 'days', 'weburg-series-max-age');
69
            $allowedMisses = $config->get('weburg-series-allowed-misses');
70
71
            $movieArgument = $input->getArgument('movie-id');
72
            if (isset($movieArgument)) {
73
                $torrentsUrls = $this->getMovieTorrentsUrls(
74
                    $weburgClient,
75
                    $movieArgument,
76
                    $daysMax,
77
                    $allowedMisses
78
                );
79
            } else {
80
                $torrentsUrls = $this->getTorrentsUrls(
81
                    $input,
82
                    $output,
83
                    $weburgClient,
84
                    $downloadDir,
85
                    $daysMax,
86
                    $allowedMisses
87
                );
88
            }
89
90
            $this->dryRun($input, $output, function () use (
91
                $input,
92
                $output,
93
                $weburgClient,
94
                $torrentsDir,
95
                $torrentsUrls
96
            ) {
97
                $downloadedFiles = [];
98
                foreach ($torrentsUrls as $torrentUrl) {
99
                    $downloadedFiles[] = $weburgClient->downloadTorrent($torrentUrl, $torrentsDir);
100
                }
101
102
                $downloadedFiles = $this->filterByLists($downloadedFiles);
103
                if (!empty($downloadedFiles)) {
104
                    $this->addTorrents($input, $output, $downloadedFiles);
105
                } else {
106
                    $output->writeln("\nAll torrents filtered by black/whitelists");
107
                }
108
            }, 'dry-run, don\'t really download');
109
        } catch (\RuntimeException $e) {
110
            $output->writeln($e->getMessage());
111
            return 1;
112
        }
113
114
        return 0;
115
    }
116
117
    private function getTorrentsUrls(
118
        InputInterface $input,
119
        OutputInterface $output,
120
        WeburgClient $weburgClient,
121
        $downloadDir,
122
        $daysMax,
123
        $allowedMisses
124
    ) {
125
        $torrentsUrls = [];
126
127
        if (!$input->getOption('popular') && !$input->getOption('series')) {
128
            $input->setOption('popular', true);
129
            $input->setOption('series', true);
130
        }
131
132
        if ($input->getOption('popular')) {
133
            $torrentsUrls = array_merge(
134
                $torrentsUrls,
135
                $this->getPopularTorrentsUrls($output, $weburgClient, $downloadDir)
136
            );
137
        }
138
139
        if ($input->getOption('series')) {
140
            $torrentsUrls = array_merge(
141
                $torrentsUrls,
142
                $this->getTrackedSeriesUrls($output, $weburgClient, $daysMax, $allowedMisses)
143
            );
144
        }
145
146
        return $torrentsUrls;
147
    }
148
149
    public function getPopularTorrentsUrls(OutputInterface $output, WeburgClient $weburgClient, $downloadDir)
150
    {
151
        $torrentsUrls = [];
152
153
        $config = $this->getApplication()->getConfig();
154
        $logger = $this->getApplication()->getLogger();
155
156
        $moviesIds = $weburgClient->getMoviesIds();
157
158
        $output->writeln("\nDownloading popular torrents");
159
160
        $progress = new ProgressBar($output, count($moviesIds));
161
        $progress->start();
162
163
        foreach ($moviesIds as $movieId) {
164
            $progress->setMessage('Check movie ' . $movieId . '...');
165
            $progress->advance();
166
167
            $downloadedLogfile = $downloadDir . '/' . $movieId;
168
169
            $isDownloaded = file_exists($downloadedLogfile);
170
            if ($isDownloaded) {
171
                continue;
172
            }
173
174
            $movieInfo = $weburgClient->getMovieInfoById($movieId);
175
            foreach (array_keys($movieInfo) as $infoField) {
176
                if (!isset($movieInfo[$infoField])) {
177
                    $logger->warning('Cannot find ' . $infoField . ' in movie ' . $movieId);
178
                }
179
            }
180
181
            $isTorrentPopular = $weburgClient->isTorrentPopular(
182
                $movieInfo,
183
                $config->get('download-comments-min'),
184
                $config->get('download-imdb-min'),
185
                $config->get('download-kinopoisk-min'),
186
                $config->get('download-votes-min')
187
            );
188
189
            if ($isTorrentPopular) {
190
                $progress->setMessage('Download movie ' . $movieId . '...');
191
192
                $movieUrls = $weburgClient->getMovieTorrentUrlsById($movieId);
193
                $torrentsUrls = array_merge($torrentsUrls, $movieUrls);
194
                $logger->info('Download movie ' . $movieId . ': ' . $movieInfo['title']);
195
196
                file_put_contents(
197
                    $downloadedLogfile,
198
                    date('Y-m-d H:i:s') . "\n" . implode("\n", $torrentsUrls)
199
                );
200
            }
201
        }
202
203
        $progress->finish();
204
205
        return $torrentsUrls;
206
    }
207
208
    /**
209
     * @param OutputInterface $output
210
     * @param WeburgClient $weburgClient
211
     * @param $daysMax
212
     * @param $allowedMisses
213
     * @return array
214
     */
215
    public function getTrackedSeriesUrls(OutputInterface $output, WeburgClient $weburgClient, $daysMax, $allowedMisses)
216
    {
217
        $torrentsUrls = [];
218
219
        $config = $this->getApplication()->getConfig();
220
221
        $seriesList = $config->get('weburg-series-list');
222
        if (!$seriesList) {
223
            return [];
224
        }
225
226
        $output->writeln("\nDownloading tracked series");
227
228
        $progress = new ProgressBar($output, count($seriesList));
229
        $progress->start();
230
231
        foreach ($seriesList as $seriesItem) {
232
            if (is_array($seriesItem)) {
233
                $seriesId = $seriesItem['id'];
234
                $seriesTitle = isset($seriesItem['title']) && $seriesItem['title'] ? $seriesItem['title'] : $seriesId;
235
            } else {
236
                $seriesId = $seriesTitle = $seriesItem;
237
            }
238
            $progress->setMessage('Check series ' . $seriesTitle . '...');
239
            $progress->advance();
240
241
            $movieInfo = $weburgClient->getMovieInfoById($seriesId);
242
            $seriesUrls = $weburgClient->getSeriesTorrents($seriesId, $movieInfo['hashes'], $daysMax, $allowedMisses);
243
            $torrentsUrls = array_merge($torrentsUrls, $seriesUrls);
244
        }
245
246
        $progress->finish();
247
248
        return $torrentsUrls;
249
    }
250
251
    /**
252
     * @param WeburgClient $weburgClient
253
     * @param $movieId
254
     * @param $daysMax
255
     * @param $allowedMisses
256
     * @return array
257
     */
258
    public function getMovieTorrentsUrls(WeburgClient $weburgClient, $movieId, $daysMax, $allowedMisses)
259
    {
260
        $torrentsUrls = [];
261
        $logger = $this->getApplication()->getLogger();
262
263
        $movieId = $weburgClient->cleanMovieId($movieId);
264
        if (!$movieId) {
265
            throw new \RuntimeException($movieId . ' seems not weburg movie ID or URL');
266
        }
267
268
        $movieInfo = $weburgClient->getMovieInfoById($movieId);
269
        $logger->info('Search series ' . $movieId);
270
        if (!empty($movieInfo['hashes'])) {
271
            $seriesUrls = $weburgClient->getSeriesTorrents($movieId, $movieInfo['hashes'], $daysMax, $allowedMisses);
272
            $torrentsUrls = array_merge($torrentsUrls, $seriesUrls);
273
274
            if (count($seriesUrls)) {
275
                $logger->info('Download series ' . $movieId . ': '
276
                    . $movieInfo['title'] . ' (' . count($seriesUrls) . ')');
277
            }
278
        } else {
279
            $torrentsUrls = array_merge($torrentsUrls, $weburgClient->getMovieTorrentUrlsById($movieId));
280
        }
281
282
        return $torrentsUrls;
283
    }
284
285
    /**
286
     * @param InputInterface $input
287
     * @return array
288
     * @throws \RuntimeException
289
     */
290
    private function getTorrentsDirectory(InputInterface $input)
291
    {
292
        $config = $this->getApplication()->getConfig();
293
294
        $torrentsDir = $config->overrideConfig($input, 'download-torrents-dir');
295
        if (!$torrentsDir) {
296
            throw new \RuntimeException('Destination directory not defined. '
297
                . 'Use command with --download-torrents-dir=/path/to/dir parameter '
298
                . 'or define destination directory \'download-torrents-dir\' in config file.');
299
        }
300
301
        if (!file_exists($torrentsDir)) {
302
            throw new \RuntimeException('Destination directory not exists: ' . $torrentsDir);
303
        }
304
305
        $downloadDir = $torrentsDir . '/downloaded';
306
        if (!file_exists($downloadDir)) {
307
            mkdir($downloadDir, 0777);
308
        }
309
310
        return [$torrentsDir, $downloadDir];
311
    }
312
313
    private function filterByLists(array $torrentFiles)
314
    {
315
        $config = $this->getApplication()->getConfig();
316
        $logger = $this->getApplication()->getLogger();
317
318
        $whitelist = $config->get('download-filename-whitelist');
319
        $blacklist = $config->get('download-filename-blacklist');
320
321
        $torrentFiles = array_filter($torrentFiles, function ($torrentFile) use ($whitelist, $blacklist, $logger) {
322
            if (!empty($whitelist)) {
323
                $matched = false;
324
                foreach ($whitelist as $white) {
325
                    if (preg_match('/' . $white . '/i', $torrentFile)) {
326
                        $logger->info($torrentFile . ' matched whitelist: ' . $white);
327
                        $matched = true;
328
                    }
329
                }
330
                if (!$matched) {
331
                    $logger->info($torrentFile . ' not matched any whitelist: ' . implode(', ', $whitelist));
332
                    return false;
333
                }
334
            }
335
            if (!empty($blacklist)) {
336
                foreach ($blacklist as $black) {
337
                    if (preg_match('/' . $black . '/i', $torrentFile)) {
338
                        $logger->info($torrentFile . ' matched blacklist: ' . $black);
339
                        return false;
340
                    }
341
                }
342
            }
343
            return true;
344
        });
345
        return $torrentFiles;
346
    }
347
348
    private function addTorrents(InputInterface $input, OutputInterface $output, array $torrentFiles)
349
    {
350
        $config = $this->getApplication()->getConfig();
351
        $hosts = [];
352
353
        if (empty($input->getOption('transmission-host'))) {
354
            $transmissionConnects = $config->get('transmission');
355
            foreach ($transmissionConnects as $transmissionConnect) {
356
                $hosts[] = $transmissionConnect['host'];
357
            }
358
        } else {
359
            $hosts[] = $config->get('transmission-host');
360
        }
361
362
        foreach ($hosts as $host) {
363
            $command = $this->getApplication()->find('torrent-add');
364
            $arguments = array(
365
                'command'             => 'torrent-add',
366
                'torrent-files'       => $torrentFiles,
367
                '--transmission-host' => $host,
368
                '--yes'               => $input->getOption('yes'),
369
                '--dry-run'           => $input->getOption('dry-run'),
370
            );
371
372
            $addInput = new ArrayInput($arguments);
373
            $output->writeln("\nAdd torrents to " . $host);
374
            $command->run($addInput, $output);
375
        }
376
    }
377
}
378