Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

#24 - add Link and BinBin providers #117

Merged
merged 13 commits into from
Aug 22, 2023
69 changes: 69 additions & 0 deletions app/Importers/BinBinDataImporter.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
<?php

declare(strict_types=1);

namespace App\Importers;

use GuzzleHttp\Exception\GuzzleException;
use Symfony\Component\DomCrawler\Crawler;

class BinBinDataImporter extends DataImporter
{
public const language = "en";
krzysztofrewak marked this conversation as resolved.
Show resolved Hide resolved

protected Crawler $sections;

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

$this->stopExecution = true;

return $this;
}

$crawler = new Crawler($html);
$this->sections = $crawler->filter(".location-wrapper .cities-information .div-block-35");

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) {
$data = explode("|", $section->nodeValue);

if (trim($data[1]) === "Türkiye")
$countryName = "Turkey";
else $countryName = $this->translate(trim($data[1]), self::language);

if (trim($data[0]) === "Uşak")
$cityName = "Usak";
elseif (trim($data[0]) === "Murter")
continue;
else $cityName = $this->translate(trim($data[0]), "en");

$provider = $this->load($cityName, $countryName);

if ($provider !== "") $existingCityProviders[] = $provider;
krzysztofrewak marked this conversation as resolved.
Show resolved Hide resolved
}

$this->deleteMissingProviders(self::getProviderName(), $existingCityProviders);
}
}
11 changes: 10 additions & 1 deletion app/Importers/DataImporter.php
Original file line number Diff line number Diff line change
Expand Up @@ -12,16 +12,20 @@
use App\Models\ImportInfoDetail;
use App\Services\MapboxGeocodingService;
use GuzzleHttp\Client;
use Stichoza\GoogleTranslate\GoogleTranslate;

abstract class DataImporter
{
protected bool $stopExecution = false;
protected int $importInfoId;
protected GoogleTranslate $translate;

public function __construct(
protected Client $client,
protected MapboxGeocodingService $mapboxService,
) {}
) {
$this->translate = new GoogleTranslate();
}

public function setImportInfo(int $importInfoId): static
{
Expand All @@ -48,6 +52,11 @@ public static function getProviderName(): string
return $classNameParts[0];
}

public function translate(string $word, $language): string
AleksandraKozubal marked this conversation as resolved.
Show resolved Hide resolved
{
return $this->translate->setTarget($language)->translate($word);
}

