Remove @ from description + try fix BMP characters issue
All checks were successful
Push image to registry / build-image (push) Successful in 4m46s
All checks were successful
Push image to registry / build-image (push) Successful in 4m46s
This commit is contained in:
@ -286,4 +286,18 @@ abstract class BrowserJob implements ShouldQueue
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function typeText(Browser $browser, string $text, string $querySelector): void
|
||||||
|
{
|
||||||
|
$browser->script("
|
||||||
|
let element = document.querySelector('{$querySelector}');
|
||||||
|
if (element) {
|
||||||
|
element.focus();
|
||||||
|
element.value = '{$text}';
|
||||||
|
element.dispatchEvent(new Event('input', { bubbles: true }));
|
||||||
|
} else {
|
||||||
|
console.error('Element not found: {$querySelector}');
|
||||||
|
}
|
||||||
|
");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,17 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Browser\Jobs\InstagramRepost\DescriptionPipeline;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Interface for Instagram description pipeline steps.
|
||||||
|
*/
|
||||||
|
interface IInstagramDescriptionPipelineStep
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Process the description.
|
||||||
|
* @param string $description
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public function process(string $description): string;
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,42 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
// Pipeline for processing Instagram post descriptions
|
||||||
|
|
||||||
|
namespace App\Browser\Jobs\InstagramRepost\DescriptionPipeline;
|
||||||
|
|
||||||
|
class InstagramDescriptionPipeline
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @var array of IInstagramDescriptionPipelineStep
|
||||||
|
*/
|
||||||
|
private array $steps;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* InstagramDescriptionPipeline constructor.
|
||||||
|
*
|
||||||
|
* @param array $steps
|
||||||
|
*/
|
||||||
|
public function __construct(array $steps)
|
||||||
|
{
|
||||||
|
$this->steps = $steps;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Process the description through the pipeline.
|
||||||
|
*
|
||||||
|
* @param string $description
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public function process(string $description): string
|
||||||
|
{
|
||||||
|
foreach ($this->steps as $step) {
|
||||||
|
if (!$step instanceof IInstagramDescriptionPipelineStep) {
|
||||||
|
throw new \InvalidArgumentException('All steps must implement IInstagramDescriptionPipelineStep interface.');
|
||||||
|
}
|
||||||
|
|
||||||
|
$description = $step->process($description);
|
||||||
|
}
|
||||||
|
|
||||||
|
return $description;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,37 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Browser\Jobs\InstagramRepost\DescriptionPipeline;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Step to remove account references from the description.
|
||||||
|
*/
|
||||||
|
|
||||||
|
class RemoveAccountsReferenceStep implements IInstagramDescriptionPipelineStep
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Process the description to remove account references.
|
||||||
|
*
|
||||||
|
* @param string $description
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public function process(string $description): string
|
||||||
|
{
|
||||||
|
// Regular expression to match Instagram account references
|
||||||
|
$pattern = '/@([a-zA-Z0-9._]+)/';
|
||||||
|
|
||||||
|
// Split by lines
|
||||||
|
$lines = explode("\n", $description);
|
||||||
|
|
||||||
|
// Remove lines that contain account references
|
||||||
|
$lines = array_filter($lines, function ($line) use ($pattern) {
|
||||||
|
// Check if the line does not match the account reference pattern
|
||||||
|
return !preg_match($pattern, $line);
|
||||||
|
});
|
||||||
|
|
||||||
|
// Join the remaining lines back into a single string
|
||||||
|
$cleanedDescription = implode("\n", $lines);
|
||||||
|
|
||||||
|
// Trim whitespace from the beginning and end of the description
|
||||||
|
return trim($cleanedDescription);
|
||||||
|
}
|
||||||
|
}
|
@ -4,6 +4,7 @@ namespace App\Browser\Jobs\InstagramRepost;
|
|||||||
|
|
||||||
use App\Browser\BrowserJob;
|
use App\Browser\BrowserJob;
|
||||||
use App\Browser\JobDebugScreenshot;
|
use App\Browser\JobDebugScreenshot;
|
||||||
|
use App\Browser\Jobs\InstagramRepost\DescriptionPipeline\InstagramDescriptionPipeline;
|
||||||
use App\Models\InstagramRepost;
|
use App\Models\InstagramRepost;
|
||||||
use App\Models\InstagramAccount;
|
use App\Models\InstagramAccount;
|
||||||
use App\Models\Job;
|
use App\Models\Job;
|
||||||
@ -50,12 +51,25 @@ class InstagramRepostJob extends BrowserJob implements ShouldBeUniqueUntilProces
|
|||||||
|
|
||||||
protected string $downloadFolder = "app/Browser/downloads/InstagramRepost/";
|
protected string $downloadFolder = "app/Browser/downloads/InstagramRepost/";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Pipeline for processing Instagram post descriptions.
|
||||||
|
* This pipeline can be used to modify the description before reposting.
|
||||||
|
* For example, it can remove account references or add hashtags.
|
||||||
|
*
|
||||||
|
* @var InstagramDescriptionPipeline
|
||||||
|
*/
|
||||||
|
protected InstagramDescriptionPipeline $descriptionPipeline;
|
||||||
|
|
||||||
public function __construct($jobId = 4)
|
public function __construct($jobId = 4)
|
||||||
{
|
{
|
||||||
parent::__construct($jobId);
|
parent::__construct($jobId);
|
||||||
|
|
||||||
$this->downloadFolder = base_path($this->downloadFolder);
|
$this->downloadFolder = base_path($this->downloadFolder);
|
||||||
$this->videoDownloader = new YTDLPDownloader();
|
$this->videoDownloader = new YTDLPDownloader();
|
||||||
|
$this->descriptionPipeline = new InstagramDescriptionPipeline([
|
||||||
|
// Add steps to the pipeline here
|
||||||
|
new DescriptionPipeline\RemoveAccountsReferenceStep(),
|
||||||
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function run(Browser $browser): ?JobRun
|
public function run(Browser $browser): ?JobRun
|
||||||
@ -317,8 +331,20 @@ class InstagramRepostJob extends BrowserJob implements ShouldBeUniqueUntilProces
|
|||||||
$this->clickNext($browser); // Skip cover photo and trim
|
$this->clickNext($browser); // Skip cover photo and trim
|
||||||
|
|
||||||
// Add a caption
|
// Add a caption
|
||||||
$captionInput = $browser->driver->findElement(WebDriverBy::xpath('//div[@contenteditable]'));
|
$captionText = $this->descriptionPipeline->process($videoInfo->getDescription());
|
||||||
$captionInput->sendKeys($videoInfo->getDescription());
|
$browser->script("
|
||||||
|
var el = document.querySelector('div[contenteditable]'), text = '{$captionText}';
|
||||||
|
const dataTransfer = new DataTransfer();
|
||||||
|
dataTransfer.setData('text', text);
|
||||||
|
const event = new ClipboardEvent('paste', {
|
||||||
|
clipboardData: dataTransfer,
|
||||||
|
bubbles: true
|
||||||
|
});
|
||||||
|
document.querySelector('div[contenteditable]').dispatchEvent(event)
|
||||||
|
");
|
||||||
|
//$this->typeText($browser, $captionText, 'div[contenteditable]');
|
||||||
|
//$captionInput = $browser->driver->findElement(WebDriverBy::xpath('//div[@contenteditable]'));
|
||||||
|
//$captionInput->sendKeys($this->descriptionPipeline->process($videoInfo->getDescription()));
|
||||||
|
|
||||||
sleep(2); // Wait for the caption to be added
|
sleep(2); // Wait for the caption to be added
|
||||||
|
|
||||||
@ -341,11 +367,11 @@ class InstagramRepostJob extends BrowserJob implements ShouldBeUniqueUntilProces
|
|||||||
try {
|
try {
|
||||||
$browser->waitForText("Your post was shared", 60, true);
|
$browser->waitForText("Your post was shared", 60, true);
|
||||||
$closeButton = $browser->driver->findElement(WebDriverBy::xpath('//div[./div/*[local-name() = "svg"][@aria-label="Close"]]'));
|
$closeButton = $browser->driver->findElement(WebDriverBy::xpath('//div[./div/*[local-name() = "svg"][@aria-label="Close"]]'));
|
||||||
|
$closeButton->click();
|
||||||
} catch (\Exception $e) {
|
} catch (\Exception $e) {
|
||||||
Log::error("Failed to repost reel: {$reel->reel_id} - " . $e->getMessage());
|
Log::error("Failed to repost reel: {$reel->reel_id} - " . $e->getMessage());
|
||||||
$browser->screenshot(JobDebugScreenshot::getFileName($this->jobId));
|
$browser->screenshot(JobDebugScreenshot::getFileName($this->jobId));
|
||||||
AllNotification::send(new JobDebugNotification($this->jobId, "Failed to repost reel: {$reel->reel_id} - " . $e->getMessage()));
|
AllNotification::send(new JobDebugNotification($this->jobId, "Failed to repost reel: {$reel->reel_id} - " . $e->getMessage()));
|
||||||
$closeButton->click();
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
return true; // Reel reposted successfully, no error message found
|
return true; // Reel reposted successfully, no error message found
|
||||||
|
Reference in New Issue
Block a user