-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
11 changed files
with
390 additions
and
2 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,149 @@ | ||
<?php | ||
|
||
namespace App\Console\Commands; | ||
|
||
use App\Models\LostPet; | ||
use App\Providers\GeocoderProvider; | ||
use Carbon\Carbon; | ||
use Illuminate\Console\Command; | ||
use Illuminate\Support\Facades\Http; | ||
use Symfony\Component\Console\Command\Command as CommandAlias; | ||
|
||
class LostPetsImport extends Command | ||
{ | ||
/** | ||
* The name and signature of the console command. | ||
* | ||
* @var string | ||
*/ | ||
protected $signature = 'lost-pets:import'; | ||
|
||
/** | ||
* The console command description. | ||
* | ||
* @var string | ||
*/ | ||
protected $description = 'Imports lost pets from petco love lost website'; | ||
|
||
/** | ||
* Execute the console command. | ||
* | ||
* @return int | ||
*/ | ||
public function handle() | ||
{ | ||
$geocoder = resolve(GeocoderProvider::class); | ||
$response = $geocoder->geocode(config('services.petco.location')); | ||
$data = data_get($response, 'results.0', false); | ||
$petCount = 0; | ||
for ($i = 0; $i < 90; $i++) { | ||
$pets = collect( | ||
$this->getPage($data['lat'], | ||
$data['lon'], | ||
$i, | ||
config('services.petco.search_radius') | ||
) | ||
)->filter(function($item){ | ||
return $item['typeKey'] != 'search.headerRow.foundPetNearbyList'; | ||
}); | ||
$thisPageCount = count($pets); | ||
foreach ($pets as $pet) { | ||
$this->createOrUpdatePet($pet); | ||
$petCount++; | ||
} | ||
$this->info("Page $i: $thisPageCount pets"); | ||
sleep(10); | ||
} | ||
$this->info("Imported $petCount pets"); | ||
return CommandAlias::SUCCESS; | ||
} | ||
|
||
private function getPage($lat, $long, $page, $type = ['Cat'], $radius = 100) | ||
{ | ||
$response = Http::asJson()->withHeaders([ | ||
'User-Agent' => 'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:122.0) Gecko/20100101 Firefox/122.0', | ||
'X-Parse-Application-Id' => config('services.petco.application_id'), | ||
'X-Parse-Session-Token' => config('services.petco.session_token') | ||
])->post('https://frbackendprod.herokuapp.com/parse/functions/getSearchSet', [ | ||
'objects' => [ | ||
'geopoint' => [ | ||
'latitude' => $lat, | ||
'longitude' => $long, | ||
] | ||
], | ||
'parameters' => [ | ||
'appVersion' => '100000', | ||
'facialEngine' => 'MLFacial', | ||
'feedSetTypeKey' => 'getNearbyList', | ||
'filters' => $type, | ||
'listDistance' => "$radius", | ||
'mlFacialParameters' => [ | ||
'paging' => [ | ||
'limit' => 25, | ||
'skip' => 0, | ||
], | ||
], | ||
'mode' => 'list', | ||
'osname' => 'webVue', | ||
'pageNum' => $page, | ||
'typeKeys' => [ | ||
0 => 'foundPet', | ||
1 => 'foundOrgPet' | ||
] | ||
] | ||
]); | ||
return $response->json('result.results.objects.items'); | ||
} | ||
|
||
private function createOrUpdatePet($pet) : void | ||
{ | ||
match ($pet['typeKey']) { | ||
'foundPet' => $this->importFoundPet($pet), | ||
'foundOrgPet' => $this->importFoundOrgPet($pet), | ||
default => $this->info("Unknown type: {$pet['typeKey']}") | ||
}; | ||
} | ||
|
||
|
||
private function importFoundPet($pet){ | ||
return LostPet::query()->firstOrCreate([ | ||
'animal_id' => data_get($pet, 'id') | ||
], [ | ||
'name' => data_get($pet, 'name', 'Unknown Name'), | ||
'breed' => data_get($pet, '', 'Unknown Breed'), | ||
'color' => data_get($pet, 'targetEntity.attributes.FDRAnimalPrimaryColor', 'Unknown Color'), | ||
'sex' => data_get($pet, 'attributes.FDRPetSex', 'Unknown Sex'), | ||
'photo' => data_get($pet, 'photo.url'), | ||
'age' => data_get($pet, 'targetEntity.attributes.FDRAnimalAge'), | ||
'age_group' => data_get($pet, 'targetEntity.attributes.FDRAnimalAgeGroup', 'Unknown Age Group'), | ||
'status' => data_get($pet, 'targetEntity.status', 'Unknown Status'), | ||
'rescue_name' => data_get($pet, 'fromEntity.name', 'Unknown Name'), | ||
'rescue_address' => data_get($pet, 'fromEntity.attributes.locationAddress'), | ||
'rescue_email' => trim(data_get($pet, 'fromEntity.attributes.FDREntityEmail')), | ||
'rescue_phone' => data_get($pet, 'fromEntity.attributes.FDREntityPhone'), | ||
'intake_date' => Carbon::parse(data_get($pet, 'attributes.FDRPetPosterStartDate')), | ||
'intake_type' => data_get($pet, 'targetEntity.attributes.FDRAnimalIntakeTypeKey'), | ||
'poster_text' => data_get($pet, 'attributes.FDRPetPosterMarkings') | ||
]); | ||
} | ||
|
||
private function importFoundOrgPet($pet){ | ||
return LostPet::query()->firstOrCreate([ | ||
'animal_id' => data_get($pet, 'id') | ||
], [ | ||
'name' => data_get($pet, 'targetEntity.name', 'No name'), | ||
'breed' => data_get($pet, 'targetEntity.attributes.FDRDogPrimaryBreed', 'Unknown Breed'), | ||
'color' => data_get($pet, 'targetEntity.attributes.FDRAnimalPrimaryColor', 'Unknown Color'), | ||
'sex' => data_get($pet, 'targetEntity.attributes.FDRPetSex', 'Unknown'), | ||
'photo' => data_get($pet, 'targetEntity.photoOriginal.url'), | ||
'age' => data_get($pet, 'targetEntity.attributes.FDRAnimalAge'), | ||
'age_group' => data_get($pet, 'targetEntity.attributes.FDRAnimalAgeGroup', 'Unknown Age Group'), | ||
'status' => data_get($pet, 'targetEntity.status', 'Unknown Status'), | ||
'rescue_name' => data_get($pet, 'fromEntity.name', 'No name'), | ||
'rescue_email' => trim(data_get($pet, 'fromEntity.attributes.FDREntityEmail')), | ||
'rescue_phone' => data_get($pet, 'fromEntity.attributes.FDREntityPhone'), | ||
'intake_date' => Carbon::parse(data_get($pet, 'targetEntity.attributes.FDRAnimalIntakeDate')), | ||
'intake_type' => data_get($pet, 'targetEntity.attributes.FDRAnimalIntakeTypeKey'), | ||
]); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
<?php | ||
|
||
namespace App\Models; | ||
|
||
use Illuminate\Database\Eloquent\Factories\HasFactory; | ||
use Illuminate\Database\Eloquent\Model; | ||
|
||
class LostPet extends Model | ||
{ | ||
use HasFactory; | ||
protected $guarded = []; | ||
protected $casts = [ | ||
'intake_date' => 'datetime', | ||
]; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,42 @@ | ||
<?php | ||
|
||
namespace App\Providers; | ||
|
||
use Illuminate\Support\Facades\Http; | ||
use Illuminate\Support\ServiceProvider; | ||
|
||
class GeocoderProvider extends ServiceProvider | ||
{ | ||
|
||
public function __construct($app) | ||
{ | ||
parent::__construct($app); | ||
$this->baseUrl = 'https://api.geoapify.com/'; | ||
$this->apiKey = config('services.geoapify.key'); | ||
} | ||
|
||
/** | ||
* Register services. | ||
* | ||
* @return void | ||
*/ | ||
public function register() | ||
{ | ||
$this->app->singleton(GeocoderProvider::class, function ($app) { | ||
return new GeocoderProvider($app); | ||
}); | ||
} | ||
|
||
public function geocode($address){ | ||
if(\Cache::has(sha1($address))){ | ||
return \Cache::get(sha1($address)); | ||
} | ||
$value = Http::get('https://api.geoapify.com/v1/geocode/search', [ | ||
'text' => $address, | ||
'format' => 'json', | ||
'apiKey' => $this->apiKey, | ||
])->json(); | ||
\Cache::put(sha1($address), $value, now()->addDay()); | ||
return $value; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,84 @@ | ||
<?php | ||
|
||
return [ | ||
|
||
// @see https://docs.sentry.io/product/sentry-basics/dsn-explainer/ | ||
'dsn' => env('SENTRY_LARAVEL_DSN', env('SENTRY_DSN')), | ||
|
||
// The release version of your application | ||
// Example with dynamic git hash: trim(exec('git --git-dir ' . base_path('.git') . ' log --pretty="%h" -n1 HEAD')) | ||
'release' => env('SENTRY_RELEASE'), | ||
|
||
// When left empty or `null` the Laravel environment will be used | ||
'environment' => env('SENTRY_ENVIRONMENT'), | ||
|
||
'breadcrumbs' => [ | ||
// Capture Laravel logs in breadcrumbs | ||
'logs' => true, | ||
|
||
// Capture Laravel cache events in breadcrumbs | ||
'cache' => true, | ||
|
||
// Capture Livewire components in breadcrumbs | ||
'livewire' => true, | ||
|
||
// Capture SQL queries in breadcrumbs | ||
'sql_queries' => true, | ||
|
||
// Capture bindings on SQL queries logged in breadcrumbs | ||
'sql_bindings' => true, | ||
|
||
// Capture queue job information in breadcrumbs | ||
'queue_info' => true, | ||
|
||
// Capture command information in breadcrumbs | ||
'command_info' => true, | ||
|
||
// Capture HTTP client requests information in breadcrumbs | ||
'http_client_requests' => true, | ||
], | ||
|
||
'tracing' => [ | ||
// Trace queue jobs as their own transactions | ||
'queue_job_transactions' => env('SENTRY_TRACE_QUEUE_ENABLED', false), | ||
|
||
// Capture queue jobs as spans when executed on the sync driver | ||
'queue_jobs' => true, | ||
|
||
// Capture SQL queries as spans | ||
'sql_queries' => true, | ||
|
||
// Try to find out where the SQL query originated from and add it to the query spans | ||
'sql_origin' => true, | ||
|
||
// Capture views as spans | ||
'views' => true, | ||
|
||
// Capture Livewire components as spans | ||
'livewire' => true, | ||
|
||
// Capture HTTP client requests as spans | ||
'http_client_requests' => true, | ||
|
||
// Capture Redis operations as spans (this enables Redis events in Laravel) | ||
'redis_commands' => env('SENTRY_TRACE_REDIS_COMMANDS', false), | ||
|
||
// Try to find out where the Redis command originated from and add it to the command spans | ||
'redis_origin' => true, | ||
|
||
// Indicates if the tracing integrations supplied by Sentry should be loaded | ||
'default_integrations' => true, | ||
|
||
// Indicates that requests without a matching route should be traced | ||
'missing_routes' => false, | ||
], | ||
|
||
// @see: https://docs.sentry.io/platforms/php/guides/laravel/configuration/options/#send-default-pii | ||
'send_default_pii' => env('SENTRY_SEND_DEFAULT_PII', false), | ||
|
||
// @see: https://docs.sentry.io/platforms/php/guides/laravel/configuration/options/#traces-sample-rate | ||
'traces_sample_rate' => env('SENTRY_TRACES_SAMPLE_RATE') === null ? null : (float)env('SENTRY_TRACES_SAMPLE_RATE'), | ||
|
||
'profiles_sample_rate' => env('SENTRY_PROFILES_SAMPLE_RATE') === null ? null : (float)env('SENTRY_PROFILES_SAMPLE_RATE'), | ||
|
||
]; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
47 changes: 47 additions & 0 deletions
47
database/migrations/2023_12_28_001437_create_lost_pets_table.php
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,47 @@ | ||
<?php | ||
|
||
use Illuminate\Database\Migrations\Migration; | ||
use Illuminate\Database\Schema\Blueprint; | ||
use Illuminate\Support\Facades\Schema; | ||
|
||
return new class extends Migration | ||
{ | ||
/** | ||
* Run the migrations. | ||
* | ||
* @return void | ||
*/ | ||
public function up() | ||
{ | ||
Schema::create('lost_pets', function (Blueprint $table) { | ||
$table->id(); | ||
$table->string('animal_id'); | ||
$table->string('name')->nullable(); | ||
$table->string('breed')->nullable(); | ||
$table->string('color')->nullable(); | ||
$table->string('sex')->nullable(); | ||
$table->string('photo')->nullable(); | ||
$table->integer('age')->nullable(); | ||
$table->string('age_group')->nullable(); | ||
$table->string('status')->nullable(); | ||
$table->string('rescue_name')->nullable(); | ||
$table->string('rescue_address')->nullable(); | ||
$table->string('rescue_email')->nullable(); | ||
$table->string('rescue_phone')->nullable(); | ||
$table->dateTime('intake_date')->nullable(); | ||
$table->string('intake_type')->nullable(); | ||
$table->longText("poster_text")->nullable(); | ||
$table->timestamps(); | ||
}); | ||
} | ||
|
||
/** | ||
* Reverse the migrations. | ||
* | ||
* @return void | ||
*/ | ||
public function down() | ||
{ | ||
Schema::dropIfExists('lost_pets'); | ||
} | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
<div class="pet" data-pet="{{json_encode($pet)}}"> | ||
<a href="{{$pet->photo}}" target="_blank"> | ||
<img src="{{$pet->photo}}" width="256"> | ||
</a> | ||
<b>{{$pet->name}}</b><br> | ||
<b>Rescue: {{$pet->rescue_name}}</b><br> | ||
<b>Found: {{$pet->intake_date->diffForHumans()}}</b><br> | ||
<a href="https://lost.petcolove.org/pet/{{$pet->animal_id}}" target="_blank">view</a> | ||
</div> |
Oops, something went wrong.