Skip to content

Commit 8f2784f

Browse files
committed
Merge remote-tracking branch 'origin/main' into pr/607
2 parents 32dd239 + 2c8c374 commit 8f2784f

File tree

312 files changed

+24752
-3413
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

312 files changed

+24752
-3413
lines changed

.env.example

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,3 +57,5 @@ ANYSTACK_TOKEN=
5757
PIRSCH_TOKEN=
5858

5959
TORCHLIGHT_TOKEN=
60+
61+
VPN_API_TOKEN=

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ Your bio should be written in Markdown here. In the future, we may introduce an
3636
- The `github_url` should be a link to your GitHub profile.
3737
- The `twitter_url` should be a link to your Twitter profile. It is optional.
3838
- The `mastodon_url` should be a link to your Mastodon profile. It is optional.
39-
- The `sponsors_url` should be a link to your sponsors page like GitHub sponsors. It is optional.
39+
- The `sponsor_url` should be a link to your sponsors page like GitHub sponsors. It is optional.
4040

4141
### Submitting a plugin
4242

app/Actions/FetchPluginDataFromAnystack.php

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,10 @@ public function __invoke(): void
5353

5454
$prices = collect($advertisedProducts['prices'] ?? []);
5555

56+
if ($prices->isEmpty()) {
57+
return;
58+
}
59+
5660
$priceAmount = $prices->min('amount');
5761
$priceCurrency = $prices->keyBy('amount')[$priceAmount]['currency'];
5862

app/Actions/GetPluginsListData.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ function () use ($plugins): array {
2222
fn (Builder $query) => $query->whereIn('starrable_id', $plugins),
2323
)
2424
->where('starrable_type', 'plugin')
25+
->where(fn (Builder $query) => $query->whereNull('is_vpn_ip')->orWhere('is_vpn_ip', false))
2526
->groupBy('starrable_id')
2627
->selectRaw('count(id) as count, starrable_id')
2728
->get()

app/Actions/Star.php

Lines changed: 23 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,21 +2,42 @@
22

33
namespace App\Actions;
44

5+
use App\Jobs\CheckIfIpIsVpn;
56
use App\Models\Contracts\Starrable;
7+
use App\Models\Star as StarModel;
8+
use Illuminate\Support\Facades\RateLimiter;
69

710
class Star
811
{
912
public function __invoke(Starrable $starrable): void
1013
{
14+
if (RateLimiter::tooManyAttempts('star:' . request()->ip(), 3)) {
15+
return;
16+
}
17+
18+
RateLimiter::hit('star:' . request()->ip());
19+
1120
if ($starrable->stars()->where('ip', request()->ip())->exists()) {
1221
return;
1322
}
1423

24+
$existingIpStar = StarModel::query()
25+
->where('ip', request()->ip())
26+
->whereNotNull('is_vpn_ip')
27+
->first();
28+
1529
$starrable->stars()->create([
1630
'ip' => request()->ip(),
31+
'is_vpn_ip' => $existingIpStar?->is_vpn_ip,
1732
]);
1833

19-
$starrable->cacheStarsCount();
20-
$starrable->getAuthor()->cacheStarsCount();
34+
if ($existingIpStar?->is_vpn_ip !== true) {
35+
$starrable->cacheStarsCount();
36+
$starrable->getAuthor()->cacheStarsCount();
37+
}
38+
39+
if (! $existingIpStar) {
40+
dispatch(new CheckIfIpIsVpn(request()->ip()));
41+
}
2142
}
2243
}
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
<?php
2+
3+
namespace App\Http\Controllers\Api;
4+
5+
use App\Http\Controllers\Controller;
6+
use App\Models\Article;
7+
8+
class ArticleController extends Controller
9+
{
10+
public function index()
11+
{
12+
return Article::paginate();
13+
}
14+
15+
public function show(Article $article)
16+
{
17+
return $article->append('stars_count');
18+
}
19+
}

app/Http/Controllers/Articles/ListArticlesController.php

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
use App\Models\ArticleType;
99
use App\Models\Author;
1010
use App\Models\Star;
11+
use Illuminate\Database\Query\Builder;
1112

