Completed
Push — master ( 542498...7eecb4 )
by Kirill
03:23
created

GitterSync::syncUsers()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 22
Code Lines 14

Duplication

Lines 0
Ratio 0 %
Metric Value
dl 0
loc 22
rs 9.2
cc 2
eloc 14
nc 2
nop 2
1
<?php
2
3
/**
4
 * This file is part of GitterBot package.
5
 *
6
 * @author Serafim <[email protected]>
7
 * @date 24.09.2015 15:27
8
 *
9
 * For the full copyright and license information, please view the LICENSE
10
 * file that was distributed with this source code.
11
 */
12
13
namespace App\Console\Commands;
14
15
use App\Gitter\Console\CircleProgress;
16
use App\Karma;
17
use App\User;
18
use App\Room;
19
use App\Message;
20
use App\Gitter\Client;
21
use InvalidArgumentException;
22
use App\Gitter\Karma\Validator;
23
use Illuminate\Console\Command;
24
use Illuminate\Contracts\Config\Repository;
25
use Illuminate\Contracts\Container\Container;
26
use Symfony\Component\Finder\Finder;
27
28
/**
29
 * Class GitterSync
30
 * @package App\Console\Commands
31
 */
32
class GitterSync extends Command
33
{
34
    /**
35
     * The name and signature of the console command.
36
     *
37
     * @var string
38
     */
39
    protected $signature = 'gitter:sync {room}';
40
41
42
    /**
43
     * The console command description.
44
     *
45
     * @var string
46
     */
47
    protected $description = 'Fill users karma from all messages of target room.';
48
49
50
    /**
51
     * @var Container
52
     */
53
    protected $container;
54
55
    /**
56
     * @var Validator
57
     */
58
    protected $karma;
59
60
61
    /**
62
     * Execute the console command.
63
     *
64
     * @param Repository $config
65
     * @param Container $container
66
     *
67
     * @return mixed
68
     * @throws \InvalidArgumentException
69
     * @throws \RuntimeException
70
     * @throws \LogicException
71
     * @throws \Exception
72
     */
73
    public function handle(Repository $config, Container $container)
74
    {
75
        $this->syncUsers($config, $container);
76
77
        $config->set('gitter.output', false);
78
79
        $client = Client::make($config->get('gitter.token'), $this->argument('room'));
80
        $room = $container->make(Room::class);
81
82
        $this->karma = new Validator();
83
84
85
        $request = $this->cursor($client, $room);
86
        $count = 1;   // Start number
87
        $page = 0;   // Current page
88
        $chunk = 1000; // Per page
89
90
91
        while (true) {
92
            $messageChunk = $request($chunk, $chunk * $page++);
93
94
            if (!count($messageChunk)) {
95
                $this->output->write(sprintf("\r Well done. <comment>%s</comment> Messages was be loaded.", $count));
96
                break;
97
            }
98
99
100
            foreach ($messageChunk as $m) {
101
                echo "\rLoad message: $count ";
102
                $count++;
103
            }
104
105
            $name = 'sync/' . $page . '.json';
106
            echo '...dump to ' . $name;
107
            file_put_contents(
108
                storage_path($name),
109
                json_encode($messageChunk)
110
            );
111
        }
112
113
114
        echo "\n";
115
116
        $this->output->write('Flush database karma increments');
117
        Karma::query()
118
            ->where('room_id', $room->id)
119
            ->delete();
120
121
122
        $this->output->write('Start message parsing.');
123
        $finder = (new Finder())
124
            ->files()
125
            ->in(storage_path('sync'))
126
            ->name('*.json')
127
            ->sort(function($a, $b) {
128
                $parse = function(\SplFileInfo $file) {
129
                    return str_replace('.json', '', $file->getFilename());
130
                };
131
132
                return $parse($b) <=> $parse($a);
133
            });
134
135
136
        $count = 1;
137
        foreach ($finder as $file) {
138
            $messages = json_decode($file->getContents(), true);
139
            foreach ($messages as $message) {
140
                $message = Message::fromGitterObject($message);
141
142
                echo "\r" . $count++ . ' messages parsing: ' . $message->created_at;
143
                usleep(100);
144
                $this->onMessage($message);
145
            }
146
147
            unlink($file->getRealPath());
148
        }
149
    }
150
151
    /**
152
     * @param Client $client
153
     * @param Room $room
154
     * @return \Closure
155
     * @throws \InvalidArgumentException
156
     */
157
    public function cursor(Client $client, Room $room)
158
    {
159
        return function ($limit = 100, $skip = 0) use ($client, $room) {
160
            return $client->request('message.list', [
161
                'roomId' => $room->id,
162
                'limit'  => $limit,
163
                'skip'   => $skip,
164
            ]);
165
        };
166
    }
167
168
    /**
169
     * @param Message $message
170
     * @throws InvalidArgumentException
171
     */
172
    protected function onMessage(Message $message)
173
    {
174
        $collection = $this->karma->validate($message);
175
176
        foreach ($collection as $state) {
177
            $user = $state->getUser();
178
179
            if ($state->isIncrement()) {
180
                $message->user->addKarmaTo($user, $message);
181
            }
182
183
            if ($state->isIncrement() || $state->isTimeout() || $state->isSelf()) {
184
                echo "\r" . '[' . $message->created_at . '] ' .
185
                    $state->getTranslation($user->karma_text) . "\n";
186
            }
187
        }
188
    }
189
190
    /**
191
     * @param Repository $config
192
     * @param Container $container
193
     */
194
    public function syncUsers(Repository $config, Container $container)
195
    {
196
        $this->output->write('Start user sync...');
197
        $config->set('gitter.output', false);
198
199
        $client = Client::make($config->get('gitter.token'), $this->argument('room'));
200
        $room = $container->make(Room::class);
201
202
203
        $users = $client->request('room.users', ['roomId' => $room->id]);
204
        $message = "\r<comment>[%s/%s]</comment> %s%80s";
205
206
        $count = count($users);
207
        $current = 1;
208
        foreach ($users as $user) {
209
            $user = User::fromGitterObject($user);
210
            $this->output->write(sprintf($message, $current, $count, $user->login, ''));
211
            $current++;
212
        }
213
214
        $this->output->write(sprintf($message, $count, $count, 'OK', ''));
215
    }
216
}
217