HoshiAI-be/app/Http/Controllers/HitcountController.php
2025-11-11 19:41:58 +01:00

178 lines
6.1 KiB
PHP

<?php
namespace App\Http\Controllers;
use App\Http\Resources\HitcountResource;
use App\Models\Hitcount;
use App\Models\Log;
use Detection\MobileDetect;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Http;
class HitcountController extends Controller
{
/**
* @OA\Get(
* path="/api/hitcounts",
* summary="Get list of hitcounts (paginated, only admin)",
* description="Returns a paginated list of all recorded hitcounts. Requires admin privileges.",
* operationId="getHitcounts",
* tags={"Hitcounts"},
* security={{"bearerAuth":{}}},
* @OA\Response(
* response=200,
* description="List of hitcounts",
* @OA\JsonContent(
* type="object",
* @OA\Property(
* property="data",
* type="array",
* @OA\Items(ref="#/components/schemas/HitcountResource")
* ),
* @OA\Property(property="links", type="object"),
* @OA\Property(property="meta", type="object")
* )
* ),
* @OA\Response(response=401, description="Unauthenticated"),
* @OA\Response(response=403, description="Forbidden (not admin)")
* )
*/
public function index()
{
$this->authorize('viewAny', Hitcount::class);
return HitcountResource::collection(Hitcount::paginate());
}
/**
* @OA\Get(
* path="/api/hitcounts/{id}",
* summary="Get a specific hitcount (only admin)",
* description="Returns detailed information about a specific hitcount. Requires admin privileges.",
* operationId="getHitcount",
* tags={"Hitcounts"},
* security={{"bearerAuth":{}}},
* @OA\Parameter(
* name="id",
* in="path",
* required=true,
* description="Hitcount ID",
* @OA\Schema(type="integer", example=1)
* ),
* @OA\Response(
* response=200,
* description="Hitcount details",
* @OA\JsonContent(ref="#/components/schemas/HitcountResource")
* ),
* @OA\Response(response=401, description="Unauthenticated"),
* @OA\Response(response=403, description="Forbidden (not admin)"),
* @OA\Response(response=404, description="Not Found")
* )
*/
public function show(Hitcount $hitcount)
{
$this->authorize('view', $hitcount);
return new HitcountResource($hitcount);
}
/**
* @OA\Delete(
* path="/api/hitcounts/{id}",
* summary="Delete a hitcount (only admin)",
* description="Deletes a specific hitcount entry. Requires admin privileges.",
* operationId="deleteHitcount",
* tags={"Hitcounts"},
* security={{"bearerAuth":{}}},
* @OA\Parameter(
* name="id",
* in="path",
* required=true,
* description="Hitcount ID to delete",
* @OA\Schema(type="integer", example=1)
* ),
* @OA\Response(
* response=200,
* description="Hitcount deleted successfully",
* @OA\JsonContent(
* type="object",
* @OA\Property(property="message", type="string", example="The hitcount was deleted")
* )
* ),
* @OA\Response(response=401, description="Unauthenticated"),
* @OA\Response(response=403, description="Forbidden (not admin)"),
* @OA\Response(response=404, description="Not Found")
* )
*/
public function destroy(Request $request, Hitcount $hitcount)
{
$this->authorize('delete', $hitcount);
$hitcount->delete();
Log::writeLog("Hitcount '" . $hitcount->id . "' is deleted by " . $request->user()->username);
return ['message' => 'The hitcount was deleted'];
}
/**
* @OA\Post(
* path="/api/hit",
* summary="Register a hit for a URL",
* description="Stores information about a visit, including IP, device, user agent, and country",
* tags={"Hitcounts"},
* @OA\RequestBody(
* required=true,
* @OA\JsonContent(
* required={"url"},
* @OA\Property(property="url", type="string", maxLength=255, example="https://my-application.com")
* )
* ),
* @OA\Response(
* response=200,
* description="Hitcount successfully set",
* @OA\JsonContent(
* @OA\Property(property="message", type="string", example="The hitcount is set")
* )
* ),
* @OA\Response(
* response=422,
* description="Validation error",
* @OA\JsonContent(
* @OA\Property(property="message", type="string", example="The given data was invalid."),
* @OA\Property(
* property="errors",
* type="object",
* example={"url": {"The url field is required."}}
* )
* )
* )
* )
*/
public function callHit(Request $request)
{
$fields = $request->validate([
'url' => 'required|max:255'
]);
$hitcount = new Hitcount();
$ip = $request->ip();
$hitcount->ip = $ip;
$hitcount->user_agent = $request->userAgent();
$hitcount->url = $fields['url'];
$detect = new MobileDetect();
$hitcount->device_type = ($detect->isMobile() ? ($detect->isTablet() ? 'tablet' : 'phone') : 'desktop');
$previousHitcount = Hitcount::where('ip', $ip)->first();
if($previousHitcount) {
$hitcount->country = $previousHitcount->country;
}
else {
$response = Http::get("http://ip-api.com/json/{$hitcount->ip}?fields=country");
if ($response->ok()) {
$hitcount->country = $response->json('country');
} else {
$hitcount->country = null;
}
}
$hitcount->save();
return ['message' => 'The hitcount is set'];
}
}