Issues (955)

app/Console/Commands/GetArticleRange.php (1 issue)

Severity
1
<?php
2
3
namespace App\Console\Commands;
4
5
use App\Models\Settings;
6
use App\Models\UsenetGroup;
7
use App\Services\Binaries\BinariesService;
8
use App\Services\NNTP\NNTPService;
9
use Illuminate\Console\Command;
10
use Illuminate\Support\Facades\DB;
11
use Illuminate\Support\Facades\Log;
12
13
class GetArticleRange extends Command
14
{
15
    /**
16
     * The name and signature of the console command.
17
     *
18
     * @var string
19
     */
20
    protected $signature = 'articles:get-range
21
                            {mode : Mode: binaries or backfill}
22
                            {group : Group name}
23
                            {first : First article number}
24
                            {last : Last article number}';
25
26
    /**
27
     * The console command description.
28
     *
29
     * @var string
30
     */
31
    protected $description = 'Get a range of article headers for a group';
32
33
    /**
34
     * Execute the console command.
35
     */
36
    public function handle(): int
37
    {
38
        $mode = $this->argument('mode');
39
        $groupName = $this->argument('group');
40
        $firstArticle = (int) $this->argument('first');
41
        $lastArticle = (int) $this->argument('last');
42
43
        if (! \in_array($mode, ['binaries', 'backfill'], true)) {
44
            $this->error('Mode must be either "binaries" or "backfill".');
45
46
            return self::FAILURE;
47
        }
48
49
        try {
50
            $nntp = $this->getNntp();
51
            $groupMySQL = UsenetGroup::getByName($groupName)->toArray();
52
53
            if ($groupMySQL === null) {
0 ignored issues
show
The condition $groupMySQL === null is always false.
Loading history...
54
                $this->error("Group not found: {$groupName}");
55
56
                return self::FAILURE;
57
            }
58
59
            if (NNTPService::isError($nntp->selectGroup($groupMySQL['name']))
60
                && NNTPService::isError($nntp->dataError($nntp, $groupMySQL['name']))) {
61
                return self::FAILURE;
62
            }
63
64
            $binaries = new BinariesService();
65
            $binaries->setNntp($nntp);
66
            $return = $binaries->scan(
67
                $groupMySQL,
68
                $firstArticle,
69
                $lastArticle,
70
                ((int) Settings::settingValue('safepartrepair') === 1 ? 'update' : 'backfill')
71
            );
72
73
            if (empty($return)) {
74
                return self::SUCCESS;
75
            }
76
77
            $this->updateGroupRecords($mode, $groupMySQL, $return);
78
79
            return self::SUCCESS;
80
        } catch (\Throwable $e) {
81
            Log::error($e->getTraceAsString());
82
            $this->error($e->getMessage());
83
84
            return self::FAILURE;
85
        }
86
    }
87
88
    /**
89
     * Update group records based on mode.
90
     */
91
    private function updateGroupRecords(string $mode, array $groupMySQL, array $return): void
92
    {
93
        $columns = [];
94
95
        switch ($mode) {
96
            case 'binaries':
97
                if ($return['lastArticleNumber'] <= $groupMySQL['last_record']) {
98
                    return;
99
                }
100
                $unixTime = is_numeric($return['lastArticleDate'])
101
                    ? $return['lastArticleDate']
102
                    : strtotime($return['lastArticleDate']);
103
                $columns[1] = sprintf('last_record_postdate = FROM_UNIXTIME(%s)', $unixTime);
104
                $columns[2] = sprintf('last_record = %s', $return['lastArticleNumber']);
105
                $query = sprintf(
106
                    'UPDATE usenet_groups SET %s, %s, last_updated = NOW() WHERE id = %d AND last_record < %s',
107
                    $columns[1],
108
                    $columns[2],
109
                    $groupMySQL['id'],
110
                    $return['lastArticleNumber']
111
                );
112
                break;
113
114
            case 'backfill':
115
                if ($return['firstArticleNumber'] >= $groupMySQL['first_record']) {
116
                    return;
117
                }
118
                $unixTime = is_numeric($return['firstArticleDate'])
119
                    ? $return['firstArticleDate']
120
                    : strtotime($return['firstArticleDate']);
121
                $columns[1] = sprintf('first_record_postdate = FROM_UNIXTIME(%s)', $unixTime);
122
                $columns[2] = sprintf('first_record = %s', $return['firstArticleNumber']);
123
                $query = sprintf(
124
                    'UPDATE usenet_groups SET %s, %s, last_updated = NOW() WHERE id = %d AND first_record > %s',
125
                    $columns[1],
126
                    $columns[2],
127
                    $groupMySQL['id'],
128
                    $return['firstArticleNumber']
129
                );
130
                break;
131
132
            default:
133
                return;
134
        }
135
136
        DB::update($query);
137
    }
138
139
    /**
140
     * Get NNTP connection.
141
     */
142
    private function getNntp(): NNTPService
143
    {
144
        $nntp = new NNTPService;
145
146
        $connectResult = config('nntmux_nntp.use_alternate_nntp_server') === true
147
            ? $nntp->doConnect(false, true)
148
            : $nntp->doConnect();
149
150
        if ($connectResult !== true) {
151
            $errorMessage = 'Unable to connect to usenet.';
152
            if (NNTPService::isError($connectResult)) {
153
                $errorMessage .= ' Error: '.$connectResult->getMessage();
154
            }
155
            throw new \Exception($errorMessage);
156
        }
157
158
        return $nntp;
159
    }
160
}
161