diff --git a/.env.example b/.env.example index 244e6a5..84e517d 100644 --- a/.env.example +++ b/.env.example @@ -35,3 +35,8 @@ SPARKPOST_SECRET= PUSHER_APP_ID= PUSHER_APP_KEY= PUSHER_APP_SECRET= + +# (Optional) reCAPTCHA Key +# https://www.google.com/recaptcha +NOCAPTCHA_SECRET= +NOCAPTCHA_SITEKEY= diff --git a/Dockerfile b/Dockerfile index 9301d92..4960985 100644 --- a/Dockerfile +++ b/Dockerfile @@ -3,7 +3,7 @@ FROM php:7.1-apache ENV APACHE_DOCUMENT_ROOT /var/www/html/public RUN apt-get update \ - && apt-get install -y git libpq-dev \ + && apt-get install -y git libpq-dev unzip \ && docker-php-ext-install pdo_pgsql \ && curl -sS https://getcomposer.org/installer | php \ && mv composer.phar /usr/local/bin/composer \ diff --git a/app/Http/Controllers/Auth/RegisterController.php b/app/Http/Controllers/Auth/RegisterController.php index c68ed7e..0e79f03 100644 --- a/app/Http/Controllers/Auth/RegisterController.php +++ b/app/Http/Controllers/Auth/RegisterController.php @@ -47,11 +47,18 @@ class RegisterController extends Controller */ protected function validator(array $data) { - return Validator::make($data, [ + $rules = [ 'name' => 'required|string|regex:/^[a-zA-Z0-9_-]+$/u|max:15|unique:users', 'email' => 'required|string|email|max:255|unique:users', - 'password' => 'required|string|min:6|confirmed', - ], + 'password' => 'required|string|min:6|confirmed' + ]; + + // reCAPTCHAのキーが設定されている場合、判定を有効化 + if (!empty(config('captcha.secret'))) { + $rules['g-recaptcha-response'] = 'required|captcha'; + } + + return Validator::make($data, $rules, ['name.regex' => 'ユーザー名には半角英数字とアンダーバー、ハイフンのみ使用できます。'], ['name' => 'ユーザー名'] ); diff --git a/app/MetadataResolver/DLsiteResolver.php b/app/MetadataResolver/DLsiteResolver.php index 866bde0..a2ead81 100644 --- a/app/MetadataResolver/DLsiteResolver.php +++ b/app/MetadataResolver/DLsiteResolver.php @@ -2,8 +2,6 @@ namespace App\MetadataResolver; -use Illuminate\Support\Facades\Log; - class DLsiteResolver implements Resolver { public function resolve(string $url): Metadata diff --git a/app/MetadataResolver/MetadataResolver.php b/app/MetadataResolver/MetadataResolver.php index 8180589..528c73c 100644 --- a/app/MetadataResolver/MetadataResolver.php +++ b/app/MetadataResolver/MetadataResolver.php @@ -12,6 +12,7 @@ class MetadataResolver implements Resolver '~ec\.toranoana\.jp/tora_r/ec/item/.*~' => ToranoanaResolver::class, '~iwara\.tv/videos/.*~' => IwaraResolver::class, '~www\.dlsite\.com/.*/work/=/product_id/..\d+\.html~' => DLsiteResolver::class, + '~www\.pixiv\.net/member_illust\.php\?illust_id=\d+~' => PixivResolver::class, '/.*/' => OGPResolver::class ]; diff --git a/app/MetadataResolver/PixivResolver.php b/app/MetadataResolver/PixivResolver.php new file mode 100644 index 0000000..c06f0e4 --- /dev/null +++ b/app/MetadataResolver/PixivResolver.php @@ -0,0 +1,93 @@ +get($url); + if ($res->getStatusCode() === 200) { + $ogpResolver = new OGPResolver(); + $metadata = $ogpResolver->parse($res->getBody()); + + preg_match("~https://i\.pximg\.net/c/128x128/img-master/img/\d{4}/\d{2}/\d{2}/\d{2}/\d{2}/\d{2}/{$illustId}_p0_square1200\.jpg~", $res->getBody(), $match); + $illustThumbnailUrl = $match[0]; + + $illustUrl = $this->thumbnailToMasterUrl($illustThumbnailUrl); + + // 指定ページに変換 + $illustUrl = str_replace("p0_master", "p{$page}_master", $illustUrl); + + $metadata->image = $this->proxize($illustUrl); + + return $metadata; + } else { + throw new \RuntimeException("{$res->getStatusCode()}: $url"); + } + } else { + $client = new \GuzzleHttp\Client(); + $res = $client->get($url); + if ($res->getStatusCode() === 200) { + $ogpResolver = new OGPResolver(); + $metadata = $ogpResolver->parse($res->getBody()); + + // OGP がデフォルト画像であるようならなんとかして画像を取得する + if (strpos($metadata->image, "pixiv_logo.gif") || strpos($metadata->image, "pictures.jpg")) { + + // 作品ページの場合のみ対応 + if (strpos(parse_url($url)["query"], "mode=medium")) { + preg_match("~https://i\.pximg\.net/c/128x128/img-master/img/\d{4}/\d{2}/\d{2}/\d{2}/\d{2}/\d{2}/{$illustId}(_p0)?_square1200\.jpg~", $res->getBody(), $match); + $illustThumbnailUrl = $match[0]; + + $illustUrl = $this->thumbnailToMasterUrl($illustThumbnailUrl); + + $metadata->image = $this->proxize($illustUrl); + } + } + + return $metadata; + } else { + throw new \RuntimeException("{$res->getStatusCode()}: $url"); + } + } + } +} diff --git a/composer.json b/composer.json index b309ae6..b64f2d1 100644 --- a/composer.json +++ b/composer.json @@ -6,6 +6,7 @@ "type": "project", "require": { "php": ">=7.0.0", + "anhskohbo/no-captcha": "^3.0", "doctrine/dbal": "^2.9", "fideloper/proxy": "~3.3", "guzzlehttp/guzzle": "^6.3", diff --git a/composer.lock b/composer.lock index 0d47d7a..ac5ace9 100644 --- a/composer.lock +++ b/composer.lock @@ -4,8 +4,67 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file", "This file is @generated automatically" ], - "content-hash": "6ac4cd158b1f93a24e21fce57d4404c8", + "content-hash": "4a3dffd3f7adecbb805a02c43f5c1f25", "packages": [ + { + "name": "anhskohbo/no-captcha", + "version": "3.0.3", + "source": { + "type": "git", + "url": "https://github.com/anhskohbo/no-captcha.git", + "reference": "164715a2de0fded5979e7a9b7721785d72a4a7d3" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/anhskohbo/no-captcha/zipball/164715a2de0fded5979e7a9b7721785d72a4a7d3", + "reference": "164715a2de0fded5979e7a9b7721785d72a4a7d3", + "shasum": "" + }, + "require": { + "guzzlehttp/guzzle": "^6.2", + "illuminate/support": "5.0.*|5.1.*|5.2.*|5.3.*|5.4.*|5.5.*|5.6.*|5.7.*", + "php": ">=5.5.5" + }, + "require-dev": { + "phpunit/phpunit": "~4.8" + }, + "type": "library", + "extra": { + "laravel": { + "providers": [ + "Anhskohbo\\NoCaptcha\\NoCaptchaServiceProvider" + ], + "aliases": { + "NoCaptcha": "Anhskohbo\\NoCaptcha\\Facades\\NoCaptcha" + } + } + }, + "autoload": { + "psr-4": { + "Anhskohbo\\NoCaptcha\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "anhskohbo", + "email": "anhskohbo@gmail.com" + } + ], + "description": "No CAPTCHA reCAPTCHA For Laravel.", + "keywords": [ + "captcha", + "laravel", + "laravel4", + "laravel5", + "no-captcha", + "recaptcha" + ], + "time": "2018-08-27T02:16:31+00:00" + }, { "name": "dnoegel/php-xdg-base-dir", "version": "0.1", diff --git a/resources/lang/ja/validation.php b/resources/lang/ja/validation.php index 7b11851..9c9217f 100644 --- a/resources/lang/ja/validation.php +++ b/resources/lang/ja/validation.php @@ -99,6 +99,10 @@ return [ 'attribute-name' => [ 'rule-name' => 'custom-message', ], + 'g-recaptcha-response' => [ + 'required' => '「私はロボットではありません」にチェックを入れてください。', + 'captcha' => 'reCAPTCHAチェックに失敗しました。何度試しても解決しない場合、管理者にお問い合わせください。', + ], ], /* diff --git a/resources/views/auth/register.blade.php b/resources/views/auth/register.blade.php index 7ef6a7d..ff9fc34 100644 --- a/resources/views/auth/register.blade.php +++ b/resources/views/auth/register.blade.php @@ -2,6 +2,12 @@ @section('title', '新規登録') +@push('head') + @if (!empty(config('captcha.secret'))) + {!! NoCaptcha::renderJs() !!} + @endif +@endpush + @section('content')

新規登録

@@ -53,6 +59,16 @@
+ @if (!empty(config('captcha.secret'))) +
+
+ {!! NoCaptcha::display() !!} +
+ @if ($errors->has('g-recaptcha-response')) +
{{ $errors->first('g-recaptcha-response') }}
+ @endif +
+ @endif