Skip to content

Commit

Permalink
Merge branch 'main' into add-felyx
Browse files Browse the repository at this point in the history
  • Loading branch information
JakubKermes authored May 14, 2024
2 parents 9e143e7 + 8f72356 commit dd3f63c
Show file tree
Hide file tree
Showing 35 changed files with 1,194 additions and 51 deletions.
2 changes: 2 additions & 0 deletions .env.example
Original file line number Diff line number Diff line change
Expand Up @@ -62,3 +62,5 @@ GOOGLE_REDIRECT_URI=http://escooters.blumilk.localhost/login/google/redirect
FACEBOOK_CLIENT_ID=
FACEBOOK_CLIENT_SECRET=
FACEBOOK_REDIRECT_URI=http://escooters.blumilk.localhost/login/facebook/redirect

OPENAI_API_KEY=
2 changes: 1 addition & 1 deletion api.json

Large diffs are not rendered by default.

4 changes: 4 additions & 0 deletions app/Exceptions/ExceptionHandler.php
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,10 @@ public function render($request, Throwable $exception)
return back()->withErrors($exception->errors());
}

if ($exception instanceof OpenAiException) {
return response()->json(["error" => $exception->getMessage()], $exception->getCode());
}

$response = parent::render($request, $exception);
$statusCode = $response->status();

Expand Down
14 changes: 14 additions & 0 deletions app/Exceptions/OpenAiException.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
<?php

declare(strict_types=1);

namespace App\Exceptions;

use Exception;
use Symfony\Component\HttpFoundation\Response;

class OpenAiException extends Exception
{
protected $message = "OpenAI API connection error";
protected $code = Response::HTTP_INTERNAL_SERVER_ERROR;
}
50 changes: 50 additions & 0 deletions app/Http/Controllers/Api/RulesController.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
<?php

declare(strict_types=1);

namespace App\Http\Controllers\Api;

use App\Models\City;
use App\Models\Country;
use App\Models\Rules;
use App\Services\OpenAIService;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;

class RulesController
{
public function getRules(Country $country, City $city): JsonResponse
{
$rules = Rules::query()
->where("city_id", $city->id)
->first();

if (!$rules || $rules->rules_en === null || $rules->rules_pl === null) {
$cityData = [
"cityId" => $city->id,
"countryId" => $country->id,
"cityName" => $city->name,
"countryName" => $country->name,
];
$importer = new OpenAIService();
$data = $importer->importRulesForCity($cityData, true);
} else {
$data = [
"country" => $country->name,
"city" => $city->name,
"rules_en" => $rules->rules_en,
"rules_pl" => $rules->rules_pl,
];
}

return response()->json($data);
}

public function importRules(Request $request, OpenAIService $importer): JsonResponse
{
$force = $request->input("force", false);
$importer->importRulesForAllCities($force);

return response()->json(["message" => "Rules import started"]);
}
}
47 changes: 47 additions & 0 deletions app/Http/Controllers/RulesController.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
<?php

declare(strict_types=1);

namespace App\Http\Controllers;

use App\Models\City;
use App\Models\Country;
use App\Models\Rules;
use App\Services\OpenAIService;
use Illuminate\Http\Request;

class RulesController
{
public function getRules(Country $country, City $city): array
{
$rules = Rules::query()
->where("city_id", $city->id)
->first();

if (!$rules || $rules->rules_en === null || $rules->rules_pl === null) {
$cityData = [
"cityId" => $city->id,
"countryId" => $country->id,
"cityName" => $city->name,
"countryName" => $country->name,
];
$importer = new OpenAIService();
$data = $importer->importRulesForCity($cityData, true);
} else {
$data = [
"country" => $country->name,
"city" => $city->name,
"rules_en" => $rules->rules_en,
"rules_pl" => $rules->rules_pl,
];
}

return $data;
}

public function importRules(Request $request, OpenAIService $importer): void
{
$force = $request->input("force", false);
$importer->importRulesForAllCities($force);
}
}
66 changes: 66 additions & 0 deletions app/Importers/BaqmeDataImporter.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
<?php

declare(strict_types=1);

namespace App\Importers;

use App\Enums\ServicesEnum;
use GuzzleHttp\Exception\GuzzleException;
use Symfony\Component\DomCrawler\Crawler;

class BaqmeDataImporter extends DataImporter
{
private const COUNTRY_NAME = "Netherlands";

protected Crawler $sections;
private array $services = [ServicesEnum::Cargo];

public function extract(): static
{
try {
$response = $this->client->get("https://www.baqme.com/en/");
$html = $response->getBody()->getContents();
} catch (GuzzleException) {
$this->createImportInfoDetails("400", self::getProviderName());
$this->stopExecution = true;

return $this;
}

$crawler = new Crawler($html);
$this->sections = $crawler->filter("div.coming");

if (count($this->sections) === 0) {
$this->createImportInfoDetails("204", self::getProviderName());
$this->stopExecution = true;
}

return $this;
}

public function transform(): void
{
if ($this->stopExecution) {
return;
}
$existingCityProviders = [];

foreach ($this->sections as $section) {
$city = new Crawler($section);
$cityData = $city->filter("b")->html();
$cityArray = explode("<br>", $cityData);

if (count($cityArray) > 1 && $cityArray[1] === "Coming soon") {
continue;
}
$cityName = $cityArray[0];
$provider = $this->load($cityName, self::COUNTRY_NAME, $lat = "", $long = "", $this->services);

if ($provider) {
$existingCityProviders[] = $provider;
}
}

$this->deleteMissingProviders(self::getProviderName(), $existingCityProviders);
}
}
61 changes: 61 additions & 0 deletions app/Importers/DocomoDataImporter.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
<?php