protected function countryNotFound(string $cityName, string $countryName): void
{
CityWithoutAssignedCountry::query()->updateOrCreate(
Expand Down
86 changes: 86 additions & 0 deletions app/Importers/LinkDataImporter.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
<?php

declare(strict_types=1);

namespace App\Importers;

use GuzzleHttp\Exception\GuzzleException;
use Symfony\Component\DomCrawler\Crawler;

class LinkDataImporter extends DataImporter
{
protected Crawler $sections;
private string $countryName = "";

public function extract(): static
{
try {
$response = $this->client->get("https://superpedestrian.com/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(".Main-content .sqs-row.row > .col p > strong");

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) {
foreach ($section->childNodes as $node) {
$countryName = trim($node->nodeValue);

foreach ($node->parentNode->parentNode->parentNode->childNodes as $i => $cityName) {
if ($i === 0 || !trim($cityName->nodeValue)) {
continue;
}

$name = $cityName->nodeValue;

$cities = [];

if (str_contains($name, "(") && str_contains($name, ")")) {
$names = explode("(", $name)[1];
$names = explode(")", $names)[0];
$names = explode(", ", $names);

foreach ($names as $name) {
$cities[] = str_replace("*", "", $name);
}
} else {
$cities[] = $name;
}

foreach ($cities as $name) {
$provider = $this->load($name, $countryName);

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

$this->deleteMissingProviders(self::getProviderName(), $existingCityProviders);
}
}
15 changes: 15 additions & 0 deletions app/Jobs/BinBinDataImporterJob.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\BinBinDataImporter;

class BinBinDataImporterJob extends DataImporterJob
{
public function handle(BinBinDataImporter $importer): void
{
$importer->setImportInfo($this->importInfoId)->extract()->transform();
}
}
15 changes: 15 additions & 0 deletions app/Jobs/LinkDataImporterJob.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\LinkDataImporter;

class LinkDataImporterJob extends DataImporterJob
{
public function handle(LinkDataImporter $importer): void
{
$importer->setImportInfo($this->importInfoId)->extract()->transform();
}
}
4 changes: 4 additions & 0 deletions app/Services/DataImporterService.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,14 @@

use App\Jobs\BeamDataImporterJob;
use App\Jobs\BerylDataImporterJob;
use App\Jobs\BinBinDataImporterJob;
use App\Jobs\BirdDataImporterJob;
use App\Jobs\BitMobilityDataImporterJob;
use App\Jobs\BoltDataImporterJob;
use App\Jobs\DottDataImporterJob;
use App\Jobs\HulajDataImporterJob;
use App\Jobs\LimeDataImporterJob;
use App\Jobs\LinkDataImporterJob;
use App\Jobs\NeuronDataImporterJob;
use App\Jobs\QuickDataImporterJob;
use App\Jobs\RydeDataImporterJob;
Expand Down Expand Up @@ -40,12 +42,14 @@ public function run(string $whoRunsIt = "admin"): void
Bus::batch([
new BeamDataImporterJob($this->importInfoId),
new BerylDataImporterJob($this->importInfoId),
new BinBinDataImporterJob($this->importInfoId),
new BirdDataImporterJob($this->importInfoId),
new BitMobilityDataImporterJob($this->importInfoId),
new BoltDataImporterJob($this->importInfoId),
new DottDataImporterJob($this->importInfoId),
new HulajDataImporterJob($this->importInfoId),
new LimeDataImporterJob($this->importInfoId),
new LinkDataImporterJob($this->importInfoId),
new NeuronDataImporterJob($this->importInfoId),
new QuickDataImporterJob($this->importInfoId),
new RydeDataImporterJob($this->importInfoId),
Expand Down
4 changes: 4 additions & 0 deletions database/seeders/ProviderSeeder.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,14 @@

use App\Importers\BeamDataImporter;
use App\Importers\BerylDataImporter;
use App\Importers\BinBinDataImporter;
use App\Importers\BirdDataImporter;
use App\Importers\BitMobilityDataImporter;
use App\Importers\BoltDataImporter;
use App\Importers\DottDataImporter;
use App\Importers\HulajDataImporter;
use App\Importers\LimeDataImporter;
use App\Importers\LinkDataImporter;
use App\Importers\NeuronDataImporter;
use App\Importers\QuickDataImporter;
use App\Importers\RydeDataImporter;
Expand All @@ -31,12 +33,14 @@ public function run(): void
$providers = [
["name" => BeamDataImporter::getProviderName(), "color" => "#7347ff"],
["name" => BerylDataImporter::getProviderName(), "color" => "#00e3c2"],
["name" => BinBinDataImporter::getProviderName(), "color" => "#3dbcc8"],
["name" => BirdDataImporter::getProviderName(), "color" => "#26ccf0"],
["name" => BitMobilityDataImporter::getProviderName(), "color" => "#8da6e3"],
["name" => BoltDataImporter::getProviderName(), "color" => "#24f0a0"],
["name" => DottDataImporter::getProviderName(), "color" => "#f5c604"],
["name" => HulajDataImporter::getProviderName(), "color" => "#d6213f"],
["name" => LimeDataImporter::getProviderName(), "color" => "#00de00"],
["name" => LinkDataImporter::getProviderName(), "color" => "#def700"],
["name" => NeuronDataImporter::getProviderName(), "color" => "#445261"],
["name" => QuickDataImporter::getProviderName(), "color" => "#009ac7"],
["name" => SpinDataImporter::getProviderName(), "color" => "#ff5436"],
Expand Down
19 changes: 19 additions & 0 deletions readme.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,23 @@
## 🛴 escooters
### Available providers

1. BinBin
2. Bird
3. BitMobility
4. Bolt
5. Dott
6. Hulaj
7. Lime
8. Link
9. Neuron
10. Quick
11. Ryde
12. Spin
13. Tier
13. Urent
14. Voi
15. Zwings
krzysztofrewak marked this conversation as resolved.
Show resolved Hide resolved

### Local development
```
cp .env.example .env
Expand Down
3 changes: 3 additions & 0 deletions tests/Unit/ImporterTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
use GuzzleHttp\Psr7\Request;
use GuzzleHttp\Psr7\Response;
use PHPUnit\Framework\MockObject\Exception;
use Stichoza\GoogleTranslate\GoogleTranslate;
use Tests\TestCase;

class ImporterTest extends TestCase
Expand All @@ -41,6 +42,8 @@ protected function setUp(): void
$handlerStack = HandlerStack::create($mockHandler);
$mockHttpClient = new Client(["handler" => $handlerStack]);

$mockGoogleTranslate = $this->createMock(GoogleTranslate::class);

$mockMapboxService = $this->createMock(MapboxGeocodingService::class);
$mockMapboxService->method("getPlaceFromApi")->willReturn(["Perth", "Australia"]);
$mockMapboxService->method("getCoordinatesFromApi")
Expand Down