diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 0000000..21edee1 --- /dev/null +++ b/.dockerignore @@ -0,0 +1,4 @@ +.idea +.git +.gitignore +.gitattributes diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..892f260 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,14 @@ +FROM php:7.1-apache + +ENV APACHE_DOCUMENT_ROOT /var/www/html/public + +RUN apt-get update \ + && apt-get install -y libpq-dev \ + && docker-php-ext-install pdo_pgsql \ + && curl -sS https://getcomposer.org/installer | php \ + && mv composer.phar /usr/local/bin/composer \ + && sed -ri -e 's!/var/www/html!${APACHE_DOCUMENT_ROOT}!g' /etc/apache2/sites-available/*.conf \ + && sed -ri -e 's!/var/www/!${APACHE_DOCUMENT_ROOT}!g' /etc/apache2/apache2.conf /etc/apache2/conf-available/*.conf \ + && a2enmod rewrite + +WORKDIR /var/www/html diff --git a/app/Events/LinkDiscovered.php b/app/Events/LinkDiscovered.php new file mode 100644 index 0000000..0163dc6 --- /dev/null +++ b/app/Events/LinkDiscovered.php @@ -0,0 +1,24 @@ +url = $url; + } +} diff --git a/app/Http/Controllers/EjaculationController.php b/app/Http/Controllers/EjaculationController.php index 1509443..43b3d13 100644 --- a/app/Http/Controllers/EjaculationController.php +++ b/app/Http/Controllers/EjaculationController.php @@ -2,6 +2,7 @@ namespace App\Http\Controllers; +use App\Events\LinkDiscovered; use App\Tag; use App\User; use Carbon\Carbon; @@ -71,6 +72,10 @@ class EjaculationController extends Controller } $ejaculation->tags()->sync($tagIds); + if (!empty($ejaculation->link)) { + event(new LinkDiscovered($ejaculation->link)); + } + return redirect()->route('checkin.show', ['id' => $ejaculation->id])->with('status', 'チェックインしました!'); } @@ -148,6 +153,10 @@ class EjaculationController extends Controller } $ejaculation->tags()->sync($tagIds); + if (!empty($ejaculation->link)) { + event(new LinkDiscovered($ejaculation->link)); + } + return redirect()->route('checkin.show', ['id' => $ejaculation->id])->with('status', 'チェックインを修正しました!'); } diff --git a/app/Listeners/LinkCollector.php b/app/Listeners/LinkCollector.php new file mode 100644 index 0000000..6bd41ad --- /dev/null +++ b/app/Listeners/LinkCollector.php @@ -0,0 +1,54 @@ +formatter = $formatter; + $this->metadataResolver = $metadataResolver; + } + + /** + * Handle the event. + * + * @param LinkDiscovered $event + * @return void + */ + public function handle(LinkDiscovered $event) + { + // URLの正規化 + $url = $this->formatter->normalizeUrl($event->url); + + // 無かったら取得 + // TODO: ある程度古かったら再取得とかありだと思う + $metadata = Metadata::find($url); + if ($metadata == null) { + $resolved = $this->metadataResolver->resolve($url); + Metadata::create([ + 'url' => $url, + 'title' => $resolved->title, + 'description' => $resolved->description, + 'image' => $resolved->image + ]); + } + } +} diff --git a/app/Metadata.php b/app/Metadata.php new file mode 100644 index 0000000..98badb6 --- /dev/null +++ b/app/Metadata.php @@ -0,0 +1,15 @@ +get('https://api.komiflo.com/content/id/' . $id); + if ($res->getStatusCode() === 200) { + $json = json_decode($res->getBody()->getContents(), true); + $metadata = new Metadata(); + + $metadata->title = $json['content']['data']['title'] ?? ''; + $metadata->description = ($json['content']['attributes']['artists']['children'][0]['data']['name'] ?? '?') . + ' - ' . + ($json['content']['parents'][0]['data']['title'] ?? '?'); + + return $metadata; + } else { + throw new \RuntimeException("{$res->getStatusCode()}: $url"); + } + } +} \ No newline at end of file diff --git a/app/MetadataResolver/MetadataResolver.php b/app/MetadataResolver/MetadataResolver.php index 1896376..1a19f3a 100644 --- a/app/MetadataResolver/MetadataResolver.php +++ b/app/MetadataResolver/MetadataResolver.php @@ -7,6 +7,7 @@ class MetadataResolver implements Resolver public $rules = [ '~(((sp\.)?seiga\.nicovideo\.jp/seiga(/#!)?|nico\.ms))/im~' => NicoSeigaResolver::class, '~nijie\.info/view\.php~' => NijieResolver::class, + '~komiflo\.com(/#!)?/comics/(\\d+)~' => KomifloResolver::class, '/.*/' => OGPResolver::class ]; diff --git a/app/Providers/EventServiceProvider.php b/app/Providers/EventServiceProvider.php index fca6152..4e1b51e 100644 --- a/app/Providers/EventServiceProvider.php +++ b/app/Providers/EventServiceProvider.php @@ -13,9 +13,9 @@ class EventServiceProvider extends ServiceProvider * @var array */ protected $listen = [ - 'App\Events\Event' => [ - 'App\Listeners\EventListener', - ], + 'App\Events\LinkDiscovered' => [ + 'App\Listeners\LinkCollector' + ] ]; /** diff --git a/app/Utilities/Formatter.php b/app/Utilities/Formatter.php index fd7da98..c19e6f2 100644 --- a/app/Utilities/Formatter.php +++ b/app/Utilities/Formatter.php @@ -36,4 +36,29 @@ class Formatter { return $this->linkify->processUrls($text); } + + /** + * URLを正規化します。 + * @param string $url URL + * @return string 正規化されたURL + */ + public function normalizeUrl($url) + { + // Decode + $url = urldecode($url); + + // Remove Hashbang + $url = preg_replace('~/#!/~u', '/', $url); + + // Sort query parameters + $query = parse_url($url, PHP_URL_QUERY); + if (!empty($query)) { + $url = str_replace_last('?' . $query, '', $url); + parse_str($query, $params); + ksort($params); + $url = $url . '?' . http_build_query($params); + } + + return $url; + } } \ No newline at end of file diff --git a/database/migrations/2018_06_07_225520_create_metadata_table.php b/database/migrations/2018_06_07_225520_create_metadata_table.php new file mode 100644 index 0000000..3cb78f6 --- /dev/null +++ b/database/migrations/2018_06_07_225520_create_metadata_table.php @@ -0,0 +1,36 @@ +string('url'); + $table->string('title'); + $table->string('description'); + $table->string('image'); + $table->timestamps(); + + $table->index('url'); + }); + } + + /** + * Reverse the migrations. + * + * @return void + */ + public function down() + { + Schema::dropIfExists('metadata'); + } +} diff --git a/docker-compose.yml b/docker-compose.yml new file mode 100644 index 0000000..f5fbae3 --- /dev/null +++ b/docker-compose.yml @@ -0,0 +1,38 @@ +version: "3" + +services: + web: + build: . + environment: + DB_CONNECTION: pgsql + DB_HOST: db + DB_PORT: 5432 + DB_DATABASE: tissue + DB_USERNAME: tissue + DB_PASSWORD: tissue + volumes: + - .:/var/www/html + networks: + - backend + ports: + - 4545:80 + restart: always + depends_on: + - db + db: + image: postgres:10-alpine + environment: + POSTGRES_DB: tissue + POSTGRES_USER: tissue + POSTGRES_PASSWORD: tissue + volumes: + - db:/var/lib/postgresql/data + networks: + - backend + restart: always + +networks: + backend: + +volumes: + db: \ No newline at end of file diff --git a/resources/views/ejaculation/show.blade.php b/resources/views/ejaculation/show.blade.php index c9006cc..007398c 100644 --- a/resources/views/ejaculation/show.blade.php +++ b/resources/views/ejaculation/show.blade.php @@ -26,13 +26,13 @@
{{ $ejaculatedSpan ?? '精通' }} {{ $ejaculation->before_date }}{{ !empty($ejaculation->before_date) ? ' ~ ' : '' }}{{ $ejaculation->ejaculated_date->format('Y/m/d H:i') }}
- @if ($user->isMe()) -
- +
+ + @if ($user->isMe()) -
- @endif + @endif +
@if ($ejaculation->is_private || $ejaculation->tags->isNotEmpty()) diff --git a/resources/views/home.blade.php b/resources/views/home.blade.php index 7649afc..f5482aa 100644 --- a/resources/views/home.blade.php +++ b/resources/views/home.blade.php @@ -37,6 +37,9 @@ @{{ $ejaculation->user->name }} {{ $ejaculation->ejaculated_date->format('Y/m/d H:i') }} +
+ +
@if ($ejaculation->tags->isNotEmpty()) diff --git a/resources/views/user/profile.blade.php b/resources/views/user/profile.blade.php index 8bc7c14..c1789ee 100644 --- a/resources/views/user/profile.blade.php +++ b/resources/views/user/profile.blade.php @@ -12,13 +12,13 @@
{{ $ejaculation->ejaculated_span ?? '精通' }} {{ $ejaculation->before_date }}{{ !empty($ejaculation->before_date) ? ' ~ ' : '' }}{{ $ejaculation->ejaculated_date->format('Y/m/d H:i') }}
- @if ($user->isMe())
- - + @if ($user->isMe()) + + + @endif
- @endif
@if ($ejaculation->is_private || $ejaculation->tags->isNotEmpty()) diff --git a/routes/api.php b/routes/api.php index 083a21b..4ef841a 100644 --- a/routes/api.php +++ b/routes/api.php @@ -1,6 +1,7 @@ get('/user', function (Request $request) { return $request->user(); }); -Route::get('/checkin/card', function (Request $request, MetadataResolver $resolver) { +Route::get('/checkin/card', function (Request $request, MetadataResolver $resolver, Formatter $formatter) { $request->validate([ 'url:required|url' ]); - $url = $request->input('url'); + $url = $formatter->normalizeUrl($request->input('url')); + + $metadata = App\Metadata::find($url); + if ($metadata == null) { + $resolved = $resolver->resolve($url); + $metadata = App\Metadata::create([ + 'url' => $url, + 'title' => $resolved->title, + 'description' => $resolved->description, + 'image' => $resolved->image + ]); + } - $metadata = $resolver->resolve($url); $response = response()->json($metadata); if (!config('app.debug')) { $response = $response->setCache(['public' => true, 'max_age' => 86400]);