Skip to content

Commit

Permalink
Add petfinder stuff
Browse files Browse the repository at this point in the history
  • Loading branch information
zack6849 committed Dec 28, 2023
1 parent c5cc945 commit 13eba88
Show file tree
Hide file tree
Showing 11 changed files with 390 additions and 2 deletions.
149 changes: 149 additions & 0 deletions app/Console/Commands/LostPetsImport.php
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'),
]);
}
}
3 changes: 1 addition & 2 deletions app/Console/Kernel.php
Original file line number Diff line number Diff line change
Expand Up @@ -24,10 +24,9 @@ class Kernel extends ConsoleKernel
*/
protected function schedule(Schedule $schedule)
{
// $schedule->command('inspire')
// ->hourly();
$schedule->command('upload:scan')->everyMinute();
$schedule->command('logbook:import')->daily();
$schedule->command('lost-pets:import')->hourly();
}

/**
Expand Down
15 changes: 15 additions & 0 deletions app/Models/LostPet.php
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',
];
}
42 changes: 42 additions & 0 deletions app/Providers/GeocoderProvider.php
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;
}
}
1 change: 1 addition & 0 deletions config/app.php
Original file line number Diff line number Diff line change
Expand Up @@ -179,6 +179,7 @@
\App\Providers\MainheadGridResolutionServiceProvider::class,
\App\Providers\ParksOnTheAirServiceProvider::class,
\App\Providers\QRZLogbookProvider::class,
\App\Providers\GeocoderProvider::class,
],

/*
Expand Down
84 changes: 84 additions & 0 deletions config/sentry.php
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'),

];
9 changes: 9 additions & 0 deletions config/services.php
Original file line number Diff line number Diff line change
Expand Up @@ -59,5 +59,14 @@

'discord' => [
'webhook_uri' => env('DISCORD_WEBHOOK_URI')
],
'petco' => [
'application_id' => 'z1dq4rokCsjt7foJ4C6uMzN4YhSFgsSzbAQlBY2y',
'session_token' => env('PETCO_SESSION_TOKEN'),
'location' => env('PECO_LOCATION'),
'search_radius' => env('PETCO_SEARCH_RADIUS', 100)
],
'geoapify' => [
'key' => env('GEOAPIFY_API_KEY')
]
];
47 changes: 47 additions & 0 deletions database/migrations/2023_12_28_001437_create_lost_pets_table.php
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');
}
};
9 changes: 9 additions & 0 deletions resources/views/components/partials/pet-card.blade.php
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>
Loading

0 comments on commit 13eba88

Please sign in to comment.