Sort of working beta
This commit is contained in:
272
app/Browser/BrowserJob.php
Normal file
272
app/Browser/BrowserJob.php
Normal file
@ -0,0 +1,272 @@
|
||||
<?php
|
||||
|
||||
namespace App\Browser;
|
||||
|
||||
use App\Browser\JobArtifacts\JobRunArtifact;
|
||||
use App\Exception\JobException;
|
||||
use App\Models\JobArtifact;
|
||||
use App\Models\JobRun;
|
||||
use Facebook\WebDriver\Chrome\ChromeOptions;
|
||||
use Facebook\WebDriver\Remote\DesiredCapabilities;
|
||||
use Facebook\WebDriver\Remote\RemoteWebDriver;
|
||||
use Facebook\WebDriver\Remote\RemoteWebElement;
|
||||
use Facebook\WebDriver\WebDriverBy;
|
||||
use Illuminate\Support\Collection;
|
||||
use Laravel\Dusk\Browser;
|
||||
use Laravel\Dusk\TestCase as BaseTestCase;
|
||||
use Closure;
|
||||
use PHPUnit\Framework\Attributes\BeforeClass;
|
||||
use Exception;
|
||||
use Laravel\Dusk\Chrome\SupportsChrome;
|
||||
use Laravel\Dusk\Concerns\ProvidesBrowser;
|
||||
use Laravel\Dusk;
|
||||
use Throwable;
|
||||
|
||||
abstract class BrowserJob
|
||||
{
|
||||
use SupportsChrome, ProvidesBrowser;
|
||||
|
||||
public int $jobId;
|
||||
|
||||
public function __construct(int $jobId)
|
||||
{
|
||||
$this->jobId = $jobId;
|
||||
}
|
||||
|
||||
/**
|
||||
* Execute the callback in a browser
|
||||
* @param Closure $callback function with a Browser as parameter
|
||||
* @return void
|
||||
*/
|
||||
private function executeInBrowser(Closure $callback): ?JobRun
|
||||
{
|
||||
|
||||
$this->prepare();
|
||||
$this->setUp();
|
||||
|
||||
$this->browse(function (Browser $browser) use ($callback, &$log) {
|
||||
try {
|
||||
$log = $callback($browser);
|
||||
// } catch (Exception $e) {
|
||||
// $browser->screenshot("failure-{$this->jobId}");
|
||||
// dump($e);
|
||||
// throw $e;
|
||||
}
|
||||
catch (Throwable $e) {
|
||||
$browser->screenshot("failure-{$this->jobId}");
|
||||
dump($e);
|
||||
throw $e;
|
||||
} finally {
|
||||
$browser->quit();
|
||||
return [];
|
||||
}
|
||||
});
|
||||
|
||||
return $log;
|
||||
}
|
||||
|
||||
/**
|
||||
* Execute the job
|
||||
* @return void
|
||||
*/
|
||||
public function execute(): ?JobRun {
|
||||
return $this->executeInBrowser(function (Browser $browser): ?JobRun {
|
||||
return $this->run($browser);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Execute the job test
|
||||
* @return void
|
||||
*/
|
||||
public function executeTest(): ?JobRun {
|
||||
return $this->executeInBrowser(function (Browser $browser): ?JobRun {
|
||||
return $this->runTest($browser);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Steps that run in the browser
|
||||
* @param \Laravel\Dusk\Browser $browser
|
||||
* @return void
|
||||
*/
|
||||
abstract public function run(Browser $browser): ?JobRun;
|
||||
|
||||
abstract public function runTest(Browser $browser): ?JobRun;
|
||||
|
||||
/**
|
||||
* Prepare for Dusk test execution.
|
||||
* @unused
|
||||
*/
|
||||
#[BeforeClass]
|
||||
public static function prepare(): void
|
||||
{
|
||||
if (config("dusk.driver.url") == null && !(isset($_ENV['LARAVEL_SAIL']) && $_ENV['LARAVEL_SAIL'] == '1')) {
|
||||
static::startChromeDriver(['--port=9515']);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Register the base URL with Dusk.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
protected function setUp(): void
|
||||
{
|
||||
Browser::$baseUrl = "https://pdftools.matthiasg.dev/";
|
||||
|
||||
Browser::$storeScreenshotsAt = base_path('app/Browser/screenshots');
|
||||
|
||||
Browser::$storeConsoleLogAt = base_path('app/Browser/console');
|
||||
|
||||
Browser::$storeSourceAt = base_path('app/Browser/source');
|
||||
|
||||
/*Browser::$userResolver = function () {
|
||||
return $this->user();
|
||||
}; */
|
||||
}
|
||||
|
||||
protected function makeSimpleJobRun(bool $success, string $name, string $content): JobRun {
|
||||
$artifact = new JobRun([
|
||||
"job_id" => $this->jobId,
|
||||
"success" => $success
|
||||
]);
|
||||
$artifact->save();
|
||||
$artifact->artifacts()->save(new JobArtifact([
|
||||
"name" => $name,
|
||||
"content" => $content,
|
||||
]));
|
||||
return $artifact;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create the RemoteWebDriver instance.
|
||||
*/
|
||||
protected function driver(): RemoteWebDriver
|
||||
{
|
||||
$options = (new ChromeOptions)->addArguments(collect([
|
||||
$this->shouldStartMaximized() ? '--start-maximized' : '--window-size=1360,1020',
|
||||
'--disable-search-engine-choice-screen',
|
||||
'--disable-gpu',
|
||||
'--no-sandbox',
|
||||
'--disable-setuid-sandbox',
|
||||
'--whitelisted-ips=""',
|
||||
'--disable-dev-shm-usage',
|
||||
'--user-data-dir=/home/seluser/profile/',
|
||||
])->all());
|
||||
|
||||
return RemoteWebDriver::create(
|
||||
config("dusk.driver.url", 'http://localhost:9515'),
|
||||
DesiredCapabilities::chrome()->setCapability(
|
||||
ChromeOptions::CAPABILITY,
|
||||
$options
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
public function terminate() {
|
||||
$this->browse(function (Browser $browser) {
|
||||
$browser->quit();
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine whether the Dusk command has disabled headless mode.
|
||||
*/
|
||||
protected function hasHeadlessDisabled(): bool
|
||||
{
|
||||
return isset($_SERVER['DUSK_HEADLESS_DISABLED']) ||
|
||||
isset($_ENV['DUSK_HEADLESS_DISABLED']);
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if the browser window should start maximized.
|
||||
*/
|
||||
protected function shouldStartMaximized(): bool
|
||||
{
|
||||
return isset($_SERVER['DUSK_START_MAXIMIZED']) ||
|
||||
isset($_ENV['DUSK_START_MAXIMIZED']);
|
||||
}
|
||||
|
||||
/**
|
||||
* Register an "after class" tear down callback.
|
||||
*
|
||||
* @param \Closure $callback
|
||||
* @return void
|
||||
*/
|
||||
public static function afterClass(Closure $callback)
|
||||
{
|
||||
static::$afterClassCallbacks[] = $callback;
|
||||
}
|
||||
|
||||
public static function name()
|
||||
{
|
||||
return "test";
|
||||
}
|
||||
|
||||
public static function dataName()
|
||||
{
|
||||
return "dataTest";
|
||||
}
|
||||
|
||||
|
||||
// BROWSER MACROS
|
||||
protected function waitForAndClickText(Browser $browser, string $text, int $timeout = 30, bool $ignoreCase = true) {
|
||||
$browser->waitForText($text, $timeout, $ignoreCase);
|
||||
$this->findElementContainingText($browser, $text, $ignoreCase)?->click();
|
||||
}
|
||||
|
||||
protected function waitForElementContainingTextAndGetIt(Browser $browser, string $text, int $timeout = 30, bool $ignoreCase = true): RemoteWebElement|null {
|
||||
try {
|
||||
$browser->waitForText($text, $timeout, $ignoreCase);
|
||||
return $this->findElementContainingText($browser, $text, $ignoreCase);
|
||||
} catch (Exception $e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
protected function findElementContainingText(Browser $browser, string $text, bool $ignoreCase = true): RemoteWebElement|null {
|
||||
try {
|
||||
if ($ignoreCase) {
|
||||
return $browser->driver->findElement(WebDriverBy::xpath("//*[{$this->xpathContainsIgnoreCase($text)}]"));
|
||||
} else {
|
||||
return $browser->driver->findElement(WebDriverBy::xpath("//*[contains(text(), \"{$text}\")]"));
|
||||
}
|
||||
} catch (Exception $e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
private function xpathContainsIgnoreCase(string $needle, string $haystack = "text()") {
|
||||
$needle = strtolower($needle);
|
||||
return "contains(translate({$haystack}, \"ABCDEFGHIJKLMNOPQRSTUVWXYZ\", \"abcdefghijklmnopqrstuvwxyz\"), \"{$needle}\")";
|
||||
}
|
||||
|
||||
protected function waitForAndClickElementContainingText(Browser $browser, string $elementXpath, string $text, int $timeout = 30, bool $ignoreCase = true) {
|
||||
$browser->waitForText($text, $timeout, $ignoreCase);
|
||||
$this->findElementContainingElementWithText($browser, $elementXpath, $text, $ignoreCase)?->click();
|
||||
}
|
||||
|
||||
protected function waitForElementContainingElementWithTextAndGetIt(Browser $browser, string $elementXpath, string $text, int $timeout = 30, bool $ignoreCase = true): RemoteWebElement|null {
|
||||
try {
|
||||
$browser->waitForText($text, $timeout, $ignoreCase);
|
||||
sleep(2);
|
||||
return $this->findElementContainingElementWithText($browser, $elementXpath, $text, $ignoreCase);
|
||||
} catch (Exception $e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
protected function findElementContainingElementWithText(Browser $browser, string $elementXpath, string $text, bool $ignoreCase = true): RemoteWebElement|null {
|
||||
try {
|
||||
if ($ignoreCase) {
|
||||
dump("{$elementXpath}[.//*[{$this->xpathContainsIgnoreCase($text)}]]");
|
||||
return $browser->driver->findElement(WebDriverBy::xpath("{$elementXpath}[.//*[{$this->xpathContainsIgnoreCase($text)}]]"));
|
||||
} else {
|
||||
return $browser->driver->findElement(WebDriverBy::xpath("{$elementXpath}[.//*[contains(text(), \"{$text}\")]]"));
|
||||
}
|
||||
} catch (Exception $e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
43
app/Browser/Components/Hellcase/MainNav.php
Normal file
43
app/Browser/Components/Hellcase/MainNav.php
Normal file
@ -0,0 +1,43 @@
|
||||
<?php
|
||||
|
||||
namespace App\Browser\Components\Hellcase;
|
||||
|
||||
use Laravel\Dusk\Browser;
|
||||
use Laravel\Dusk\Component as BaseComponent;
|
||||
|
||||
class MainNav extends BaseComponent
|
||||
{
|
||||
/**
|
||||
* Get the root selector for the component.
|
||||
*/
|
||||
public function selector(): string
|
||||
{
|
||||
return 'header.header';
|
||||
}
|
||||
|
||||
/**
|
||||
* Assert that the browser page contains the component.
|
||||
*/
|
||||
public function assert(Browser $browser): void
|
||||
{
|
||||
$browser->assertVisible($this->selector());
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the element shortcuts for the component.
|
||||
*
|
||||
* @return array<string, string>
|
||||
*/
|
||||
public function elements(): array
|
||||
{
|
||||
return [
|
||||
'@logo' => 'a.header-logo',
|
||||
'@daily-free-link' => 'a[href="/dailyfree"]',
|
||||
];
|
||||
}
|
||||
|
||||
public function goToHome(Browser $browser) {
|
||||
$browser->scrollIntoView('@logo');
|
||||
$browser->click('@logo');
|
||||
}
|
||||
}
|
29
app/Browser/Jobs/Hellcase/HellcaseDailyFreeScreenshot.php
Normal file
29
app/Browser/Jobs/Hellcase/HellcaseDailyFreeScreenshot.php
Normal file
@ -0,0 +1,29 @@
|
||||
<?php
|
||||
|
||||
namespace App\Browser\Jobs\Hellcase;
|
||||
|
||||
use Laravel\Dusk\Browser;
|
||||
use function rtrim;
|
||||
|
||||
|
||||
class HellcaseDailyFreeScreenshot {
|
||||
public const IMG_FILE_NAME = "Hellcase-dailyFreeLoot";
|
||||
|
||||
/**
|
||||
* QR code validity in seconds
|
||||
* @var int
|
||||
*/
|
||||
public const QR_CODE_VALIDITY = 20;
|
||||
|
||||
public static function getImgFileAbsolutePath(): string {
|
||||
return rtrim(Browser::$storeScreenshotsAt, '/') . "/Hellcase/" . static::IMG_FILE_NAME;
|
||||
}
|
||||
|
||||
public static function getImgFileProjectPath(): string {
|
||||
return app_path("Browser/screenshots/Hellcase/" . static::IMG_FILE_NAME);
|
||||
}
|
||||
|
||||
public static function getImgFileExternalPath(): string {
|
||||
return "screenshots/Hellcase/" . static::IMG_FILE_NAME;
|
||||
}
|
||||
}
|
315
app/Browser/Jobs/Hellcase/HellcaseJob.php
Normal file
315
app/Browser/Jobs/Hellcase/HellcaseJob.php
Normal file
@ -0,0 +1,315 @@
|
||||
<?php
|
||||
|
||||
namespace App\Browser\Jobs\Hellcase;
|
||||
|
||||
use App\Browser\BrowserJob;
|
||||
use App\Browser\Components\Hellcase\MainNav;
|
||||
use App\Models\JobArtifact;
|
||||
use App\Browser\JobArtifacts\JobRunArtifact;
|
||||
use App\Browser\Jobs\Hellcase\HellcaseLoginQrCode;
|
||||
use App\Models\JobRun;
|
||||
use App\Notification\NotificationBody\Hellcase\HellcaseNotificationDailyFreeBody;
|
||||
use App\Notification\NotificationBody\Hellcase\HellcaseNotificationLoginBody;
|
||||
use App\Notification\Notifications\Hellcase\HellcaseNotificationDailyFree;
|
||||
use App\Notification\Notifications\Hellcase\HellcaseNotificationLogin;
|
||||
use App\Notification\Providers\AllNotification;
|
||||
use Dom\XPath;
|
||||
use Facebook\WebDriver\WebDriverBy;
|
||||
use Laravel\Dusk\Browser;
|
||||
|
||||
class HellcaseJob extends BrowserJob
|
||||
{
|
||||
private const STEAM_LOGIN_THRESHOLD = 5 * 60; // 5 minutes
|
||||
|
||||
private JobRun $jobRun;
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
parent::__construct(2);
|
||||
}
|
||||
|
||||
public function run(Browser $browser): ?JobRun
|
||||
{
|
||||
$this->jobRun = new JobRun([
|
||||
"job_id" => $this->jobId,
|
||||
"success" => false,
|
||||
]);
|
||||
$this->jobRun->save();
|
||||
|
||||
$browser->visit('https://hellcase.com');
|
||||
sleep(5);
|
||||
$this->removePopups($browser);
|
||||
sleep(5);
|
||||
$this->signin($browser);
|
||||
$this->joinFreeGiveaways($browser);
|
||||
$this->getDailyFree($browser);
|
||||
|
||||
$this->jobRun->success = true;
|
||||
$this->jobRun->save();
|
||||
|
||||
return $this->jobRun;
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
public function runTest(Browser $browser): ?JobRun
|
||||
{
|
||||
try {
|
||||
$browser->visit('https://hellcase.com');
|
||||
sleep(5);
|
||||
$this->removePopups($browser);
|
||||
$this->signin($browser);
|
||||
return $this->makeSimpleJobRun(
|
||||
true,
|
||||
"Connexion réussie",
|
||||
"Datboi a réussi à se connecter sur Hellcase"
|
||||
);
|
||||
} catch (\Exception $e) {
|
||||
return $this->makeSimpleJobRun(
|
||||
true,
|
||||
"Connexion échouée",
|
||||
"Datboi n'a pas réussi à se connecter sur Hellcase :\n" . $e->getMessage()
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
private function signin(Browser $browser)
|
||||
{
|
||||
try {
|
||||
$browser->clickAtXPath('//button[.//span[text() = "Sign in"]]');
|
||||
} catch (\Exception $e) {
|
||||
return;
|
||||
}
|
||||
|
||||
sleep(3);
|
||||
$browser->clickAtXPath('//button[.//span[contains(text(), "Sign in through Steam")]]');
|
||||
sleep(5);
|
||||
|
||||
// QR CODE SCANNING
|
||||
try {
|
||||
$browser->waitForTextIn("div", "Or sign in with QR", 30, true);
|
||||
$qrCode = $browser->driver->findElement(WebDriverBy::xpath('//div[./*[contains(text(), "Or sign in with QR")]]'));
|
||||
|
||||
// Wait to be redirected to the Steam login page, while waiting take a new screenshot every 30 seconds
|
||||
$isBackOnHellcase = false;
|
||||
$secondsCounter = 0;
|
||||
while (!$isBackOnHellcase && $secondsCounter < self::STEAM_LOGIN_THRESHOLD) {
|
||||
// Take a screenshot of the QR code and send it
|
||||
$qrCode->takeElementScreenshot(HellcaseLoginQrCode::getImgFileAbsolutePath());
|
||||
AllNotification::send(
|
||||
new HellcaseNotificationLogin(
|
||||
$this->jobId,
|
||||
new HellcaseNotificationLoginBody()
|
||||
)
|
||||
);
|
||||
|
||||
try {
|
||||
$browser->waitForLocation("https://hellcase.com", HellcaseLoginQrCode::QR_CODE_VALIDITY); // The QR code is only valid for 20 seconds
|
||||
} catch (\Exception $e) {
|
||||
$secondsCounter += HellcaseLoginQrCode::QR_CODE_VALIDITY; // we've waited for QR_CODE_VALIDITY seconds
|
||||
continue;
|
||||
}
|
||||
$isBackOnHellcase = true;
|
||||
}
|
||||
} catch (\Exception $e) {
|
||||
// If the QR code is not found, we are not on the QR code page
|
||||
$isBackOnHellcase = true;
|
||||
} catch (\Throwable $e) {
|
||||
// If the QR code is not found, we are not on the QR code page
|
||||
$isBackOnHellcase = true;
|
||||
}
|
||||
|
||||
if ($isBackOnHellcase) {
|
||||
// Click a button tjat says "sign in"
|
||||
$browser->waitForText("By signing into steam.loginhell.com through Steam", 30, true);
|
||||
$browser->clickAtXPath('//input[@id = "imageLogin"]');
|
||||
sleep(30);
|
||||
}
|
||||
}
|
||||
|
||||
private function joinFreeGiveaways(Browser $browser)
|
||||
{
|
||||
try {
|
||||
$buttons = $browser->driver->findElements(WebDriverBy::xpath('//a[text() = "Join for free"]'));
|
||||
} catch (\Exception $e) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (sizeof($buttons) == 0) {
|
||||
$this->jobRun->addArtifact(new JobArtifact([
|
||||
"name" => "Pas de concours joignable",
|
||||
"content" => ""
|
||||
]));
|
||||
}
|
||||
foreach ($buttons as $button) {
|
||||
$button->click();
|
||||
sleep(5);
|
||||
$this->joinGiveaway($browser);
|
||||
$browser->within(new MainNav, function (Browser $browser) {
|
||||
$browser->goToHome();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
private function joinGiveaway(Browser $browser)
|
||||
{
|
||||
$joinButton = $browser->driver->findElement(WebDriverBy::xpath('//button[span[contains(text(), "Join for free")]]'));
|
||||
$joinButton->click();
|
||||
}
|
||||
|
||||
private function getDailyFree(Browser $browser)
|
||||
{
|
||||
$browser->visit('https://hellcase.com/dailyfree');
|
||||
$browser->waitForText("Get Daily free loot", 30, true);
|
||||
|
||||
// Do we fill the conditions ?
|
||||
if (sizeof(value: $browser->driver->findElements(WebDriverBy::xpath('//p[contains(text(), "Fulfill the conditions below")]'))) > 0) {
|
||||
$this->fillDailyFreeConditions($browser);
|
||||
}
|
||||
|
||||
// If we see "availible in 20 HR 49 MIN", parse the hours and minute and reschedule
|
||||
$availibleInButton = $this->waitForElementContainingTextAndGetIt($browser, "available", 30);
|
||||
if ($availibleInButton != null) {
|
||||
$hours = $availibleInButton->getText();
|
||||
$hours = explode(" ", $hours);
|
||||
$minutes = $hours[2];
|
||||
$hours = $hours[0];
|
||||
// $this->reschedule($hours);
|
||||
|
||||
$this->jobRun->addArtifact(new JobArtifact([
|
||||
"name" => "Cadeau gratuit pas encore disponible",
|
||||
"content" => "Le cadeau gratuit journalier sera disponible dans $hours heures et $minutes minutes.\nDatboi se fera un plaisir d'aller le chercher pour vous."
|
||||
]));
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
$this->waitForAndClickText($browser, "Get Free Bonus", 30, true);
|
||||
|
||||
$lootElement = $browser->driver->findElement(WebDriverBy::xpath('//div[contains(@class, "daily-free-win-bonus")]'));
|
||||
$lootElement->takeElementScreenshot(HellcaseDailyFreeScreenshot::getImgFileAbsolutePath());
|
||||
|
||||
AllNotification::send(
|
||||
new HellcaseNotificationDailyFree($this->jobId, new HellcaseNotificationDailyFreeBody())
|
||||
);
|
||||
|
||||
sleep(5000);
|
||||
}
|
||||
|
||||
/**
|
||||
* Must be on the dailyfree page
|
||||
* @param \Laravel\Dusk\Browser $browser
|
||||
* @throws \Exception
|
||||
* @return void
|
||||
*/
|
||||
private function fillDailyFreeConditions(Browser $browser) {
|
||||
// 1. See what conditions we need to fullfill
|
||||
$conditions = [];
|
||||
$conditionsDivs = $browser->driver->findElements(WebDriverBy::xpath('//*[@class = "daily-free-requirement__heading-left"]'));
|
||||
for($i = 0; $i < sizeof($conditionsDivs); $i++) {
|
||||
$conditionDiv = $conditionsDivs[$i];
|
||||
// See if the element has the completed class
|
||||
$conditions[$i] = [
|
||||
"isFilled" => str_contains($conditionDiv->getAttribute("class"), "completed"),
|
||||
"text" => $conditionDiv->getText()
|
||||
];
|
||||
}
|
||||
|
||||
if (sizeof($conditions) == 0) {
|
||||
throw new \Exception("No dailyfree conditions found");
|
||||
}
|
||||
|
||||
if (!$conditions[0]["isFilled"]) {
|
||||
$this->changeSteamProfilePicture($browser);
|
||||
}
|
||||
if (!$conditions[1]["isFilled"]) {
|
||||
$this->changeSteamProfileToPublic($browser);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* Must be on the dailyfree page
|
||||
* @param \Laravel\Dusk\Browser $browser
|
||||
* @return void
|
||||
*/
|
||||
private function changeSteamProfilePicture(Browser $browser) {
|
||||
// Get all of the availible image link
|
||||
$images = $browser->driver->findElements(WebDriverBy::xpath('//a[@class = "daily-free-user-requirement-avatar-item"]'));
|
||||
// Download the image from the second link in a special folder
|
||||
$imageLink = $images[1]->getAttribute("href");
|
||||
// Download the image in app/Browser/downloads/
|
||||
$imagePath = base_path("app/Browser/downloads/Hellcase/pp.jpg");
|
||||
file_put_contents($imagePath, file_get_contents($imageLink));
|
||||
|
||||
$this->goToSteamProfileSettings($browser);
|
||||
|
||||
// Wait for and click "Avatar"
|
||||
$this->waitForAndClickText($browser, "Avatar");
|
||||
|
||||
// Wait for and click "Upload your avatar"
|
||||
$browser->waitForText("Upload your avatar", 30, true);
|
||||
// $browser->clickAtXPath('//*[contains(text(), "Upload your avatar")]');
|
||||
|
||||
// Upload the downloaded image
|
||||
$browser->attach('input[type="file"]', $imagePath);
|
||||
|
||||
// Wait for and click save
|
||||
$this->waitForAndClickText($browser, "Save");
|
||||
|
||||
// Go back to dailyfree
|
||||
$browser->visit('https://hellcase.com/dailyfree');
|
||||
|
||||
sleep(10);
|
||||
|
||||
try {
|
||||
// wait and click "Check the condition"
|
||||
$this->waitForAndClickText($browser, "Check the condition");
|
||||
$browser->waitForText("Your Steam profile avatar does not match any of the ones specified in the", 30, true);
|
||||
} catch (\Exception $e) {
|
||||
// If the text is not found, the condition is filled
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
private function changeSteamProfileToPublic(Browser $browser) {
|
||||
$this->goToSteamProfileSettings($browser);
|
||||
|
||||
// Wait for and click "Privacy Settings"
|
||||
$this->waitForAndClickText($browser, "Privacy Settings");
|
||||
|
||||
$dropdownButton = $browser->driver->findElement(WebDriverBy::xpath('//div[text() = "My profile"]/div'));
|
||||
$dropdownButton->click();
|
||||
|
||||
sleep(2);
|
||||
|
||||
// Div that contains the visible class ath the body root an element with public text
|
||||
$publicOption = $browser->driver->findElement(WebDriverBy::xpath('/body/div[contains(@class, "visible")]/div[contains(text(), "Public")]'));
|
||||
$publicOption->click();
|
||||
|
||||
// Go back to dailyfree
|
||||
$browser->visit('https://hellcase.com/dailyfree');
|
||||
}
|
||||
|
||||
/**
|
||||
* From the dailyfree page
|
||||
* @param \Laravel\Dusk\Browser $browser
|
||||
* @return void
|
||||
*/
|
||||
private function goToSteamProfileSettings(Browser $browser) {
|
||||
// Get the link that has text "Steam profile"
|
||||
$steamProfileLink = $browser->driver->findElement(WebDriverBy::xpath('//a[contains(text(), "Steam profile")]'));
|
||||
$browser->visit($steamProfileLink->getAttribute("href"));
|
||||
$browser->waitForText("Level");
|
||||
|
||||
// Click "Edit Profile
|
||||
$browser->clickAtXPath('//*[contains(text(), "Edit Profile")]');
|
||||
}
|
||||
|
||||
private function removePopups(Browser $browser)
|
||||
{
|
||||
// $browser->script('document.querySelector("div.app-modal")[0].remove();');
|
||||
// $browser->driver->executeScript('document.querySelector("div.app-modal")[0].remove();');
|
||||
}
|
||||
}
|
29
app/Browser/Jobs/Hellcase/HellcaseLoginQrCode.php
Normal file
29
app/Browser/Jobs/Hellcase/HellcaseLoginQrCode.php
Normal file
@ -0,0 +1,29 @@
|
||||
<?php
|
||||
|
||||
namespace App\Browser\Jobs\Hellcase;
|
||||
|
||||
use Laravel\Dusk\Browser;
|
||||
use function rtrim;
|
||||
|
||||
|
||||
class HellcaseLoginQrCode {
|
||||
public const IMG_FILE_NAME = "SteamQRCode.png";
|
||||
|
||||
/**
|
||||
* QR code validity in seconds
|
||||
* @var int
|
||||
*/
|
||||
public const QR_CODE_VALIDITY = 20;
|
||||
|
||||
public static function getImgFileAbsolutePath(): string {
|
||||
return rtrim(Browser::$storeScreenshotsAt, '/') . "/Hellcase/" . static::IMG_FILE_NAME;
|
||||
}
|
||||
|
||||
public static function getImgFileProjectPath(): string {
|
||||
return app_path("Browser/screenshots/Hellcase/" . static::IMG_FILE_NAME);
|
||||
}
|
||||
|
||||
public static function getImgFileExternalPath(): string {
|
||||
return "screenshots/Hellcase/" . static::IMG_FILE_NAME;
|
||||
}
|
||||
}
|
41
app/Browser/Jobs/Parameters/ParametersJob.php
Normal file
41
app/Browser/Jobs/Parameters/ParametersJob.php
Normal file
@ -0,0 +1,41 @@
|
||||
<?php
|
||||
|
||||
namespace App\Browser\Jobs\Parameters;
|
||||
|
||||
use App\Browser\BrowserJob;
|
||||
use App\Models\JobArtifact;
|
||||
use App\Models\JobRun;
|
||||
use App\Notification\Notifications\SimpleNotification;
|
||||
use App\Notification\Providers\AllNotification;
|
||||
use Laravel\Dusk\Browser;
|
||||
|
||||
class ParametersJob extends BrowserJob
|
||||
{
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
parent::__construct(1);
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
public function run(Browser $browser): ?JobRun
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
public function runTest(Browser $browser): ?JobRun
|
||||
{
|
||||
try {
|
||||
AllNotification::send(new SimpleNotification($this->jobId, "Test", "Test des notifications"));
|
||||
AllNotification::send(new SimpleNotification($this->jobId, "Test", "Test des notifications d'erreur", true));
|
||||
return $this->makeSimpleJobRun(true, "Envoi de notification réussi", "Datboi a réussi à envoyer des notifications");
|
||||
} catch (\Throwable $e) {
|
||||
return $this->makeSimpleJobRun(false, "Envoi de notification échoué", "Datboi n'a pas réussi à envoyer des notifications :\n" . $e->getMessage());
|
||||
}
|
||||
}
|
||||
}
|
2
app/Browser/downloads/.gitignore
vendored
Normal file
2
app/Browser/downloads/.gitignore
vendored
Normal file
@ -0,0 +1,2 @@
|
||||
*
|
||||
!.gitignore
|
Reference in New Issue
Block a user