Completed
Branch dev (4bcb34)
by Darko
13:52
created

Books::getBookInfoByName()   A

Complexity

Conditions 4
Paths 3

Size

Total Lines 21
Code Lines 13

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 4
eloc 13
nc 3
nop 1
dl 0
loc 21
rs 9.0534
c 0
b 0
f 0
1
<?php
2
3
namespace Blacklight;
4
5
use ApaiIO\ApaiIO;
6
use Blacklight\db\DB;
7
use GuzzleHttp\Client;
8
use App\Models\Release;
9
use App\Models\BookInfo;
10
use App\Models\Category;
11
use App\Models\Settings;
12
use ApaiIO\Operations\Search;
13
use Illuminate\Support\Carbon;
14
use ApaiIO\Configuration\Country;
15
use ApaiIO\Request\GuzzleRequest;
16
use Illuminate\Support\Facades\Cache;
17
use ApaiIO\Configuration\GenericConfiguration;
18
use ApaiIO\ResponseTransformer\XmlToSimpleXmlObject;
19
20
class Books
21
{
22
    /**
23
     * @var \Blacklight\db\DB
24
     */
25
    public $pdo;
26
27
    /**
28
     * @var bool
29
     */
30
    public $echooutput;
31
32
    /**
33
     * @var null|string
34
     */
35
    public $pubkey;
36
37
    /**
38
     * @var null|string
39
     */
40
    public $privkey;
41
42
    /**
43
     * @var null|string
44
     */
45
    public $asstag;
46
47
    /**
48
     * @var int|null|string
49
     */
50
    public $bookqty;
51
52
    /**
53
     * @var int|null|string
54
     */
55
    public $sleeptime;
56
57
    /**
58
     * @var string
59
     */
60
    public $imgSavePath;
61
62
    /**
63
     * @var null|string
64
     */
65
    public $bookreqids;
66
67
    /**
68
     * @var string
69
     */
70
    public $renamed;
71
72
    /**
73
     * @var array
74
     */
75
    public $failCache;
76
77
    /**
78
     * @param array $options Class instances / Echo to cli.
79
     *
80
     * @throws \Exception
81
     */
82
    public function __construct(array $options = [])
83
    {
84
        $defaults = [
85
            'Echo'     => false,
86
            'Settings' => null,
87
        ];
88
        $options += $defaults;
89
90
        $this->echooutput = ($options['Echo'] && config('nntmux.echocli'));
91
        $this->pdo = ($options['Settings'] instanceof DB ? $options['Settings'] : new DB());
92
93
        $this->pubkey = Settings::settingValue('APIs..amazonpubkey');
0 ignored issues
show
Bug introduced by
'APIs..amazonpubkey' of type string is incompatible with the type boolean|array expected by parameter $setting of App\Models\Settings::settingValue(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

93
        $this->pubkey = Settings::settingValue(/** @scrutinizer ignore-type */ 'APIs..amazonpubkey');
Loading history...
94
        $this->privkey = Settings::settingValue('APIs..amazonprivkey');
95
        $this->asstag = Settings::settingValue('APIs..amazonassociatetag');
96
        $this->bookqty = Settings::settingValue('..maxbooksprocessed') !== '' ? (int) Settings::settingValue('..maxbooksprocessed') : 300;
97
        $this->sleeptime = Settings::settingValue('..amazonsleep') !== '' ? (int) Settings::settingValue('..amazonsleep') : 1000;
98
        $this->imgSavePath = NN_COVERS.'book'.DS;
0 ignored issues
show
Bug introduced by
The constant Blacklight\DS was not found. Maybe you did not declare it correctly or list all dependencies?
Loading history...
99
        $result = Settings::settingValue('..book_reqids');
100
        $this->bookreqids = $result ?? Category::BOOKS_EBOOK;
101
        $this->renamed = (int) Settings::settingValue('..lookupbooks') === 2 ? 'AND isrenamed = 1' : '';
102
103
        $this->failCache = [];
104
    }
105
106
    /**
107
     * @param $id
108
     *
109
     * @return \Illuminate\Database\Eloquent\Model|null|static
110
     */
111
    public function getBookInfo($id)
112
    {
113
        return BookInfo::query()->where('id', $id)->first();
114
    }
115
116
    /**
117
     * @param $title
118
     *
119
     * @return \Illuminate\Database\Eloquent\Model
120
     */
121
    public function getBookInfoByName($title)
122
    {
123
124
        //only used to get a count of words
125
        $searchWords = $searchsql = '';
0 ignored issues
show
Unused Code introduced by
The assignment to $searchsql is dead and can be removed.
Loading history...
126
        $title = preg_replace('/( - | -|\(.+\)|\(|\))/', ' ', $title);
127
        $title = preg_replace('/[^\w ]+/', '', $title);
128
        $title = trim(preg_replace('/\s\s+/i', ' ', $title));
129
        $title = trim($title);
130
        $words = explode(' ', $title);
131
132
        foreach ($words as $word) {
133
            $word = trim(rtrim(trim($word), '-'));
134
            if ($word !== '' && $word !== '-') {
135
                $word = '+'.$word;
136
                $searchWords .= sprintf('%s ', $word);
137
            }
138
        }
139
        $searchWords = trim($searchWords);
140
141
        return BookInfo::search($searchWords)->first();
142
    }
143
144
    /**
145
     * @param $cat
146
     * @param $start
147
     * @param $num
148
     * @param $orderby
149
     * @param array $excludedcats
150
     * @return array
151
     * @throws \Exception
152
     */
153
    public function getBookRange($cat, $start, $num, $orderby, array $excludedcats = []): array
154
    {
155
        $browseby = $this->getBrowseBy();
156
157
        $catsrch = '';
158
        if (\count($cat) > 0 && $cat[0] !== -1) {
159
            $catsrch = Category::getCategorySearch($cat);
160
        }
161
162
        $exccatlist = '';
163
        if (\count($excludedcats) > 0) {
164
            $exccatlist = ' AND r.categories_id NOT IN ('.implode(',', $excludedcats).')';
165
        }
166
167
        $order = $this->getBookOrder($orderby);
168
169
        $booksql = sprintf(
170
                    "
171
				SELECT SQL_CALC_FOUND_ROWS boo.id,
172
					GROUP_CONCAT(r.id ORDER BY r.postdate DESC SEPARATOR ',') AS grp_release_id
173
				FROM bookinfo boo
174
				LEFT JOIN releases r ON boo.id = r.bookinfo_id
175
				WHERE r.nzbstatus = 1
176
				AND boo.cover = 1
177
				AND boo.title != ''
178
				AND r.passwordstatus %s
179
				%s %s %s
180
				GROUP BY boo.id
181
				ORDER BY %s %s %s",
182
                        Releases::showPasswords(),
183
                        $browseby,
184
                        $catsrch,
185
                        $exccatlist,
186
                        $order[0],
187
                        $order[1],
188
                        ($start === false ? '' : ' LIMIT '.$num.' OFFSET '.$start)
189
        );
190
        $expiresAt = Carbon::now()->addSeconds(config('nntmux.cache_expiry_medium'));
191
        $bookscache = Cache::get(md5($booksql));
192
        if ($bookscache !== null) {
193
            $books = $bookscache;
194
        } else {
195
            $books = $this->pdo->queryCalc($booksql);
196
            Cache::put(md5($booksql), $books, $expiresAt);
197
        }
198
199
        $bookIDs = $releaseIDs = false;
200
201
        if (\is_array($books['result'])) {
202
            foreach ($books['result'] as $book => $id) {
203
                $bookIDs[] = $id['id'];
204
                $releaseIDs[] = $id['grp_release_id'];
205
            }
206
        }
207
208
        $sql = sprintf(
209
            "
210
			SELECT
211
				GROUP_CONCAT(r.id ORDER BY r.postdate DESC SEPARATOR ',') AS grp_release_id,
212
				GROUP_CONCAT(r.rarinnerfilecount ORDER BY r.postdate DESC SEPARATOR ',') as grp_rarinnerfilecount,
213
				GROUP_CONCAT(r.haspreview ORDER BY r.postdate DESC SEPARATOR ',') AS grp_haspreview,
214
				GROUP_CONCAT(r.passwordstatus ORDER BY r.postdate DESC SEPARATOR ',') AS grp_release_password,
215
				GROUP_CONCAT(r.guid ORDER BY r.postdate DESC SEPARATOR ',') AS grp_release_guid,
216
				GROUP_CONCAT(rn.releases_id ORDER BY r.postdate DESC SEPARATOR ',') AS grp_release_nfoid,
217
				GROUP_CONCAT(g.name ORDER BY r.postdate DESC SEPARATOR ',') AS grp_release_grpname,
218
				GROUP_CONCAT(r.searchname ORDER BY r.postdate DESC SEPARATOR '#') AS grp_release_name,
219
				GROUP_CONCAT(r.postdate ORDER BY r.postdate DESC SEPARATOR ',') AS grp_release_postdate,
220
				GROUP_CONCAT(r.size ORDER BY r.postdate DESC SEPARATOR ',') AS grp_release_size,
221
				GROUP_CONCAT(r.totalpart ORDER BY r.postdate DESC SEPARATOR ',') AS grp_release_totalparts,
222
				GROUP_CONCAT(r.comments ORDER BY r.postdate DESC SEPARATOR ',') AS grp_release_comments,
223
				GROUP_CONCAT(r.grabs ORDER BY r.postdate DESC SEPARATOR ',') AS grp_release_grabs,
224
				GROUP_CONCAT(df.failed ORDER BY r.postdate DESC SEPARATOR ',') AS grp_release_failed,
225
			boo.*,
226
			r.bookinfo_id,
227
			g.name AS group_name,
228
			rn.releases_id AS nfoid
229
			FROM releases r
230
			LEFT OUTER JOIN groups g ON g.id = r.groups_id
231
			LEFT OUTER JOIN release_nfos rn ON rn.releases_id = r.id
232
			LEFT OUTER JOIN dnzb_failures df ON df.release_id = r.id
233
			INNER JOIN bookinfo boo ON boo.id = r.bookinfo_id
234
			WHERE boo.id IN (%s)
235
			AND r.id IN (%s)
236
			%s
237
			GROUP BY boo.id
238
			ORDER BY %s %s",
239
                (\is_array($bookIDs) ? implode(',', $bookIDs) : -1),
0 ignored issues
show
introduced by
The condition is_array($bookIDs) is always false.
Loading history...
240
                (\is_array($releaseIDs) ? implode(',', $releaseIDs) : -1),
0 ignored issues
show
introduced by
The condition is_array($releaseIDs) is always false.
Loading history...
241
                $catsrch,
242
                $order[0],
243
                $order[1]
244
        );
245
        $return = Cache::get(md5($sql));
246
        if ($return !== null) {
247
            return $return;
0 ignored issues
show
Bug Best Practice introduced by
The expression return $return returns the type Illuminate\Contracts\Cache\Repository which is incompatible with the type-hinted return array.
Loading history...
248
        }
249
        $return = $this->pdo->query($sql);
250
        if (! empty($return)) {
251
            $return[0]['_totalcount'] = $books['total'] ?? 0;
252
        }
253
        Cache::put(md5($sql), $return, $expiresAt);
254
255
        return $return;
256
    }
257
258
    /**
259
     * @param $orderby
260
     *
261
     * @return array
262
     */
263
    public function getBookOrder($orderby): array
264
    {
265
        $order = ($orderby === '') ? 'r.postdate' : $orderby;
266
        $orderArr = explode('_', $order);
267
        switch ($orderArr[0]) {
268
            case 'title':
0 ignored issues
show
Coding Style introduced by
case statements should be defined using a colon.

As per the PSR-2 coding standard, case statements should not be wrapped in curly braces. There is no need for braces, since each case is terminated by the next break.

There is also the option to use a semicolon instead of a colon, this is discouraged because many programmers do not even know it works and the colon is universal between programming languages.

switch ($expr) {
    case "A": { //wrong
        doSomething();
        break;
    }
    case "B"; //wrong
        doSomething();
        break;
    case "C": //right
        doSomething();
        break;
}

To learn more about the PSR-2 coding standard, please refer to the PHP-Fig.

Loading history...
269
                $orderfield = 'boo.title';
270
                break;
271
            case 'author':
0 ignored issues
show
Coding Style introduced by
case statements should be defined using a colon.

As per the PSR-2 coding standard, case statements should not be wrapped in curly braces. There is no need for braces, since each case is terminated by the next break.

There is also the option to use a semicolon instead of a colon, this is discouraged because many programmers do not even know it works and the colon is universal between programming languages.

switch ($expr) {
    case "A": { //wrong
        doSomething();
        break;
    }
    case "B"; //wrong
        doSomething();
        break;
    case "C": //right
        doSomething();
        break;
}

To learn more about the PSR-2 coding standard, please refer to the PHP-Fig.

Loading history...
272
                $orderfield = 'boo.author';
273
                break;
274
            case 'publishdate':
275
                $orderfield = 'boo.publishdate';
276
                break;
277
            case 'size':
278
                $orderfield = 'r.size';
279
                break;
280
            case 'files':
281
                $orderfield = 'r.totalpart';
282
                break;
283
            case 'stats':
284
                $orderfield = 'r.grabs';
285
                break;
286
            case 'posted':
287
            default:
288
                $orderfield = 'r.postdate';
289
                break;
290
        }
291
        $ordersort = (isset($orderArr[1]) && preg_match('/^asc|desc$/i', $orderArr[1])) ? $orderArr[1] : 'desc';
292
293
        return [$orderfield, $ordersort];
294
    }
295
296
    /**
297
     * @return array
298
     */
299
    public function getBookOrdering(): array
300
    {
301
        return [
302
            'title_asc',
303
            'title_desc',
304
            'posted_asc',
305
            'posted_desc',
306
            'size_asc',
307
            'size_desc',
308
            'files_asc',
309
            'files_desc',
310
            'stats_asc',
311
            'stats_desc',
312
            'releasedate_asc',
313
            'releasedate_desc',
314
            'author_asc',
315
            'author_desc',
316
        ];
317
    }
318
319
    /**
320
     * @return array
321
     */
322
    public function getBrowseByOptions(): array
323
    {
324
        return ['author' => 'author', 'title' => 'title'];
325
    }
326
327
    /**
328
     * @return string
329
     */
330
    public function getBrowseBy(): string
331
    {
332
        $browseby = ' ';
333
        $browsebyArr = $this->getBrowseByOptions();
334
        foreach ($browsebyArr as $bbk => $bbv) {
335
            if (isset($_REQUEST[$bbk]) && ! empty($_REQUEST[$bbk])) {
336
                $bbs = stripslashes($_REQUEST[$bbk]);
337
                $browseby .= 'AND boo.'.$bbv.' '.$this->pdo->likeString($bbs, true, true);
338
            }
339
        }
340
341
        return $browseby;
342
    }
343
344
    /**
345
     * @param $title
346
     *
347
     * @return bool|mixed
348
     * @throws \Exception
349
     */
350
    public function fetchAmazonProperties($title)
351
    {
352
        $conf = new GenericConfiguration();
353
        $client = new Client();
354
        $request = new GuzzleRequest($client);
355
356
        try {
357
            $conf
358
                ->setCountry(Country::INTERNATIONAL)
359
                ->setAccessKey($this->pubkey)
360
                ->setSecretKey($this->privkey)
361
                ->setAssociateTag($this->asstag)
362
                ->setRequest($request)
363
                ->setResponseTransformer(new XmlToSimpleXmlObject());
364
        } catch (\Exception $e) {
365
            echo $e->getMessage();
366
        }
367
368
        $search = new Search();
369
        $search->setCategory('Books');
370
        $search->setKeywords($title);
371
        $search->setResponseGroup(['Large']);
372
373
        $apaiIo = new ApaiIO($conf);
374
375
        $response = $apaiIo->runOperation($search);
376
        if ($response === false) {
377
            throw new \RuntimeException('Could not connect to Amazon');
378
        }
379
380
        if (isset($response->Items->Item->ItemAttributes->Title)) {
381
            ColorCLI::doEcho(ColorCLI::info('Found matching title: '.$response->Items->Item->ItemAttributes->Title), true);
382
383
            return $response;
384
        }
385
386
        ColorCLI::doEcho(ColorCLI::notice('Could not find a match on Amazon!'), true);
387
388
        return false;
389
    }
390
391
    /**
392
     * Process book releases, 1 category at a time.
393
     *
394
     * @throws \Exception
395
     */
396
    public function processBookReleases(): void
397
    {
398
        $bookids = [];
399
        if (ctype_digit((string) $this->bookreqids)) {
400
            $bookids[] = $this->bookreqids;
401
        } else {
402
            $bookids = explode(', ', $this->bookreqids);
403
        }
404
405
        $total = \count($bookids);
406
        if ($total > 0) {
407
            foreach ($bookids as $i => $iValue) {
408
                $this->processBookReleasesHelper(
409
                    Release::query()->where('nzbstatus', '=', NZB::NZB_ADDED)
410
                        ->whereNull('bookinfo_id')
411
                        ->whereIn('categories_id', [$bookids[$i]])
412
                    ->orderBy('postdate', 'desc')
413
                    ->limit($this->bookqty)
0 ignored issues
show
Bug introduced by
It seems like $this->bookqty can also be of type string; however, parameter $value of Illuminate\Database\Query\Builder::limit() does only seem to accept integer, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

413
                    ->limit(/** @scrutinizer ignore-type */ $this->bookqty)
Loading history...
414
                    ->get(['searchname', 'id', 'categories_id']),
415
                    $bookids[$i]
416
                );
417
            }
418
        }
419
    }
420
421
    /**
422
     * @param $res
423
     * @param $categoryID
424
     *
425
     * @throws \Exception
426
     */
427
    protected function processBookReleasesHelper($res, $categoryID): void
428
    {
429
        if ($res->count() > 0) {
430
            if ($this->echooutput) {
431
                ColorCLI::doEcho(ColorCLI::header("\nProcessing ".$res->count().' book release(s) for categories id '.$categoryID), true);
432
            }
433
434
            $bookId = -2;
435
            foreach ($res as $arr) {
436
                $startTime = microtime(true);
437
                $usedAmazon = false;
438
                // audiobooks are also books and should be handled in an identical manor, even though it falls under a music category
439
                if ($arr['categories_id'] === '3030') {
440
                    // audiobook
441
                    $bookInfo = $this->parseTitle($arr['searchname'], $arr['id'], 'audiobook');
442
                } else {
443
                    // ebook
444
                    $bookInfo = $this->parseTitle($arr['searchname'], $arr['id'], 'ebook');
445
                }
446
447
                if ($bookInfo !== false) {
448
                    if ($this->echooutput) {
449
                        ColorCLI::doEcho(ColorCLI::headerOver('Looking up: ').ColorCLI::primary($bookInfo), true);
450
                    }
451
452
                    // Do a local lookup first
453
                    $bookCheck = $this->getBookInfoByName($bookInfo);
454
455
                    if ($bookCheck === null && \in_array($bookInfo, $this->failCache, false)) {
456
                        // Lookup recently failed, no point trying again
457
                        if ($this->echooutput) {
458
                            ColorCLI::doEcho(ColorCLI::headerOver('Cached previous failure. Skipping.'), true);
459
                        }
460
                        $bookId = -2;
461
                    } elseif ($bookCheck === null) {
462
                        $bookId = $this->updateBookInfo($bookInfo);
463
                        $usedAmazon = true;
464
                        if ($bookId === -2) {
465
                            $this->failCache[] = $bookInfo;
466
                        }
467
                    } else {
468
                        if ($bookCheck !== null) {
469
                            $bookId = $bookCheck['id'];
470
                        }
471
                    }
472
473
                    // Update release.
474
                    Release::query()->where('id', $arr['id'])->update(['bookinfo_id' => $bookId]);
475
                } else { // Could not parse release title.
476
                    Release::query()->where('id', $arr['id'])->update(['bookinfo_id' => $bookId]);
477
                    if ($this->echooutput) {
478
                        echo '.';
479
                    }
480
                }
481
                // Sleep to not flood amazon.
482
                $diff = floor((microtime(true) - $startTime) * 1000000);
483
                if ($this->sleeptime * 1000 - $diff > 0 && $usedAmazon === true) {
484
                    usleep($this->sleeptime * 1000 - $diff);
0 ignored issues
show
Bug introduced by
$this->sleeptime * 1000 - $diff of type double is incompatible with the type integer expected by parameter $micro_seconds of usleep(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

484
                    usleep(/** @scrutinizer ignore-type */ $this->sleeptime * 1000 - $diff);
Loading history...
485
                }
486
            }
487
        } elseif ($this->echooutput) {
488
            ColorCLI::doEcho(ColorCLI::header('No book releases to process for categories id '.$categoryID), true);
489
        }
490
    }
491
492
    /**
493
     * @param $release_name
494
     * @param $releaseID
495
     * @param $releasetype
496
     *
497
     * @return bool|string
498
     */
499
    public function parseTitle($release_name, $releaseID, $releasetype)
500
    {
501
        $a = preg_replace('/\d{1,2} \d{1,2} \d{2,4}|(19|20)\d\d|anybody got .+?[a-z]\? |[-._ ](Novel|TIA)([-._ ]|$)|( |\.)HQ(-|\.| )|[\(\)\.\-_ ](AVI|AZW3?|DOC|EPUB|LIT|MOBI|NFO|RETAIL|(si)?PDF|RTF|TXT)[\)\]\.\-_ ](?![a-z0-9])|compleet|DAGSTiDNiNGEN|DiRFiX|\+ extra|r?e ?Books?([\.\-_ ]English|ers)?|azw3?|ePu(b|p)s?|html|mobi|^NEW[\.\-_ ]|PDF([\.\-_ ]English)?|Please post more|Post description|Proper|Repack(fix)?|[\.\-_ ](Chinese|English|French|German|Italian|Retail|Scan|Swedish)|^R4 |Repost|Skytwohigh|TIA!+|TruePDF|V413HAV|(would someone )?please (re)?post.+? "|with the authors name right/i', '', $release_name);
502
        $b = preg_replace('/^(As Req |conversion |eq |Das neue Abenteuer \d+|Fixed version( ignore previous post)?|Full |Per Req As Found|(\s+)?R4 |REQ |revised |version |\d+(\s+)?$)|(COMPLETE|INTERNAL|RELOADED| (AZW3|eB|docx|ENG?|exe|FR|Fix|gnv64|MU|NIV|R\d\s+\d{1,2} \d{1,2}|R\d|Req|TTL|UC|v(\s+)?\d))(\s+)?$/i', '', $a);
503
504
        //remove book series from title as this gets more matches on amazon
505
        $c = preg_replace('/ - \[.+\]|\[.+\]/', '', $b);
506
507
        //remove any brackets left behind
508
        $d = preg_replace('/(\(\)|\[\])/', '', $c);
509
        $releasename = trim(preg_replace('/\s\s+/i', ' ', $d));
510
511
        // the default existing type was ebook, this handles that in the same manor as before
512
        if ($releasetype === 'ebook') {
513
            if (preg_match('/^([a-z0-9] )+$|ArtofUsenet|ekiosk|(ebook|mobi).+collection|erotica|Full Video|ImwithJamie|linkoff org|Mega.+pack|^[a-z0-9]+ (?!((January|February|March|April|May|June|July|August|September|O(c|k)tober|November|De(c|z)ember)))[a-z]+( (ebooks?|The))?$|NY Times|(Book|Massive) Dump|Sexual/i', $releasename)) {
514
                if ($this->echooutput) {
515
                    ColorCLI::doEcho(
516
                        ColorCLI::headerOver('Changing category to misc books: ').ColorCLI::primary($releasename), true
517
                    );
518
                }
519
                Release::query()->where('id', $releaseID)->update(['categories_id' => Category::BOOKS_UNKNOWN]);
520
521
                return false;
522
            }
523
524
            if (preg_match('/^([a-z0-9ü!]+ ){1,2}(N|Vol)?\d{1,4}(a|b|c)?$|^([a-z0-9]+ ){1,2}(Jan( |unar|$)|Feb( |ruary|$)|Mar( |ch|$)|Apr( |il|$)|May(?![a-z0-9])|Jun( |e|$)|Jul( |y|$)|Aug( |ust|$)|Sep( |tember|$)|O(c|k)t( |ober|$)|Nov( |ember|$)|De(c|z)( |ember|$))/ui', $releasename) && ! preg_match('/Part \d+/i', $releasename)) {
525
                if ($this->echooutput) {
526
                    ColorCLI::doEcho(
527
                        ColorCLI::headerOver('Changing category to magazines: ').ColorCLI::primary($releasename), true
528
                    );
529
                }
530
                Release::query()->where('id', $releaseID)->update(['categories_id' => Category::BOOKS_MAGAZINES]);
531
532
                return false;
533
            }
534
            if (! empty($releasename) && ! preg_match('/^[a-z0-9]+$|^([0-9]+ ){1,}$|Part \d+/i', $releasename)) {
535
                return $releasename;
536
            }
537
538
            return false;
539
        }
540
        if ($releasetype === 'audiobook') {
541
            if (! empty($releasename) && ! preg_match('/^[a-z0-9]+$|^([0-9]+ ){1,}$|Part \d+/i', $releasename)) {
542
                // we can skip category for audiobooks, since we already know it, so as long as the release name is valid return it so that it is postprocessed by amazon.  In the future, determining the type of audiobook could be added (Lecture or book), since we can skip lookups on lectures, but for now handle them all the same way
543
                return $releasename;
544
            }
545
546
            return false;
547
        }
548
549
        return false;
550
    }
551
552
    /**
553
     * @param string $bookInfo
554
     * @param null   $amazdata
0 ignored issues
show
Documentation Bug introduced by
Are you sure the doc-type for parameter $amazdata is correct as it would always require null to be passed?
Loading history...
555
     *
556
     * @return false|int|string
557
     * @throws \Exception
558
     */
559
    public function updateBookInfo($bookInfo = '', $amazdata = null)
560
    {
561
        $ri = new ReleaseImage();
562
563
        $book = [];
564
        $bookId = -2;
565
566
        $amaz = false;
567
        if ($bookInfo !== '') {
568
            ColorCLI::doEcho(ColorCLI::info('Fetching data from Amazon for '.$bookInfo), true);
569
570
            $amaz = $this->fetchAmazonProperties($bookInfo);
571
        } elseif ($amazdata !== null) {
572
            $amaz = $amazdata;
573
        }
574
575
        if (! $amaz) {
576
            return false;
577
        }
578
579
        $book['title'] = (string) $amaz->Items->Item->ItemAttributes->Title;
580
        $book['author'] = (string) $amaz->Items->Item->ItemAttributes->Author;
581
        $book['asin'] = (string) $amaz->Items->Item->ASIN;
582
        $book['isbn'] = (string) $amaz->Items->Item->ItemAttributes->ISBN;
583
        if ($book['isbn'] === '') {
584
            $book['isbn'] = 'null';
585
        }
586
587
        $book['ean'] = (string) $amaz->Items->Item->ItemAttributes->EAN;
588
        if ($book['ean'] === '') {
589
            $book['ean'] = 'null';
590
        }
591
592
        $book['url'] = (string) $amaz->Items->Item->DetailPageURL;
593
        $book['url'] = str_replace('%26tag%3Dws', '%26tag%3Dopensourceins%2D21', $book['url']);
594
595
        $book['salesrank'] = (string) $amaz->Items->Item->SalesRank;
596
        if ($book['salesrank'] === '') {
597
            $book['salesrank'] = 'null';
598
        }
599
600
        $book['publisher'] = (string) $amaz->Items->Item->ItemAttributes->Publisher;
601
        if ($book['publisher'] === '') {
602
            $book['publisher'] = 'null';
603
        }
604
605
        $book['publishdate'] = date('Y-m-d', strtotime((string) $amaz->Items->Item->ItemAttributes->PublicationDate));
606
        if ($book['publishdate'] === '') {
607
            $book['publishdate'] = 'null';
608
        }
609
610
        $book['pages'] = (string) $amaz->Items->Item->ItemAttributes->NumberOfPages;
611
        if ($book['pages'] === '') {
612
            $book['pages'] = 'null';
613
        }
614
615
        if (isset($amaz->Items->Item->EditorialReviews->EditorialReview->Content)) {
616
            $book['overview'] = strip_tags((string) $amaz->Items->Item->EditorialReviews->EditorialReview->Content);
617
            if ($book['overview'] === '') {
618
                $book['overview'] = 'null';
619
            }
620
        } else {
621
            $book['overview'] = 'null';
622
        }
623
624
        if (isset($amaz->Items->Item->BrowseNodes->BrowseNode->Name)) {
625
            $book['genre'] = (string) $amaz->Items->Item->BrowseNodes->BrowseNode->Name;
626
            if ($book['genre'] === '') {
627
                $book['genre'] = 'null';
628
            }
629
        } else {
630
            $book['genre'] = 'null';
631
        }
632
633
        $book['coverurl'] = (string) $amaz->Items->Item->LargeImage->URL;
634
        if ($book['coverurl'] !== '') {
635
            $book['cover'] = 1;
636
        } else {
637
            $book['cover'] = 0;
638
        }
639
640
        $check = BookInfo::query()->where('asin', $book['asin'])->first();
641
        if ($check === null) {
642
            $bookId = BookInfo::query()->insertGetId(
643
                [
644
                    'title' => $book['title'],
645
                    'author' => $book['author'],
646
                    'asin' => $book['asin'],
647
                    'isbn' => $book['isbn'],
648
                    'ean' => $book['ean'],
649
                    'url' => $book['url'],
650
                    'salesrank' => $book['salesrank'],
651
                    'publisher' => $book['publisher'],
652
                    'publishdate' => $book['publishdate'],
653
                    'pages' => $book['pages'],
654
                    'overview' =>$book['overview'],
655
                    'genre' => $book['genre'],
656
                    'cover' => $book['cover'],
657
                    'created_at' => Carbon::now(),
658
                    'updated_at' => Carbon::now(),
659
                ]
660
            );
661
        } else {
662
            if ($check !== null) {
663
                $bookId = $check['id'];
664
            }
665
            BookInfo::query()->where('id', $bookId)->update(
666
                [
667
                    'title' => $book['title'],
668
                    'author' => $book['author'],
669
                    'asin' => $book['asin'],
670
                    'isbn' => $book['isbn'],
671
                    'ean' => $book['ean'],
672
                    'url' => $book['url'],
673
                    'salesrank' => $book['salesrank'],
674
                    'publisher' => $book['publisher'],
675
                    'publishdate' => $book['publishdate'],
676
                    'pages' => $book['pages'],
677
                    'overview' => $book['overview'],
678
                    'genre' => $book['genre'],
679
                    'cover' => $book['cover'],
680
                ]
681
            );
682
        }
683
684
        if ($bookId && $bookId !== -2) {
685
            if ($this->echooutput) {
686
                ColorCLI::doEcho(ColorCLI::header('Added/updated book: '), true);
687
                if ($book['author'] !== '') {
688
                    ColorCLI::doEcho(ColorCLI::alternateOver('   Author: ').ColorCLI::primary($book['author']), true);
689
                }
690
                echo ColorCLI::alternateOver('   Title: ').ColorCLI::primary(' '.$book['title']);
691
                if ($book['genre'] !== 'null') {
692
                    ColorCLI::doEcho(ColorCLI::alternateOver('   Genre: ').ColorCLI::primary(' '.$book['genre']), true);
693
                }
694
            }
695
696
            $book['cover'] = $ri->saveImage($bookId, $book['coverurl'], $this->imgSavePath, 250, 250);
697
        } else {
698
            if ($this->echooutput) {
699
                ColorCLI::doEcho(
700
                    ColorCLI::header('Nothing to update: ').
701
                    ColorCLI::header($book['author'].
702
                        ' - '.
703
                        $book['title']), true
704
                );
705
            }
706
        }
707
708
        return $bookId;
709
    }
710
}
711