1213
class ListArticlesController extends Controller
1314
{
@@ -31,6 +32,7 @@ function (): array {
3132
$stars = Star::query()
3233
->toBase()
3334
->where('starrable_type', 'article')
35+
->where(fn (Builder $query) => $query->whereNull('is_vpn_ip')->orWhere('is_vpn_ip', false))
3436
->groupBy('starrable_id')
3537
->selectRaw('count(id) as count, starrable_id')
3638
->get()

app/Http/Controllers/Plugins/ListPluginsController.php

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
use App\Models\Plugin;
99
use App\Models\PluginCategory;
1010
use App\Models\Star;
11+
use Illuminate\Database\Eloquent\Builder;
1112

1213
class ListPluginsController extends Controller
1314
{
@@ -40,6 +41,7 @@ public function __invoke(GetPluginsListData $getPluginsListData)
4041
]),
4142
'starsCount' => Star::query()
4243
->where('starrable_type', 'plugin')
44+
->where(fn (Builder $query) => $query->whereNull('is_vpn_ip')->orWhere('is_vpn_ip', false))
4345
->count(),
4446
]);
4547
}

app/Jobs/CheckIfIpIsVpn.php

Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
<?php
2+
3+
namespace App\Jobs;
4+
5+
use App\Models\Star;
6+
use Illuminate\Bus\Queueable;
7+
use Illuminate\Contracts\Queue\ShouldQueue;
8+
use Illuminate\Foundation\Bus\Dispatchable;
9+
use Illuminate\Queue\InteractsWithQueue;
10+
use Illuminate\Queue\Middleware\RateLimited;
11+
use Illuminate\Queue\SerializesModels;
12+
use Illuminate\Support\Facades\Http;
13+
14+
class CheckIfIpIsVpn implements ShouldQueue
15+
{
16+
use Dispatchable;
17+
use InteractsWithQueue;
18+
use Queueable;
19+
use SerializesModels;
20+
21+
/**
22+
* Create a new job instance.
23+
*/
24+
public function __construct(
25+
public string $ip,
26+
) {
27+
}
28+
29+
/**
30+
* Execute the job.
31+
*/
32+
public function handle(): void
33+
{
34+
$existingIpStar = Star::query()
35+
->where('ip', $this->ip)
36+
->whereNotNull('is_vpn_ip')
37+
->first();
38+
39+
if ($existingIpStar) {
40+
Star::query()
41+
->where('ip', $this->ip)
42+
->update(['is_vpn_ip' => $existingIpStar->is_vpn_ip]);
43+
44+
return;
45+
}
46+
47+
$isVpn = Http::retry(10)
48+
->throw()
49+
->get('https://vpnapi.io/api/' . $this->ip . '?key=' . config('services.vpn_api.token'))
50+
->json('security.vpn');
51+
52+
if (blank($isVpn)) {
53+
$this->fail("Failed to check if IP is VPN: {$this->ip}");
54+
55+
return;
56+
}
57+
58+
Star::query()
59+
->where('ip', $this->ip)
60+
->update(['is_vpn_ip' => $isVpn]);
61+
}
62+
63+
/**
64+
* Get the middleware the job should pass through.
65+
*
66+
* @return array<int, object>
67+
*/
68+
public function middleware(): array
69+
{
70+
return [new RateLimited('vpn_api')];
71+
}
72+
}

app/Livewire/StarRecord.php

Lines changed: 17 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,11 @@
44

55
use App\Actions\Star;
66
use App\Actions\Unstar;
7+
use Illuminate\Contracts\View\View;
78
use Illuminate\Database\Eloquent\Model;
89
use Livewire\Component;
910

10-
class Starrecord extends Component
11+
class StarRecord extends Component
1112
{
1213
public Model $record;
1314

@@ -18,7 +19,7 @@ class Starrecord extends Component
1819
public function mount()
1920
{
2021
$this->isStarred = $this->isStarred();
21-
$this->starsCount = $this->record->getStarsCount();
22+
$this->starsCount = $this->calculateStarsCount();
2223
}
2324

2425
public function isStarred(): bool
@@ -31,19 +32,30 @@ public function toggleStar(): void
3132
if ($this->isStarred()) {
3233
app(Unstar::class)($this->record);
3334

34-
$this->starsCount = $this->record->getStarsCount();
35+
$this->starsCount = $this->calculateStarsCount();
3536
$this->isStarred = false;
3637

3738
return;
3839
}
3940

4041
app(Star::class)($this->record);
4142

42-
$this->starsCount = $this->record->getStarsCount();
43+
$this->starsCount = $this->calculateStarsCount();
4344
$this->isStarred = true;
4445
}
4546

46-
public function render()
47+
protected function calculateStarsCount(): int
48+
{
49+
$count = $this->record->getStarsCount();
50+
51+
if ($this->record->stars()->where('ip', request()->ip())->where('is_vpn_ip', true)->exists()) {
52+
$count++;
53+
}
54+
55+
return $count;
56+
}
57+
58+
public function render(): View
4759
{
4860
return view('livewire.star-record');
4961
}

0 commit comments

Comments
 (0)