add POST /api/webhooks/checkin/{id}
This commit is contained in:
parent
5926c6e640
commit
de07e950f2
@ -25,4 +25,9 @@ class CheckinWebhook extends Model
|
|||||||
{
|
{
|
||||||
return $this->belongsTo(User::class);
|
return $this->belongsTo(User::class);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function isAvailable()
|
||||||
|
{
|
||||||
|
return $this->user() !== null;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -14,6 +14,7 @@ class Ejaculation extends Model
|
|||||||
|
|
||||||
const SOURCE_WEB = 'web';
|
const SOURCE_WEB = 'web';
|
||||||
const SOURCE_CSV = 'csv';
|
const SOURCE_CSV = 'csv';
|
||||||
|
const SOURCE_WEBHOOK = 'webhook';
|
||||||
|
|
||||||
protected $fillable = [
|
protected $fillable = [
|
||||||
'user_id', 'ejaculated_date',
|
'user_id', 'ejaculated_date',
|
||||||
|
@ -2,13 +2,100 @@
|
|||||||
|
|
||||||
namespace App\Http\Controllers\Api;
|
namespace App\Http\Controllers\Api;
|
||||||
|
|
||||||
|
use App\CheckinWebhook;
|
||||||
|
use App\Ejaculation;
|
||||||
|
use App\Events\LinkDiscovered;
|
||||||
use App\Http\Controllers\Controller;
|
use App\Http\Controllers\Controller;
|
||||||
|
use App\Tag;
|
||||||
|
use Carbon\Carbon;
|
||||||
use Illuminate\Http\Request;
|
use Illuminate\Http\Request;
|
||||||
|
use Illuminate\Support\Facades\Validator;
|
||||||
|
|
||||||
class WebhookController extends Controller
|
class WebhookController extends Controller
|
||||||
{
|
{
|
||||||
public function checkin(Request $request)
|
public function checkin(CheckinWebhook $webhook, Request $request)
|
||||||
{
|
{
|
||||||
// TODO
|
if (!$webhook->isAvailable()) {
|
||||||
|
return response()->json([
|
||||||
|
'status' => 404,
|
||||||
|
'error' => [
|
||||||
|
'message' => 'The webhook is unavailable'
|
||||||
|
]
|
||||||
|
], 404);
|
||||||
|
}
|
||||||
|
|
||||||
|
$inputs = $request->all();
|
||||||
|
|
||||||
|
$validator = Validator::make($inputs, [
|
||||||
|
'date' => 'nullable|date_format:Y/m/d',
|
||||||
|
'time' => 'nullable|date_format:H:i',
|
||||||
|
'note' => 'nullable|string|max:500',
|
||||||
|
'link' => 'nullable|url|max:2000',
|
||||||
|
'tags' => 'nullable|array',
|
||||||
|
'tags.*' => ['string', 'not_regex:/\s/u'],
|
||||||
|
'is_private' => 'nullable|boolean',
|
||||||
|
'is_too_sensitive' => 'nullable|boolean',
|
||||||
|
], [
|
||||||
|
'tags.*.not_regex' => 'The :attribute cannot contain spaces.'
|
||||||
|
]);
|
||||||
|
|
||||||
|
if ($validator->fails()) {
|
||||||
|
return response()->json([
|
||||||
|
'status' => 422,
|
||||||
|
'error' => [
|
||||||
|
'message' => 'Validation failed',
|
||||||
|
'violations' => $validator->errors()->all(),
|
||||||
|
]
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
$ejaculatedDate = now()->startOfMinute();
|
||||||
|
if (!empty($inputs['date'])) {
|
||||||
|
$ejaculatedDate = $ejaculatedDate->setDateFrom(Carbon::createFromFormat('Y/m/d', $inputs['date']));
|
||||||
|
}
|
||||||
|
if (!empty($inputs['time'])) {
|
||||||
|
$ejaculatedDate = $ejaculatedDate->setTimeFrom(Carbon::createFromFormat('H:i', $inputs['time']));
|
||||||
|
}
|
||||||
|
if (Ejaculation::where(['user_id' => $webhook->user_id, 'ejaculated_date' => $ejaculatedDate])->count()) {
|
||||||
|
return response()->json([
|
||||||
|
'status' => 422,
|
||||||
|
'error' => [
|
||||||
|
'message' => 'Checkin already exists in this time',
|
||||||
|
]
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
$ejaculation = Ejaculation::create([
|
||||||
|
'user_id' => $webhook->user_id,
|
||||||
|
'ejaculated_date' => $ejaculatedDate,
|
||||||
|
'note' => $inputs['note'] ?? '',
|
||||||
|
'link' => $inputs['link'] ?? '',
|
||||||
|
'source' => Ejaculation::SOURCE_WEBHOOK,
|
||||||
|
'is_private' => $request->has('is_private') ?? false,
|
||||||
|
'is_too_sensitive' => $request->has('is_too_sensitive') ?? false
|
||||||
|
]);
|
||||||
|
|
||||||
|
$tagIds = [];
|
||||||
|
if (!empty($inputs['tags'])) {
|
||||||
|
foreach ($inputs['tags'] as $tag) {
|
||||||
|
$tag = trim($tag);
|
||||||
|
if ($tag === '') {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
$tag = Tag::firstOrCreate(['name' => $tag]);
|
||||||
|
$tagIds[] = $tag->id;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
$ejaculation->tags()->sync($tagIds);
|
||||||
|
|
||||||
|
if (!empty($ejaculation->link)) {
|
||||||
|
event(new LinkDiscovered($ejaculation->link));
|
||||||
|
}
|
||||||
|
|
||||||
|
return response()->json([
|
||||||
|
'status' => 200,
|
||||||
|
'checkin' => $ejaculation
|
||||||
|
]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -38,15 +38,17 @@ class Kernel extends HttpKernel
|
|||||||
\App\Http\Middleware\NormalizeLineEnding::class,
|
\App\Http\Middleware\NormalizeLineEnding::class,
|
||||||
],
|
],
|
||||||
|
|
||||||
// 現時点では内部APIしかないので、認証の手間を省くためにステートフルにしている。
|
|
||||||
'api' => [
|
'api' => [
|
||||||
|
'throttle:60,1',
|
||||||
|
\Illuminate\Routing\Middleware\SubstituteBindings::class,
|
||||||
|
],
|
||||||
|
|
||||||
|
'stateful' => [
|
||||||
\App\Http\Middleware\EncryptCookies::class,
|
\App\Http\Middleware\EncryptCookies::class,
|
||||||
\Illuminate\Cookie\Middleware\AddQueuedCookiesToResponse::class,
|
\Illuminate\Cookie\Middleware\AddQueuedCookiesToResponse::class,
|
||||||
\Illuminate\Session\Middleware\StartSession::class,
|
\Illuminate\Session\Middleware\StartSession::class,
|
||||||
\App\Http\Middleware\VerifyCsrfToken::class,
|
\App\Http\Middleware\VerifyCsrfToken::class,
|
||||||
'throttle:60,1',
|
]
|
||||||
\Illuminate\Routing\Middleware\SubstituteBindings::class,
|
|
||||||
],
|
|
||||||
];
|
];
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -11,9 +11,9 @@ class EjaculationSourcesSeeder extends Seeder
|
|||||||
*/
|
*/
|
||||||
public function run()
|
public function run()
|
||||||
{
|
{
|
||||||
$sources = ['web', 'csv'];
|
$sources = ['web', 'csv', 'webhook'];
|
||||||
foreach ($sources as $source) {
|
foreach ($sources as $source) {
|
||||||
DB::table('ejaculation_sources')->insert(['name' => $source]);
|
DB::table('ejaculation_sources')->insertOrIgnore(['name' => $source]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -17,9 +17,10 @@
|
|||||||
|
|
||||||
Route::get('/checkin/card', 'Api\\CardController@show');
|
Route::get('/checkin/card', 'Api\\CardController@show');
|
||||||
|
|
||||||
Route::middleware('auth')->group(function () {
|
Route::middleware(['stateful', 'auth'])->group(function () {
|
||||||
Route::post('/likes', 'Api\\LikeController@store');
|
Route::post('/likes', 'Api\\LikeController@store');
|
||||||
Route::delete('/likes/{id}', 'Api\\LikeController@destroy');
|
Route::delete('/likes/{id}', 'Api\\LikeController@destroy');
|
||||||
});
|
});
|
||||||
|
|
||||||
Route::post('/webhooks/checkin/{webhook}', 'Api\\WebhookController@checkin');
|
Route::post('/webhooks/checkin/{webhook}', 'Api\\WebhookController@checkin')
|
||||||
|
->middleware('throttle:15,15,checkin_webhook');
|
||||||
|
Loading…
Reference in New Issue
Block a user