declare(strict_types=1);

namespace App\Importers;

use App\Enums\ServicesEnum;
use GuzzleHttp\Exception\GuzzleException;
use Symfony\Component\DomCrawler\Crawler;

class DocomoDataImporter extends DataImporter
{
private const COUNTRY_NAME = "Japan";

protected Crawler $sections;
private array $services = [ServicesEnum::Bike];

public function extract(): static
{
try {
$response = $this->client->get("https://docomo-cycle.jp/?lang=en");
$html = $response->getBody()->getContents();
} catch (GuzzleException) {
$this->createImportInfoDetails("400", self::getProviderName());

$this->stopExecution = true;

return $this;
}

$crawler = new Crawler($html);
$this->sections = $crawler->filter('div[class="show-all"]');

if (count($this->sections) === 0) {
$this->createImportInfoDetails("204", self::getProviderName());
$this->stopExecution = true;
}

return $this;
}

public function transform(): void
{
if ($this->stopExecution) {
return;
}
$existingCityProviders = [];

$cities = $this->sections->filter('span[class="composite"]');

$cityNames = [];

foreach ($cities as $city) {
$cityNames[] = $city->textContent;
}

foreach ($cityNames as $cityName) {
$this->load($cityName, self::COUNTRY_NAME, $lat = "", $long = "", $this->services);
}
}
}
113 changes: 113 additions & 0 deletions app/Importers/GoSharingDataImporter.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,113 @@
<?php

declare(strict_types=1);

namespace App\Importers;

use App\Enums\ServicesEnum;
use GuzzleHttp\Exception\GuzzleException;
use Symfony\Component\DomCrawler\Crawler;

class GoSharingDataImporter extends DataImporter
{
protected Crawler $sections;

public function extract(): static
{
try {
$response = $this->client->get("https://nl.go-sharing.com/en/locations/");
$html = $response->getBody()->getContents();
} catch (GuzzleException) {
$this->createImportInfoDetails("400", self::getProviderName());

$this->stopExecution = true;

return $this;
}

$crawler = new Crawler($html);
$this->sections = $crawler->filter('section[id="show-cities"]');

if (count($this->sections) === 0) {
$this->createImportInfoDetails("204", self::getProviderName());
$this->stopExecution = true;
}

return $this;
}

public function transform(): void
{
if ($this->stopExecution) {
return;
}
$existingCityProviders = [];
$countryNames = [];

foreach ($this->sections as $section) {
$sectionCrawler = new Crawler($section);
$countries = $sectionCrawler->filter("h3");

foreach ($countries as $country) {
$countryNames[] = $country->textContent;
}

$countryCitiesRows = $sectionCrawler->filter('div[class="row location-row"]');
$countryCitiesArray = [];

foreach ($countryCitiesRows as $countryCities) {
$locationsCrawler = new Crawler($countryCities);
$locations = $locationsCrawler->filter('div[class="location"]');

$citiesArray = [];

foreach ($locations as $location) {
$cityCrawler = new Crawler($location);
$cityName = $cityCrawler->text();

$activeServicesArray = [];
$activeServices = $cityCrawler->filter('div[class="location__icons__icon active"]');

foreach ($activeServices as $activeService) {
$serviceCrawler = new Crawler($activeService);
$serviceType = $serviceCrawler->filter("img")->attr("alt");

if ($serviceType === "E-Scooter") {
$activeServicesArray[] = ServicesEnum::Escooter;
}

if ($serviceType === "E-Bike") {
$activeServicesArray[] = ServicesEnum::Bike;
}
}

$citiesArray[] = [
"cityName" => $cityName,
"services" => $activeServicesArray,
];
}
$countryCitiesArray[] = $citiesArray;
}

$countryCount = count($countryNames);

for ($i = 0; $i < $countryCount; $i++) {
$countryName = $countryNames[$i];
$cities = $countryCitiesArray[$i];

foreach ($cities as $city) {
$cityName = $city["cityName"];
$services = $city["services"];

$provider = $this->load($cityName, $countryName, $lat = "", $long = "", $services);

if ($provider !== "") {
$existingCityProviders[] = $provider;
}
}
}

$this->deleteMissingProviders(self::getProviderName(), $existingCityProviders);
}
}
}
15 changes: 15 additions & 0 deletions app/Jobs/BaqmeDataImporterJob.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
<?php

declare(strict_types=1);

namespace App\Jobs;

use App\Importers\BaqmeDataImporter;

class BaqmeDataImporterJob extends DataImporterJob
{
public function handle(BaqmeDataImporter $importer): void
{
$importer->setImportInfo($this->importInfoId)->extract()->transform();
}
}
Loading

0 comments on commit dd3f63c

Please sign in to comment.