Skip to content

Commit 5c2f04a

Browse files
committed
Resolve duplicate github usernames
1 parent 03b167e commit 5c2f04a

File tree

5 files changed

+93
-39
lines changed

5 files changed

+93
-39
lines changed

app/Console/Commands/RemoveDuplicateGithubUsernames.php renamed to app/Console/Commands/ResolveDuplicateGithubUsernames.php

Lines changed: 30 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -5,81 +5,73 @@
55
use Illuminate\Console\Command;
66
use App\Models\User;
77
use Illuminate\Database\Eloquent\Collection;
8-
use Illuminate\Support\Facades\Http;
8+
use App\Social\GithubUserApi;
99

10-
class RemoveDuplicateGithubUsernames extends Command
10+
class ResolveDuplicateGithubUsernames extends Command
1111
{
12-
protected $signature = 'lio:remove-duplicate-github-usernames';
12+
protected $signature = 'lio:resolve-duplicate-github-usernames';
1313

14-
protected $description = 'Removes duplicate Github usernames from the database';
14+
protected $description = 'Resolve duplicate GitHub usernames from the database';
15+
16+
public function __construct(
17+
private readonly GithubUserApi $github
18+
){
19+
parent::__construct();
20+
}
1521

1622
public function handle(): void
1723
{
18-
$this->info('Removing duplicate Github usernames...');
24+
$this->info('Resolving duplicate Github usernames...');
1925

20-
$this->removeDuplicates();
26+
$this->resolveDuplicates();
2127

22-
$this->info('Duplicate Github usernames removed!');
28+
$this->info('Duplicate Github usernames resolved!');
2329
}
2430

25-
private function removeDuplicates(): void
31+
/**
32+
* Resolve duplicate github_username
33+
*/
34+
private function resolveDuplicates(): void
2635
{
2736
$this
2837
->duplicates()
2938
->groupBy('github_username')
30-
->each(function (Collection $duplicates) {
39+
->each(function (Collection $users) {
3140

3241
$uniqueUsernames = [];
3342

34-
foreach($duplicates as $user) {
43+
// order from the latest user to the oldest
44+
$users = $users->sortByDesc('created_at');
3545

36-
// set github_username to null if the user has no github_id
37-
if (! $user->github_id) {
38-
$user->update(['github_username' => null]);
39-
continue;
40-
}
46+
// resolve each user with the same github_username
47+
foreach($users as $user) {
4148

42-
// fetch the user from GitHub
43-
$githubUser = $this->fetchFromGithub($user);
49+
// fetch the user from GitHub API
50+
$githubUser = $this->github->find($user->github_id);
4451

45-
// if the user doesn't exist on GitHub, set github_username to null
52+
// if the user doesn't exist on GitHub
4653
if (! $githubUser || ! $githubUser->login) {
47-
$user->update(['github_username' => null, 'github_id' => null]);
54+
$user->update(['github_username' => null]);
4855
continue;
4956
}
5057

51-
// if the user's github_username marked as unique, set github_username to null
58+
// if the user's github_username marked as unique
5259
if (in_array($githubUser->login, $uniqueUsernames)) {
53-
//TODO: delete user?
54-
$user->update(['github_username' => null, 'github_id' => null]);
60+
$user->update(['github_username' => null]);
5561
continue;
5662
}
5763

5864
// if the user exists on GitHub, update the user's github_username
5965
$user->update(['github_username' => $githubUser->login]);
6066

61-
// add the user's github_username to the uniqueUsernames array
67+
// mark the user's github_username as unique
6268
$uniqueUsernames[] = $githubUser->login;
6369
}
6470
});
6571
}
6672

6773
/**
68-
* @param User $user
69-
* @return object|null
70-
*/
71-
private function fetchFromGithub(User $user): ?object
72-
{
73-
$response = Http::get("https://api.github.com/user/{$user->github_id}");
74-
75-
if ($response->failed()) {
76-
return null;
77-
}
78-
79-
return $response->object();
80-
}
81-
82-
/**
74+
* Get all users with duplicate github_username
8375
* @return Collection
8476
*/
8577
private function duplicates(): Collection

app/Http/Requests/RegisterRequest.php

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,6 @@ public function rules(): array
2626
'name' => 'required|max:255',
2727
'email' => 'required|email|max:255|unique:users',
2828
'username' => 'required|alpha_dash|max:40|unique:users',
29-
'github_username' => 'nullable|max:40|unique:users',
3029
'rules' => 'accepted',
3130
'terms' => 'accepted',
3231
'github_id' => ['required', new UniqueGitHubUser],
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace App\Listeners;
6+
7+
use App\Models\User;
8+
use App\Social\GithubUserApi;
9+
use Illuminate\Auth\Events\Registered;
10+
11+
final class FixDuplicateGithubUsername
12+
{
13+
public function __construct(
14+
private readonly GithubUserApi $github
15+
){
16+
}
17+
18+
public function handle(Registered $event): void
19+
{
20+
$users = User::query()
21+
->whereGithubUsername($event->user->github_username)
22+
->where('id', '!=', $event->user->id)
23+
->get();
24+
25+
$users->each(function (User $user) use ($event) {
26+
$githubUser = $this->github->find($user->github_id);
27+
28+
if (! $githubUser) {
29+
$user->update(['github_username' => null]);
30+
return;
31+
}
32+
33+
$user->update(['github_username' => $githubUser->login]);
34+
});
35+
}
36+
}

app/Providers/EventServiceProvider.php

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
use App\Listeners\SendNewSpamNotification;
1919
use App\Listeners\SubscribeUsersMentionedInReply;
2020
use App\Listeners\SubscribeUsersMentionedInThread;
21+
use App\Listeners\FixDuplicateGithubUsername;
2122
use App\Models\User;
2223
use App\Observers\UserObserver;
2324
use Illuminate\Auth\Events\Registered;
@@ -43,6 +44,7 @@ class EventServiceProvider extends ServiceProvider
4344
],
4445
Registered::class => [
4546
SendEmailVerificationNotification::class,
47+
FixDuplicateGithubUsername::class
4648
],
4749
ReplyWasCreated::class => [
4850
MarkLastActivity::class,

app/Social/GithubUserApi.php

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
<?php
2+
3+
namespace App\Social;
4+
5+
use Illuminate\Support\Facades\Http;
6+
7+
class GithubUserApi
8+
{
9+
private string $api = 'https://api.github.com/users';
10+
11+
/**
12+
* @param int $id GitHub user id
13+
* @return object|null
14+
*/
15+
public function find(int $id): ?object
16+
{
17+
$response = Http::get($this->api . '/' . $id);
18+
19+
if ($response->failed()) {
20+
return null;
21+
}
22+
23+
return $response->object();
24+
}
25+
}

0 commit comments

Comments
 (0)