All checks were successful
Push image to registry / build-image (push) Successful in 3m21s
403 lines
15 KiB
PHP
403 lines
15 KiB
PHP
<?php
|
|
|
|
namespace App\Browser\Jobs\Hellcase;
|
|
|
|
use App\Browser\BrowserJob;
|
|
use App\Browser\Components\Hellcase\MainNav;
|
|
use App\Browser\JobDebugScreenshot;
|
|
use App\Browser\Jobs\Hellcase\HellcaseLoginQrCode;
|
|
use App\Models\JobArtifact;
|
|
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\Notifications\JobDebugNotification;
|
|
use App\Notification\Notifications\JobErrorNotification;
|
|
use App\Notification\Providers\AllNotification;
|
|
use Facebook\WebDriver\WebDriverBy;
|
|
use Illuminate\Contracts\Queue\ShouldBeUniqueUntilProcessing;
|
|
use Illuminate\Support\Facades\Log;
|
|
use Laravel\Dusk\Browser;
|
|
|
|
class HellcaseJob extends BrowserJob implements ShouldBeUniqueUntilProcessing
|
|
{
|
|
private const STEAM_LOGIN_THRESHOLD = 5 * 60; // 5 minutes
|
|
private const APPROXIMATIVE_RUNNING_MINUTES = 2;
|
|
|
|
protected JobRun $jobRun;
|
|
|
|
public function __construct($jobId = 2)
|
|
{
|
|
parent::__construct($jobId);
|
|
}
|
|
|
|
public function run(Browser $browser): ?JobRun
|
|
{
|
|
Log::info("Running HellcaseJob");
|
|
$this->jobRun = new JobRun([
|
|
"job_id" => $this->jobId,
|
|
"success" => false,
|
|
]);
|
|
$this->jobRun->save();
|
|
|
|
$browser->visit('https://hellcase.com');
|
|
$browser->waitForText("CASES", 30, true);
|
|
$this->removePopups($browser);
|
|
sleep(5);
|
|
$this->signin($browser);
|
|
try {
|
|
$this->joinFreeGiveaways($browser);
|
|
} catch (\Exception $e) {
|
|
$this->jobRun->success = false;
|
|
$this->jobRun->save();
|
|
AllNotification::send(new JobErrorNotification($this->jobId, "Erreur lors de la participation aux concours gratuits : " . $e->getMessage()));
|
|
}
|
|
$this->getDailyFree($browser);
|
|
|
|
$this->jobRun->success = true;
|
|
$this->jobRun->save();
|
|
|
|
Log::info("HellcaseJob run ended");
|
|
|
|
return $this->jobRun;
|
|
}
|
|
|
|
/**
|
|
* @inheritDoc
|
|
*/
|
|
public function runTest(Browser $browser): ?JobRun
|
|
{
|
|
try {
|
|
$browser->visit('https://hellcase.com');
|
|
$browser->waitForText("CASES", 30, true);
|
|
$this->removePopups($browser);
|
|
sleep(2);
|
|
$this->signin($browser);
|
|
return $this->makeSimpleJobRun(
|
|
true,
|
|
"Connexion réussie",
|
|
"Datboi a réussi à se connecter sur Hellcase"
|
|
);
|
|
} catch (\Exception $e) {
|
|
return $this->makeSimpleJobRun(
|
|
false,
|
|
"Connexion échouée",
|
|
"Datboi n'a pas réussi à se connecter sur Hellcase :\n" . $e->getMessage()
|
|
);
|
|
}
|
|
}
|
|
|
|
protected function signin(Browser $browser)
|
|
{
|
|
try {
|
|
$browser->clickAtXPath('//button[.//span[text() = "Sign in"]]');
|
|
} catch (\Exception $e) {
|
|
return;
|
|
}
|
|
|
|
sleep(5);
|
|
$browser->waitForText("Sign in with Steam", 30, true);
|
|
sleep(3);
|
|
$browser->driver->findElement(WebDriverBy::xpath("//button[. = 'Sign in with Steam']"))->click();
|
|
sleep(5);
|
|
|
|
// QR CODE SCANNING
|
|
try {
|
|
$browser->waitForTextIn("div", "Or sign in with QR", 30, true);
|
|
sleep(10);
|
|
try {
|
|
$qrCode = $browser->driver->findElement(WebDriverBy::xpath('//div[./*[contains(text(), "Or sign in with QR")]]'));
|
|
} catch (\Exception $e) {
|
|
$browser->screenshot(JobDebugScreenshot::getFileName($this->jobId));
|
|
AllNotification::send(new JobDebugNotification($this->jobId, "Le QR code de la page de connexion de Steam n'a pas été trouvé"));
|
|
throw $e;
|
|
}
|
|
|
|
// 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
|
|
Log::debug("Exception because qrcode not found : " . $e);
|
|
$isBackOnHellcase = true;
|
|
} catch (\Throwable $e) {
|
|
// If the QR code is not found, we are not on the QR code page
|
|
Log::debug("Exception because qrcode not found : " . $e);
|
|
$isBackOnHellcase = true;
|
|
}
|
|
|
|
if ($isBackOnHellcase) {
|
|
// Click a button that says "sign in"
|
|
$browser->waitForText("By signing into steam.loginhell.com through Steam", 30, true);
|
|
$browser->clickAtXPath('//input[@id = "imageLogin"]');
|
|
sleep(20);
|
|
}
|
|
}
|
|
|
|
private function joinFreeGiveaways(Browser $browser)
|
|
{
|
|
try {
|
|
$buttons = $browser->driver->findElements(WebDriverBy::xpath('//a[text() = "Join for free"]'));
|
|
} catch (\Exception $e) {
|
|
$browser->screenshot(JobDebugScreenshot::getFileName($this->jobId));
|
|
AllNotification::send(new JobDebugNotification($this->jobId, "No join for free buttons found"));
|
|
return;
|
|
}
|
|
|
|
if (sizeof($buttons) == 0) {
|
|
$this->jobRun->addArtifact(new JobArtifact([
|
|
"name" => "Pas de concours joignable",
|
|
"content" => ""
|
|
]));
|
|
}
|
|
try {
|
|
// $nextSlideButton = $browser->driver->findElement(WebDriverBy::xpath('//button[@class="_button_1ygbm_7 _next_1ygbm_24"]'));
|
|
$nextSlideButton = "Button next slide is deactivated";
|
|
} catch (\Exception $e) {
|
|
$browser->screenshot(JobDebugScreenshot::getFileName($this->jobId));
|
|
AllNotification::send(new JobDebugNotification($this->jobId, "No next slide button found"));
|
|
return;
|
|
}
|
|
foreach ($buttons as $button) {
|
|
// Click the next slide button if the button is not clickable
|
|
$clickedFailsCounter = 0;
|
|
while ($clickedFailsCounter < 7 && $clickedFailsCounter >= 0) {
|
|
try {
|
|
$button->click();
|
|
} catch (\Exception $e) {
|
|
$clickedFailsCounter++;
|
|
try {
|
|
// $nextSlideButton->click();
|
|
} catch (\Exception $_) {}
|
|
sleep(3);
|
|
continue;
|
|
}
|
|
$clickedFailsCounter = -1;
|
|
}
|
|
|
|
sleep(5); // Wait a bit for loading
|
|
$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();
|
|
|
|
sleep(3);
|
|
|
|
// JobRun
|
|
// Get the elements text containing class starting with giveaway-entity-prize__
|
|
$prizeElement = $browser->driver->findElements(WebDriverBy::xpath('//div[starts-with(@class, "giveaway-entity-prize__")]'));
|
|
// Join their text
|
|
$prize = "";
|
|
foreach ($prizeElement as $element) {
|
|
$prize .= $element->getText() . "\n";
|
|
}
|
|
$this->jobRun->addArtifact(new JobArtifact([
|
|
"name" => "Rejoint le concours",
|
|
"content" => "Pour tenter de gagner le prix : \n" . $prize
|
|
]));
|
|
}
|
|
|
|
private function getDailyFree(Browser $browser)
|
|
{
|
|
$browser->visit('https://hellcase.com/dailyfree');
|
|
try {
|
|
$browser->waitForText("Get Daily free loot", 30, true);
|
|
} catch (\Exception $e) {
|
|
return; // Pobably means we do not have access to a daily free loot
|
|
}
|
|
|
|
// 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 = $browser->driver->findElement(WebDriverBy::xpath('//button[contains(@class, "daily-free-banner__button")]'));
|
|
if ($availibleInButton->getAttribute("disabled") == "true") {
|
|
$hours = $availibleInButton->getText();
|
|
// If the text is like "in 26 sec." we need to put one minute
|
|
if (str_contains(strtolower($hours), "seconds")) {
|
|
$browser->screenshot(JobDebugScreenshot::getFileName($this->jobId));
|
|
AllNotification::send(new JobDebugNotification($this->jobId, "I hate niggers"));
|
|
// $this->reschedule(1);
|
|
sleep(60);
|
|
return $this->getDailyFree($browser);
|
|
}
|
|
$hours = explode(" ", $hours);
|
|
$minutes = $hours[4];
|
|
$hours = $hours[2];
|
|
|
|
$this->jobRun->addArtifact(new JobArtifact([
|
|
"name" => "Cadeau gratuit pas encore disponible",
|
|
"content" => "Le cadeau gratuit journalier sera disponible dans {$hours} heures et {$minutes} minutes."
|
|
]));
|
|
|
|
$this->reschedule($hours * 60 + $minutes + 1);
|
|
|
|
return;
|
|
}
|
|
|
|
// Click the dailyfree button
|
|
$availibleInButton->click();
|
|
|
|
sleep(15);
|
|
|
|
$browser->waitForText("Your drop", 30, true);
|
|
|
|
$lootElement = $browser->driver->findElement(WebDriverBy::xpath('//div[contains(@class, "daily-free-win-bonus")]'));
|
|
$lootElement->takeElementScreenshot(HellcaseDailyFreeScreenshot::getImgFileAbsolutePath());
|
|
|
|
$this->reschedule((24 * 60) - ($this::APPROXIMATIVE_RUNNING_MINUTES / 2)); // Reschedule in 24hr -1min
|
|
|
|
AllNotification::send(
|
|
new HellcaseNotificationDailyFree($this->jobId, new HellcaseNotificationDailyFreeBody())
|
|
);
|
|
}
|
|
|
|
/**
|
|
* 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.png");
|
|
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")]');
|
|
}
|
|
|
|
protected function removePopups(Browser $browser)
|
|
{
|
|
// $browser->script('document.querySelector("div.app-modal")[0].remove();');
|
|
// $browser->driver->executeScript('document.querySelector("div.app-modal")[0].remove();');
|
|
}
|
|
}
|