File "AssociateProductMedia.php"
Full Path: /home/clickysoft/public_html/jmapi5.clickysoft.net/app/Jobs/AssociateProductMedia.php
File size: 6.85 KB
MIME-type: text/x-php
Charset: utf-8
<?php
namespace App\Jobs;
use App\Http\Controllers\Traits\MediaUploadingTrait;
use App\Models\Product;
use App\Models\ProductPrice;
use App\Models\TempProductUrl;
use GuzzleHttp\Client;
use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldBeUnique;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Foundation\Bus\Dispatchable;
use Illuminate\Http\UploadedFile;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Queue\Middleware\ThrottlesExceptions;
use Illuminate\Queue\SerializesModels;
class AssociateProductMedia implements ShouldQueue
{
use Dispatchable, InteractsWithQueue, Queueable, SerializesModels, MediaUploadingTrait;
public int $timeout = 120;
public int $ipIndex = 0;
//These are being used in order to avoid throttling by google
public const USA_IPS = [
'23.129.64.202', // New York
'45.33.109.244', // Dallas
'45.79.202.233', // Fremont
'23.239.23.148', // Atlanta
'192.155.85.170', // Los Angeles
'23.129.64.197', // New York
'96.8.120.196', // Chicago
'96.8.120.227', // Chicago
'96.8.120.201', // Chicago
'45.79.202.94', // Fremont
'192.99.68.31', // Canada, but commonly used as US proxy
'192.99.68.167', // Canada, but commonly used as US proxy
'192.99.68.145', // Canada, but commonly used as US proxy
'192.99.68.162', // Canada, but commonly used as US proxy
'192.99.68.164', // Canada, but commonly used as US proxy
'192.99.68.166', // Canada, but commonly used as US proxy
'192.99.68.170', // Canada, but commonly used as US proxy
'192.99.68.175', // Canada, but commonly used as US proxy
'192.99.68.180', // Canada, but commonly used as US proxy
'192.99.68.182', // Canada, but commonly used as US proxy
'192.99.68.186', // Canada, but commonly used as US proxy
'192.99.68.188', // Canada, but commonly used as US proxy
'192.99.68.191', // Canada, but commonly used as US proxy
'192.99.68.194', // Canada, but commonly used as US proxy
'192.99.68.197', // Canada, but commonly used as US proxy
'192.99.68.199', // Canada, but commonly used as US proxy
'192.99.68.201', // Canada, but commonly used as US proxy
'192.99.68.203', // Canada, but commonly used as US proxy
'192.99.68.206', // Canada, but commonly used as US proxy
];
/*public function middleware(): array
{
return [new ThrottlesExceptions(10, 5)];
}*/
public function __construct()
{
//
}
public function handle()
{
\Log::channel('import_logs')->info('Association job started');
$records = TempProductUrl::all();
foreach ($records as $record) {
\Log::channel('import_logs')->info('Now handling :'. $record->id);
$response = $this->handleRecordRecursively($record);
// $response = $this->downloadImageFromGoogleDrive($record);
if ($response) {
// $record->delete();
\Log::channel('import_logs')->info("Model id : {$record->model_id} => {$record->type} associated successfully.");
} else {
\Log::channel('import_logs')->info("Model id : {$record->model_id} => {$record->type} associated failed.");
}
//Delay execution for quarter second in order to avoid google rate limiting
usleep(25000000);
}
\Log::channel('import_logs')->info('Association job finished');
}
public function handleRecordRecursively($record)
{
$response = $this->downloadImageFromGoogleDrive($record);
if ($response) return true; //Successfully associated record
$this->updateIpIndex();
if ($this->ipIndex == count(self::USA_IPS) - 1) //Failed after trying all IPs
return false;
else
$this->handleRecordRecursively($record); //Try with another IP
}
public function downloadImageFromGoogleDrive($rec): bool
{
preg_match('/\/d\/(.*?)\//', $rec->url, $matches);
$fileId = $matches[1] ?? ''; //Check here
// Download the file using GuzzleHttp
$headers = [
'X-Forwarded-For' =>self::USA_IPS[$this->ipIndex], // Replace with the IP address you want to send
'User-Agent' => 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537.3',
];
$client = new Client([
'base_uri' => 'https://drive.google.com',
'headers' => $headers,
]);
try {
$response = $client->get("/uc?id={$fileId}&export=download");
$contentDisposition = $response->getHeaderLine('Content-Disposition');
preg_match('/filename="(.+)"/', $contentDisposition, $matches);
$filename = $matches[1] ?? '';
if ($filename){
// Save the file to Laravel storage directory
$fileContents = $response->getBody()->getContents();
\Storage::disk('public')->put($filename, $fileContents);
return $this->associateFile($rec, $filename);
} else {
return false;
}
} catch (\Exception $e) {
\Log::channel('import_logs')->info($rec->type.' association failed for model id => '. $rec->model_id);
\Log::channel('import_logs')->info($e->getMessage());
\Log::channel('import_logs')->info("IP : ". self::USA_IPS[$this->ipIndex]);
return false;
}
}
public function associateFile($rec, $filename): bool
{
if ($rec->type == 'image') {
$product = Product::find($rec->model_id);
if (!file_exists(public_path('storage/'. $filename))) return false;
//Delete old image of product
if (!empty($product->featured_image)) {
$product->clearMediaCollection('product_featured_image');
}
$product->addMedia(public_path('storage/'.$filename))
->toMediaCollection('product_featured_image', 'product')
->save();
} else {
$product_price = ProductPrice::find($rec->model_id);
if (!file_exists(public_path('storage/'. $filename))) return false;
\Log::channel('import_logs')->info(public_path('storage/'. $filename));
$file = new UploadedFile(public_path('storage/'.$filename), $filename);
$product_price->product_sketch = $this->storePDF($file, $product_price->product->featured_image->id, 'product');
\Log::channel('import_logs')->info('Sketch : '.$product_price->product_sketch);
$product_price->save();
}
return true;
}
public function updateIpIndex(): void
{
$this->ipIndex == count(self::USA_IPS) - 1 ? $this->ipIndex = 0 : $this->ipIndex++;
}
}