45 Commits

Author SHA1 Message Date
Ninluc d33d0ba6a1 Change visit by js window.open 2025-03-01 14:21:59 +01:00
Ninluc fcb3f8d7d8 try to finish the job 2025-03-01 13:32:07 +01:00
Ninluc 1bebf03a70 Merge branch 'main' into jobs/epic-games 2025-03-01 12:56:51 +01:00
Ninluc 025711e09d Updated dockerignore
Push image to registry / build-image (push) Successful in 5m1s
2025-03-01 12:49:02 +01:00
Ninluc 5a30cdeae5 Made a script to patch latest selenium/standalone-chromedriver 2025-03-01 12:33:03 +01:00
Ninluc 7079206658 Added migration, schdule and signing in 2025-03-01 10:03:40 +01:00
Ninluc db9d65f445 Fix job ordering 2025-03-01 10:02:47 +01:00
Ninluc a1219b92ce Should fix
Push image to registry / build-image (push) Successful in 7m31s
2025-02-28 17:05:47 +01:00
Ninluc ce13d1b0dd Job qui enlève les vieilles jobRun
Push image to registry / build-image (push) Successful in 6m18s
2025-02-27 18:54:40 +01:00
Ninluc a80a32eee8 Added links to browser downloads and others
Push image to registry / build-image (push) Successful in 6m20s
2025-02-27 17:57:54 +01:00
Ninluc cd3491c5a8 Install reverb for broadcasting
Push image to registry / build-image (push) Successful in 3m56s
2025-02-26 18:52:12 +01:00
Ninluc 9e55c98d47 Added TODO list 2025-02-26 18:28:42 +01:00
Ninluc 7abfea14e6 Reschedule 24hr after getting dailyFree
Push image to registry / build-image (push) Successful in 3m53s
2025-02-26 18:25:20 +01:00
Ninluc b177b27390 FIx ot reschedule in one hour but in one minute
Push image to registry / build-image (push) Successful in 6m42s
2025-02-26 07:19:58 +01:00
Ninluc 8d814c7658 Try to fix reschedules in seconds
Push image to registry / build-image (push) Has been cancelled
2025-02-26 07:18:32 +01:00
Ninluc 56ec14f1da Move file 2025-02-24 18:58:22 +01:00
Ninluc c7ad5810a7 fix jobModel again
Push image to registry / build-image (push) Successful in 4m31s
2025-02-22 08:53:54 +01:00
Ninluc 5b939f7d34 Fix jobModel interfering
Push image to registry / build-image (push) Failing after 53s
2025-02-22 08:46:47 +01:00
Ninluc 540c41357e cron with daemon
Push image to registry / build-image (push) Failing after 1m0s
2025-02-22 08:35:03 +01:00
Ninluc 9f7603ea18 Only start the job if active 2025-02-22 08:34:47 +01:00
Ninluc e44ea5a3b2 Fix queue wotker
Push image to registry / build-image (push) Successful in 3m46s
2025-02-21 18:34:19 +01:00
Ninluc a4d52e3f88 Logging and only one job in the queue 2025-02-21 18:34:03 +01:00
Ninluc 750bcf13b4 Fix supervisor
Push image to registry / build-image (push) Successful in 3m46s
2025-02-20 20:22:04 +01:00
Ninluc 7a03225a21 Fix supervisor
Push image to registry / build-image (push) Successful in 6m46s
2025-02-20 20:00:25 +01:00
Ninluc 51eafce03a Changed queue worker
Push image to registry / build-image (push) Failing after 7m39s
2025-02-20 19:22:38 +01:00
Ninluc f1f32c44b5 Fix daily free screenshot
Push image to registry / build-image (push) Successful in 3m53s
2025-02-19 18:50:34 +01:00
Ninluc 7b51e29060 Don't filter anything
Push image to registry / build-image (push) Successful in 3m43s
2025-02-19 17:47:18 +01:00
Ninluc 9ca6ba3018 Telescope Prune
Push image to registry / build-image (push) Successful in 3m46s
2025-02-19 17:40:57 +01:00
Ninluc a05e5e224d Fix telescope not availible on prod
Push image to registry / build-image (push) Has been cancelled
2025-02-19 17:38:42 +01:00
Ninluc 61e55f960e Fix Job
Push image to registry / build-image (push) Successful in 4m41s
2025-02-18 18:48:48 +01:00
Ninluc 313c0a6a9a Fix queue 2025-02-18 18:48:32 +01:00
Ninluc 2fdd34bc35 Added failed_jobs table 2025-02-18 18:37:05 +01:00
Ninluc e1d7a19f6c Added Telescope 2025-02-18 18:36:55 +01:00
Ninluc 77968e7619 Fix page name 2025-02-16 10:24:47 +01:00
Ninluc e535a85058 Fix favicon
Push image to registry / build-image (push) Successful in 3m47s
2025-02-16 10:21:12 +01:00
Ninluc b40764c4ad Fix crontab
Push image to registry / build-image (push) Successful in 3m47s
2025-02-16 10:04:41 +01:00
Ninluc e6776df487 Fix login button
Push image to registry / build-image (push) Successful in 6m47s
2025-02-15 13:34:37 +01:00
Ninluc 7151c6adff Fix ?
Push image to registry / build-image (push) Successful in 2m4s
2025-02-08 17:59:01 +01:00
Ninluc 22283b3b10 Fix clicking signin with steam
Push image to registry / build-image (push) Successful in 2m7s
2025-02-08 17:54:44 +01:00
Ninluc fa674c3381 Update sign in with steam button
Push image to registry / build-image (push) Successful in 2m50s
2025-02-08 17:44:55 +01:00
Ninluc 8cb0e2f88a Clening up
Push image to registry / build-image (push) Successful in 3m55s
2025-02-08 11:26:10 +01:00
Ninluc 1c3c4b1257 Cache when running
Push image to registry / build-image (push) Successful in 3m46s
2025-02-08 11:16:40 +01:00
Ninluc 77aa2e85c5 idk
Push image to registry / build-image (push) Successful in 35s
2025-02-08 11:13:42 +01:00
Ninluc 9647676c27 Fix debug
Push image to registry / build-image (push) Successful in 3m53s
2025-02-08 11:00:30 +01:00
Ninluc 71ad103a1f debug
Push image to registry / build-image (push) Successful in 3m52s
2025-02-08 10:46:20 +01:00
52 changed files with 2414 additions and 39 deletions
+3
View File
@@ -14,6 +14,7 @@ database/database.sqlite
**/.dockerignore **/.dockerignore
**/.env **/.env
**/.git **/.git
.gitea/
**/.gitignore **/.gitignore
**/.project **/.project
**/.settings **/.settings
@@ -67,3 +68,5 @@ yarn-error.log
app/Browser/console/** app/Browser/console/**
app/Browser/screenshots/** app/Browser/screenshots/**
app/Browser/source/** app/Browser/source/**
undetectedChromedriver
+12
View File
@@ -69,3 +69,15 @@ VITE_APP_URL="${APP_URL}"
DUSK_DRIVER_URL="http://undetected-chromedriver:4444" DUSK_DRIVER_URL="http://undetected-chromedriver:4444"
DUSK_START_MAXIMIZED=true DUSK_START_MAXIMIZED=true
# Reverb (broadcasting)
REVERB_APP_ID=943562
REVERB_APP_KEY=jzysqfijn8wdgugrilbb
REVERB_APP_SECRET=gyotb3asui2zbrltd3ob
REVERB_HOST="localhost"
REVERB_PORT=8080
REVERB_SCHEME=http
VITE_REVERB_APP_KEY="${REVERB_APP_KEY}"
VITE_REVERB_HOST="${REVERB_HOST}"
VITE_REVERB_PORT="${REVERB_PORT}"
VITE_REVERB_SCHEME="${REVERB_SCHEME}"
+13
View File
@@ -68,3 +68,16 @@ VITE_APP_URL="${APP_URL}"
DUSK_DRIVER_URL="http://127.0.0.1:4444" DUSK_DRIVER_URL="http://127.0.0.1:4444"
DUSK_START_MAXIMIZED=true DUSK_START_MAXIMIZED=true
# Reverb (broadcasting)
REVERB_APP_ID=943562
REVERB_APP_KEY=jzysqfijn8wdgugrilbb
REVERB_APP_SECRET=gyotb3asui2zbrltd3ob
REVERB_HOST="localhost"
REVERB_PORT=8080
REVERB_SCHEME=http
VITE_REVERB_APP_KEY="${REVERB_APP_KEY}"
VITE_REVERB_HOST="${REVERB_HOST}"
VITE_REVERB_PORT="${REVERB_PORT}"
VITE_REVERB_SCHEME="${REVERB_SCHEME}"
+5
View File
@@ -21,6 +21,11 @@ yarn-error.log
/.nova /.nova
/.vscode /.vscode
/.zed /.zed
# Python projet
venv
__pycache__
# Browser # Browser
app/Browser/console app/Browser/console
app/Browser/screenshots app/Browser/screenshots
+11 -7
View File
@@ -52,7 +52,9 @@ RUN apk update && apk add --no-cache \
supervisor \ supervisor \
nginx \ nginx \
openssl \ openssl \
linux-headers linux-headers \
supervisor \
&& rm -rf /tmp/* /var/cache/apk/*
RUN docker-php-ext-configure zip && docker-php-ext-install zip RUN docker-php-ext-configure zip && docker-php-ext-install zip
RUN docker-php-ext-install gd pdo pdo_mysql zip RUN docker-php-ext-install gd pdo pdo_mysql zip
@@ -61,7 +63,8 @@ RUN docker-php-ext-install gd pdo pdo_mysql zip
# Get latest Composer # Get latest Composer
COPY --from=composer:latest /usr/bin/composer /usr/bin/composer COPY --from=composer:latest /usr/bin/composer /usr/bin/composer
WORKDIR /var/www ARG wd=/var/www
WORKDIR ${wd}
COPY . . COPY . .
COPY --from=build-vue /usr/app/public/build ./public/build COPY --from=build-vue /usr/app/public/build ./public/build
@@ -74,16 +77,17 @@ RUN mv ${APP_ENV_FILE} .env
RUN composer install --no-interaction --prefer-dist RUN composer install --no-interaction --prefer-dist
# Supervisor
COPY ./docker/datbrowserQueueWorker.conf /etc/supervisor/conf.d/datbrowserQueueWorker.conf
COPY ./docker/supervisord.conf /etc/supervisord.conf
# RUN supervisorctl reread && supervisorctl update
# CRON # CRON
RUN echo "* * * * * cd /usr/app && php artisan schedule:run >> /dev/null 2>&1" > /etc/crontabs/root RUN echo "* * * * * cd ${wd} && php artisan schedule:run >> /dev/null 2>&1" > /etc/crontabs/root
# Link the storage directory to the public directory. # Link the storage directory to the public directory.
RUN php artisan storage:link RUN php artisan storage:link
# Laravel optimization commands
# RUN php artisan cache:clear
RUN php artisan config:cache && php artisan route:cache
RUN chmod +x ./dockerEntryPoint.sh RUN chmod +x ./dockerEntryPoint.sh
EXPOSE 80 EXPOSE 80
+6 -1
View File
@@ -2,6 +2,7 @@
namespace App\Browser; namespace App\Browser;
use App\Models\Job;
use App\Models\JobArtifact; use App\Models\JobArtifact;
use App\Models\JobRun; use App\Models\JobRun;
use Closure; use Closure;
@@ -28,6 +29,8 @@ abstract class BrowserJob implements ShouldQueue
public int $jobId; public int $jobId;
public $timeout = 500;
public function __construct(int $jobId) public function __construct(int $jobId)
{ {
$this->jobId = $jobId; $this->jobId = $jobId;
@@ -153,6 +156,7 @@ abstract class BrowserJob implements ShouldQueue
'--whitelisted-ips=""', '--whitelisted-ips=""',
'--disable-dev-shm-usage', '--disable-dev-shm-usage',
'--user-data-dir=/home/seluser/profile/', '--user-data-dir=/home/seluser/profile/',
'--auto-open-devtools-for-tabs',
])->all()); ])->all());
return RemoteWebDriver::create( return RemoteWebDriver::create(
@@ -214,8 +218,10 @@ abstract class BrowserJob implements ShouldQueue
*/ */
public function handle(): void public function handle(): void
{ {
if (Job::find($this->jobId)->is_active) {
$this->execute(); $this->execute();
} }
}
public function reschedule($minutes) { public function reschedule($minutes) {
$this::dispatch()->delay(now()->addMinutes($minutes)); $this::dispatch()->delay(now()->addMinutes($minutes));
@@ -272,7 +278,6 @@ abstract class BrowserJob implements ShouldQueue
protected function findElementContainingElementWithText(Browser $browser, string $elementXpath, string $text, bool $ignoreCase = true): RemoteWebElement|null { protected function findElementContainingElementWithText(Browser $browser, string $elementXpath, string $text, bool $ignoreCase = true): RemoteWebElement|null {
try { try {
if ($ignoreCase) { if ($ignoreCase) {
dump("{$elementXpath}[.//*[{$this->xpathContainsIgnoreCase($text)}]]");
return $browser->driver->findElement(WebDriverBy::xpath("{$elementXpath}[.//*[{$this->xpathContainsIgnoreCase($text)}]]")); return $browser->driver->findElement(WebDriverBy::xpath("{$elementXpath}[.//*[{$this->xpathContainsIgnoreCase($text)}]]"));
} else { } else {
return $browser->driver->findElement(WebDriverBy::xpath("{$elementXpath}[.//*[contains(text(), \"{$text}\")]]")); return $browser->driver->findElement(WebDriverBy::xpath("{$elementXpath}[.//*[contains(text(), \"{$text}\")]]"));
@@ -0,0 +1,47 @@
<?php
namespace App\Browser\Components\Hellcase;
use Laravel\Dusk\Browser;
use Laravel\Dusk\Component as BaseComponent;
class EpicGamesLogin extends BaseComponent
{
/**
* Get the root selector for the component.
*/
public function selector(): string
{
return 'form';
}
/**
* 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 [
'@email' => 'input#email',
'@password' => 'input#password',
'@signin-button' => 'button[type="submit"]',
];
}
public function fillForm(Browser $browser, $email, $password) {
$browser->type('@email', $email);
sleep(1);
$browser->type('@password', $password);
sleep(1);
$browser->click('@signin-button');
}
}
@@ -37,7 +37,11 @@ class MainNav extends BaseComponent
} }
public function goToHome(Browser $browser) { public function goToHome(Browser $browser) {
try {
$browser->scrollIntoView('@logo'); $browser->scrollIntoView('@logo');
$browser->click('@logo'); $browser->click('@logo');
} catch (\Exception $e) {
$browser->visit('https://hellcase.com/');
}
} }
} }
+174
View File
@@ -0,0 +1,174 @@
<?php
namespace App\Browser\Jobs\EpicGames;
use App\Browser\BrowserJob;
use App\Browser\Components\Hellcase\EpicGamesLogin;
use App\Models\JobInfo;
use App\Models\JobRun;
use App\Notification\Notifications\SimpleNotification;
use App\Notification\Providers\AllNotification;
use Exception;
use Facebook\WebDriver\WebDriverBy;
use Illuminate\Contracts\Queue\ShouldBeUniqueUntilProcessing;
use Illuminate\Support\Facades\Log;
use Laravel\Dusk\Browser;
class EpicGamesJob extends BrowserJob implements ShouldBeUniqueUntilProcessing
{
private const APPROXIMATIVE_RUNNING_MINUTES = 2;
private const WEBSITE_URL = "https://www.epicgames.com/store/en-US/";
private JobRun $jobRun;
public function __construct()
{
Log::info("Constructing " . self::class);
parent::__construct(3);
}
public function run(Browser $browser): ?JobRun
{
// $browser->visit("https://bscscan.com/contractsVerified");
// sleep(3);
Log::info("Running " . self::class);
$this->jobRun = new JobRun([
"job_id" => $this->jobId,
"success" => false,
]);
$this->jobRun->save();
// $this->goToEpicGamesWebsite($browser);
// $this->removePopups($browser);
sleep(5);
$this->signin($browser);
$this->getFreeGames($browser);
$this->jobRun->success = true;
$this->jobRun->save();
Log::info(self::class . " run ended");
return $this->jobRun;
}
/**
* @inheritDoc
*/
public function runTest(Browser $browser): ?JobRun
{
try {
$this->goToEpicGamesWebsite($browser);
sleep(2);
$this->removePopups($browser);
sleep(2);
$this->signin($browser);
return $this->makeSimpleJobRun(
true,
"Connexion réussie",
"Datboi a réussi à se connecter sur EpicGames"
);
} catch (Exception $e) {
return $this->makeSimpleJobRun(
true,
"Connexion échouée",
"Datboi n'a pas réussi à se connecter sur EpicGames :\n" . $e->getMessage()
);
}
}
private function goToEpicGamesWebsite(Browser $browser)
{
sleep(3);
$browser->visit(self::WEBSITE_URL);
sleep(3);
$this->assertNotDetected($browser);
$browser->waitForText("Store", 30, true);
}
private function signin(Browser $browser)
{
// $browser->visit("https://store.epicgames.com/login?state=%2Fen-US%2F");
$browser->driver->executeScript('window.open("https://store.epicgames.com/login?state=%2Fen-US%2F")');
sleep(5);
$this->assertNotDetected($browser);
$browser->waitForText("Sign In", 30, true);
sleep(3);
$jobInfos = JobInfo::where("job_id", $this->jobId)->get();
$email = $jobInfos->where("key", "epicgames_account_email")->first()->value;
$password = $jobInfos->where("key", "epicgames_account_password")->first()->value;
$browser->within(new EpicGamesLogin, function (Browser $browser) use ($email, $password) {
$browser->fillForm($email, $password);
});
sleep(40);
}
private function getFreeGames(Browser $browser)
{
$browser->driver->executeScript('window.open("https://www.epicgames.com/store/en-US/free-games")');
// $browser->visit('https://www.epicgames.com/store/en-US/free-games');
$browser->waitForText("Free Games", 30, true);
$freeGamesLinkElements = $browser->driver->findElements(WebDriverBy::xpath('//a[contains(@aria-label, "Free Now")]'));
$freeGamesLinks = [];
foreach ($freeGamesLinkElements as $element) {
$freeGamesLinks[] = $element->getAttribute("href");
}
foreach ($freeGamesLinks as $link) {
$browser->visit($link);
$this->claimCurrentGame($browser);
}
}
private function claimCurrentGame(Browser $browser)
{
sleep(5);
$this->assertNotDetected($browser);
if ($this->unratedContent($browser)) {
throw new Exception("Le jeu demande un âge et datboi a la flemme de le mettre");
}
$this->waitForAndClickElementContainingText($browser, '//button', "Get", 30, true);
sleep(5);
$this->assertNotDetected($browser);
$browser->waitForText("Place Order", 30, true);
$browser->click("Place Order");
sleep(5);
$this->assertNotDetected($browser);
$browser->waitForText("Order Confirmation", 30, true);
$browser->click("Close");
sleep(5);
AllNotification::send(
new SimpleNotification($this->jobId, "Un jeu a été ajouté à votre bibliothèque", "Un jeu a été ajouté à votre bibliothèque EpicGames")
);
}
private function unratedContent(Browser $browser)
{
try {
$browser->waitForText("please provide your date of birth", 5, true);
return true;
} catch (Exception $_) {
return false;
}
}
private function removePopups(Browser $browser)
{
// $browser->script('document.querySelector("div.app-modal")[0].remove();');
// $browser->driver->executeScript('document.querySelector("div.app-modal")[0].remove();');
}
private function assertNotDetected(Browser $browser)
{
try {
$browser->waitForText("One more step", 10, true);
} catch (Exception $_) {
return;
}
throw new Exception("Détecté par cloudflare");
}
}
+41 -17
View File
@@ -4,41 +4,44 @@ namespace App\Browser\Jobs\Hellcase;
use App\Browser\BrowserJob; use App\Browser\BrowserJob;
use App\Browser\Components\Hellcase\MainNav; use App\Browser\Components\Hellcase\MainNav;
use App\Models\JobArtifact;
use App\Browser\JobArtifacts\JobRunArtifact;
use App\Browser\Jobs\Hellcase\HellcaseLoginQrCode; use App\Browser\Jobs\Hellcase\HellcaseLoginQrCode;
use App\Models\JobArtifact;
use App\Models\JobRun; use App\Models\JobRun;
use App\Notification\NotificationBody\Hellcase\HellcaseNotificationDailyFreeBody; use App\Notification\NotificationBody\Hellcase\HellcaseNotificationDailyFreeBody;
use App\Notification\NotificationBody\Hellcase\HellcaseNotificationLoginBody; use App\Notification\NotificationBody\Hellcase\HellcaseNotificationLoginBody;
use App\Notification\Notifications\Hellcase\HellcaseNotificationDailyFree; use App\Notification\Notifications\Hellcase\HellcaseNotificationDailyFree;
use App\Notification\Notifications\Hellcase\HellcaseNotificationLogin; use App\Notification\Notifications\Hellcase\HellcaseNotificationLogin;
use App\Notification\Providers\AllNotification; use App\Notification\Providers\AllNotification;
use Dom\XPath;
use Facebook\WebDriver\WebDriverBy; use Facebook\WebDriver\WebDriverBy;
use Illuminate\Support\Facades\Schedule; use Illuminate\Contracts\Queue\ShouldBeUniqueUntilProcessing;
use Illuminate\Support\Facades\Log;
use Laravel\Dusk\Browser; use Laravel\Dusk\Browser;
class HellcaseJob extends BrowserJob class HellcaseJob extends BrowserJob implements ShouldBeUniqueUntilProcessing
{ {
private const STEAM_LOGIN_THRESHOLD = 5 * 60; // 5 minutes private const STEAM_LOGIN_THRESHOLD = 5 * 60; // 5 minutes
private const APPROXIMATIVE_RUNNING_MINUTES = 2;
private const WEBSITE_URL = "https://hellcase.com";
private JobRun $jobRun; private JobRun $jobRun;
public function __construct() public function __construct()
{ {
Log::info("Constructing " . self::class);
parent::__construct(2); parent::__construct(2);
} }
public function run(Browser $browser): ?JobRun public function run(Browser $browser): ?JobRun
{ {
Log::info("Running " . self::class);
$this->jobRun = new JobRun([ $this->jobRun = new JobRun([
"job_id" => $this->jobId, "job_id" => $this->jobId,
"success" => false, "success" => false,
]); ]);
$this->jobRun->save(); $this->jobRun->save();
$browser->visit('https://hellcase.com'); $browser->visit(self::WEBSITE_URL);
$browser->waitForText("Store", 30, true); $browser->waitForText("CASES", 30, true);
$this->removePopups($browser); $this->removePopups($browser);
sleep(5); sleep(5);
$this->signin($browser); $this->signin($browser);
@@ -48,6 +51,8 @@ class HellcaseJob extends BrowserJob
$this->jobRun->success = true; $this->jobRun->success = true;
$this->jobRun->save(); $this->jobRun->save();
Log::info(self::class . " run ended");
return $this->jobRun; return $this->jobRun;
} }
@@ -57,7 +62,7 @@ class HellcaseJob extends BrowserJob
public function runTest(Browser $browser): ?JobRun public function runTest(Browser $browser): ?JobRun
{ {
try { try {
$browser->visit('https://hellcase.com'); $browser->visit(self::WEBSITE_URL);
$browser->waitForText("CASES", 30, true); $browser->waitForText("CASES", 30, true);
$this->removePopups($browser); $this->removePopups($browser);
sleep(2); sleep(2);
@@ -84,8 +89,10 @@ class HellcaseJob extends BrowserJob
return; return;
} }
sleep(5);
$browser->waitForText("Sign in with Steam", 30, true);
sleep(3); sleep(3);
$browser->clickAtXPath('//button[.//span[contains(text(), "Sign in through Steam")]]'); $browser->driver->findElement(WebDriverBy::xpath('//button[@class = "_base_1uydq_1 _accent-1_1uydq_105 _m_1uydq_52 _full_1uydq_94 _primary_1uydq_100"]'))->click();
sleep(5); sleep(5);
// QR CODE SCANNING // QR CODE SCANNING
@@ -123,10 +130,10 @@ class HellcaseJob extends BrowserJob
} }
if ($isBackOnHellcase) { if ($isBackOnHellcase) {
// Click a button tjat says "sign in" // Click a button that says "sign in"
$browser->waitForText("By signing into steam.loginhell.com through Steam", 30, true); $browser->waitForText("By signing into steam.loginhell.com through Steam", 30, true);
$browser->clickAtXPath('//input[@id = "imageLogin"]'); $browser->clickAtXPath('//input[@id = "imageLogin"]');
sleep(30); sleep(20);
} }
} }
@@ -159,6 +166,8 @@ class HellcaseJob extends BrowserJob
$joinButton = $browser->driver->findElement(WebDriverBy::xpath('//button[span[contains(text(), "Join for free")]]')); $joinButton = $browser->driver->findElement(WebDriverBy::xpath('//button[span[contains(text(), "Join for free")]]'));
$joinButton->click(); $joinButton->click();
sleep(3);
// JobRun // JobRun
// Get the elements text containing class starting with giveaway-entity-prize__ // Get the elements text containing class starting with giveaway-entity-prize__
$prizeElement = $browser->driver->findElements(WebDriverBy::xpath('//div[starts-with(@class, "giveaway-entity-prize__")]')); $prizeElement = $browser->driver->findElements(WebDriverBy::xpath('//div[starts-with(@class, "giveaway-entity-prize__")]'));
@@ -187,6 +196,11 @@ class HellcaseJob extends BrowserJob
$availibleInButton = $browser->driver->findElement(WebDriverBy::xpath('//button[contains(@class, "daily-free-banner__button")]')); $availibleInButton = $browser->driver->findElement(WebDriverBy::xpath('//button[contains(@class, "daily-free-banner__button")]'));
if ($availibleInButton->getAttribute("disabled") == "true") { if ($availibleInButton->getAttribute("disabled") == "true") {
$hours = $availibleInButton->getText(); $hours = $availibleInButton->getText();
// If the text is like "in 26 sec." we need to put one minute
if (str_contains($hours, "sec")) {
$this->reschedule(1);
return;
}
$hours = explode(" ", $hours); $hours = explode(" ", $hours);
$minutes = $hours[4]; $minutes = $hours[4];
$hours = $hours[2]; $hours = $hours[2];
@@ -204,9 +218,15 @@ class HellcaseJob extends BrowserJob
// Click the dailyfree button // Click the dailyfree button
$availibleInButton->click(); $availibleInButton->click();
sleep(15);
$browser->waitForText("Your drop", 30, true);
$lootElement = $browser->driver->findElement(WebDriverBy::xpath('//div[contains(@class, "daily-free-win-bonus")]')); $lootElement = $browser->driver->findElement(WebDriverBy::xpath('//div[contains(@class, "daily-free-win-bonus")]'));
$lootElement->takeElementScreenshot(HellcaseDailyFreeScreenshot::getImgFileAbsolutePath()); $lootElement->takeElementScreenshot(HellcaseDailyFreeScreenshot::getImgFileAbsolutePath());
$this->reschedule((24 * 60) - ($this::APPROXIMATIVE_RUNNING_MINUTES / 2)); // Reschedule in 24hr -1min
AllNotification::send( AllNotification::send(
new HellcaseNotificationDailyFree($this->jobId, new HellcaseNotificationDailyFreeBody()) new HellcaseNotificationDailyFree($this->jobId, new HellcaseNotificationDailyFreeBody())
); );
@@ -218,11 +238,12 @@ class HellcaseJob extends BrowserJob
* @throws \Exception * @throws \Exception
* @return void * @return void
*/ */
private function fillDailyFreeConditions(Browser $browser) { private function fillDailyFreeConditions(Browser $browser)
{
// 1. See what conditions we need to fullfill // 1. See what conditions we need to fullfill
$conditions = []; $conditions = [];
$conditionsDivs = $browser->driver->findElements(WebDriverBy::xpath('//*[@class = "daily-free-requirement__heading-left"]')); $conditionsDivs = $browser->driver->findElements(WebDriverBy::xpath('//*[@class = "daily-free-requirement__heading-left"]'));
for($i = 0; $i < sizeof($conditionsDivs); $i++) { for ($i = 0; $i < sizeof($conditionsDivs); $i++) {
$conditionDiv = $conditionsDivs[$i]; $conditionDiv = $conditionsDivs[$i];
// See if the element has the completed class // See if the element has the completed class
$conditions[$i] = [ $conditions[$i] = [
@@ -249,13 +270,14 @@ class HellcaseJob extends BrowserJob
* @param \Laravel\Dusk\Browser $browser * @param \Laravel\Dusk\Browser $browser
* @return void * @return void
*/ */
private function changeSteamProfilePicture(Browser $browser) { private function changeSteamProfilePicture(Browser $browser)
{
// Get all of the availible image link // Get all of the availible image link
$images = $browser->driver->findElements(WebDriverBy::xpath('//a[@class = "daily-free-user-requirement-avatar-item"]')); $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 // Download the image from the second link in a special folder
$imageLink = $images[1]->getAttribute("href"); $imageLink = $images[1]->getAttribute("href");
// Download the image in app/Browser/downloads/ // Download the image in app/Browser/downloads/
$imagePath = base_path("app/Browser/downloads/Hellcase/pp.jpg"); $imagePath = base_path("app/Browser/downloads/Hellcase/pp.png");
file_put_contents($imagePath, file_get_contents($imageLink)); file_put_contents($imagePath, file_get_contents($imageLink));
$this->goToSteamProfileSettings($browser); $this->goToSteamProfileSettings($browser);
@@ -288,7 +310,8 @@ class HellcaseJob extends BrowserJob
} }
} }
private function changeSteamProfileToPublic(Browser $browser) { private function changeSteamProfileToPublic(Browser $browser)
{
$this->goToSteamProfileSettings($browser); $this->goToSteamProfileSettings($browser);
// Wait for and click "Privacy Settings" // Wait for and click "Privacy Settings"
@@ -312,7 +335,8 @@ class HellcaseJob extends BrowserJob
* @param \Laravel\Dusk\Browser $browser * @param \Laravel\Dusk\Browser $browser
* @return void * @return void
*/ */
private function goToSteamProfileSettings(Browser $browser) { private function goToSteamProfileSettings(Browser $browser)
{
// Get the link that has text "Steam profile" // Get the link that has text "Steam profile"
$steamProfileLink = $browser->driver->findElement(WebDriverBy::xpath('//a[contains(text(), "Steam profile")]')); $steamProfileLink = $browser->driver->findElement(WebDriverBy::xpath('//a[contains(text(), "Steam profile")]'));
$browser->visit($steamProfileLink->getAttribute("href")); $browser->visit($steamProfileLink->getAttribute("href"));
+35
View File
@@ -0,0 +1,35 @@
<?php
namespace App\Jobs;
use App\Models\Job;
use App\Models\JobRun;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Foundation\Queue\Queueable;
class PruneOldJobRuns implements ShouldQueue
{
use Queueable;
/**
* Create a new job instance.
*/
public function __construct()
{
//
}
/**
* Execute the job.
*/
public function handle(): void
{
// For each job, keep only the last N runs
foreach (Job::all() as $job) {
$job->jobRuns()
->orderByDesc('id')
->skip(config('jobs.pruneOldJobRuns.max_runs_per_job'))
->delete();
}
}
}
+1 -3
View File
@@ -24,9 +24,7 @@ class AppServiceProvider extends ServiceProvider
{ {
Vite::prefetch(concurrency: 3); Vite::prefetch(concurrency: 3);
dump(env('APP_URL')); if (str_starts_with(config('app.url'), "https://")) {
dump(config('app.url'));
if (str_starts_with(env('APP_URL'), "https://")) {
$url->forceScheme('https'); $url->forceScheme('https');
} }
} }
@@ -0,0 +1,67 @@
<?php
namespace App\Providers;
use Illuminate\Support\Facades\Gate;
use Laravel\Telescope\IncomingEntry;
use Laravel\Telescope\Telescope;
use Laravel\Telescope\TelescopeApplicationServiceProvider;
class TelescopeServiceProvider extends TelescopeApplicationServiceProvider
{
/**
* Register any application services.
*/
public function register(): void
{
Telescope::night();
$this->hideSensitiveRequestDetails();
$isLocal = $this->app->environment('local');
Telescope::filter(function (IncomingEntry $entry) use ($isLocal) {
return true;
/* $isLocal ||
$entry->isReportableException() ||
$entry->isFailedRequest() ||
$entry->isFailedJob() ||
$entry->isScheduledTask() ||
$entry->isCache() ||
$entry->isDump() ||
$entry->isQuery() ||
$entry->isSlowQuery() ||
$entry->hasMonitoredTag(); */
});
}
/**
* Prevent sensitive request details from being logged by Telescope.
*/
protected function hideSensitiveRequestDetails(): void
{
if ($this->app->environment('local')) {
return;
}
Telescope::hideRequestParameters(['_token']);
Telescope::hideRequestHeaders([
'cookie',
'x-csrf-token',
'x-xsrf-token',
]);
}
/**
* Register the Telescope gate.
*
* This gate determines who can access Telescope in non-local environments.
*/
protected function gate(): void
{
Gate::define('viewTelescope', function ($user) {
return true;
});
}
}
+1
View File
@@ -9,6 +9,7 @@ return Application::configure(basePath: dirname(__DIR__))
web: __DIR__.'/../routes/web.php', web: __DIR__.'/../routes/web.php',
api: __DIR__.'/../routes/api.php', api: __DIR__.'/../routes/api.php',
commands: __DIR__.'/../routes/console.php', commands: __DIR__.'/../routes/console.php',
channels: __DIR__.'/../routes/channels.php',
health: '/up', health: '/up',
) )
->withMiddleware(function (Middleware $middleware) { ->withMiddleware(function (Middleware $middleware) {
+1
View File
@@ -3,4 +3,5 @@
return [ return [
App\Providers\AppServiceProvider::class, App\Providers\AppServiceProvider::class,
App\Providers\BrowserJobsServiceProvider::class, App\Providers\BrowserJobsServiceProvider::class,
App\Providers\TelescopeServiceProvider::class,
]; ];
+2
View File
@@ -14,7 +14,9 @@
"inertiajs/inertia-laravel": "^2.0", "inertiajs/inertia-laravel": "^2.0",
"laravel/dusk": "^8.2", "laravel/dusk": "^8.2",
"laravel/framework": "^11.31", "laravel/framework": "^11.31",
"laravel/reverb": "^1.0",
"laravel/sanctum": "^4.0", "laravel/sanctum": "^4.0",
"laravel/telescope": "^5.5",
"laravel/tinker": "^2.9", "laravel/tinker": "^2.9",
"tightenco/ziggy": "^2.0" "tightenco/ziggy": "^2.0"
}, },
Generated
+1068 -1
View File
File diff suppressed because it is too large Load Diff
+82
View File
@@ -0,0 +1,82 @@
<?php
return [
/*
|--------------------------------------------------------------------------
| Default Broadcaster
|--------------------------------------------------------------------------
|
| This option controls the default broadcaster that will be used by the
| framework when an event needs to be broadcast. You may set this to
| any of the connections defined in the "connections" array below.
|
| Supported: "reverb", "pusher", "ably", "redis", "log", "null"
|
*/
'default' => env('BROADCAST_CONNECTION', 'reverb'),
/*
|--------------------------------------------------------------------------
| Broadcast Connections
|--------------------------------------------------------------------------
|
| Here you may define all of the broadcast connections that will be used
| to broadcast events to other systems or over WebSockets. Samples of
| each available type of connection are provided inside this array.
|
*/
'connections' => [
'reverb' => [
'driver' => 'reverb',
'key' => env('REVERB_APP_KEY'),
'secret' => env('REVERB_APP_SECRET'),
'app_id' => env('REVERB_APP_ID'),
'options' => [
'host' => env('REVERB_HOST'),
'port' => env('REVERB_PORT', 443),
'scheme' => env('REVERB_SCHEME', 'https'),
'useTLS' => env('REVERB_SCHEME', 'https') === 'https',
],
'client_options' => [
// Guzzle client options: https://docs.guzzlephp.org/en/stable/request-options.html
],
],
'pusher' => [
'driver' => 'pusher',
'key' => env('PUSHER_APP_KEY'),
'secret' => env('PUSHER_APP_SECRET'),
'app_id' => env('PUSHER_APP_ID'),
'options' => [
'cluster' => env('PUSHER_APP_CLUSTER'),
'host' => env('PUSHER_HOST') ?: 'api-'.env('PUSHER_APP_CLUSTER', 'mt1').'.pusher.com',
'port' => env('PUSHER_PORT', 443),
'scheme' => env('PUSHER_SCHEME', 'https'),
'encrypted' => true,
'useTLS' => env('PUSHER_SCHEME', 'https') === 'https',
],
'client_options' => [
// Guzzle client options: https://docs.guzzlephp.org/en/stable/request-options.html
],
],
'ably' => [
'driver' => 'ably',
'key' => env('ABLY_KEY'),
],
'log' => [
'driver' => 'log',
],
'null' => [
'driver' => 'null',
],
],
];
+4
View File
@@ -75,6 +75,10 @@ return [
'links' => [ 'links' => [
public_path('storage') => storage_path('app/public'), public_path('storage') => storage_path('app/public'),
public_path('console') => base_path('app/Browser/console'),
public_path('downloads') => base_path('app/Browser/downloads'),
public_path('screenshots') => base_path('app/Browser/screenshots'),
public_path('source') => base_path('app/Browser/source'),
], ],
]; ];
+20
View File
@@ -0,0 +1,20 @@
<?php
use Laravel\Telescope\Http\Middleware\Authorize;
use Laravel\Telescope\Watchers;
return [
/**
* Remove old job runs from the database.
*/
'pruneOldJobRuns' => [
'enabled' => true,
/**
* How many job runs a job can keep before we start pruning old ones.
*/
'max_runs_per_job' => 50,
],
];
+92
View File
@@ -0,0 +1,92 @@
<?php
return [
/*
|--------------------------------------------------------------------------
| Default Reverb Server
|--------------------------------------------------------------------------
|
| This option controls the default server used by Reverb to handle
| incoming messages as well as broadcasting message to all your
| connected clients. At this time only "reverb" is supported.
|
*/
'default' => env('REVERB_SERVER', 'reverb'),
/*
|--------------------------------------------------------------------------
| Reverb Servers
|--------------------------------------------------------------------------
|
| Here you may define details for each of the supported Reverb servers.
| Each server has its own configuration options that are defined in
| the array below. You should ensure all the options are present.
|
*/
'servers' => [
'reverb' => [
'host' => env('REVERB_SERVER_HOST', '0.0.0.0'),
'port' => env('REVERB_SERVER_PORT', 8080),
'hostname' => env('REVERB_HOST'),
'options' => [
'tls' => [],
],
'max_request_size' => env('REVERB_MAX_REQUEST_SIZE', 10_000),
'scaling' => [
'enabled' => env('REVERB_SCALING_ENABLED', false),
'channel' => env('REVERB_SCALING_CHANNEL', 'reverb'),
'server' => [
'url' => env('REDIS_URL'),
'host' => env('REDIS_HOST', '127.0.0.1'),
'port' => env('REDIS_PORT', '6379'),
'username' => env('REDIS_USERNAME'),
'password' => env('REDIS_PASSWORD'),
'database' => env('REDIS_DB', '0'),
],
],
'pulse_ingest_interval' => env('REVERB_PULSE_INGEST_INTERVAL', 15),
'telescope_ingest_interval' => env('REVERB_TELESCOPE_INGEST_INTERVAL', 15),
],
],
/*
|--------------------------------------------------------------------------
| Reverb Applications
|--------------------------------------------------------------------------
|
| Here you may define how Reverb applications are managed. If you choose
| to use the "config" provider, you may define an array of apps which
| your server will support, including their connection credentials.
|
*/
'apps' => [
'provider' => 'config',
'apps' => [
[
'key' => env('REVERB_APP_KEY'),
'secret' => env('REVERB_APP_SECRET'),
'app_id' => env('REVERB_APP_ID'),
'options' => [
'host' => env('REVERB_HOST'),
'port' => env('REVERB_PORT', 443),
'scheme' => env('REVERB_SCHEME', 'https'),
'useTLS' => env('REVERB_SCHEME', 'https') === 'https',
],
'allowed_origins' => ['*'],
'ping_interval' => env('REVERB_APP_PING_INTERVAL', 60),
'activity_timeout' => env('REVERB_APP_ACTIVITY_TIMEOUT', 30),
'max_message_size' => env('REVERB_APP_MAX_MESSAGE_SIZE', 10_000),
],
],
],
];
+206
View File
@@ -0,0 +1,206 @@
<?php
use Laravel\Telescope\Http\Middleware\Authorize;
use Laravel\Telescope\Watchers;
return [
/*
|--------------------------------------------------------------------------
| Telescope Master Switch
|--------------------------------------------------------------------------
|
| This option may be used to disable all Telescope watchers regardless
| of their individual configuration, which simply provides a single
| and convenient way to enable or disable Telescope data storage.
|
*/
'enabled' => env('TELESCOPE_ENABLED', true),
/*
|--------------------------------------------------------------------------
| Telescope Domain
|--------------------------------------------------------------------------
|
| This is the subdomain where Telescope will be accessible from. If the
| setting is null, Telescope will reside under the same domain as the
| application. Otherwise, this value will be used as the subdomain.
|
*/
'domain' => env('TELESCOPE_DOMAIN'),
/*
|--------------------------------------------------------------------------
| Telescope Path
|--------------------------------------------------------------------------
|
| This is the URI path where Telescope will be accessible from. Feel free
| to change this path to anything you like. Note that the URI will not
| affect the paths of its internal API that aren't exposed to users.
|
*/
'path' => env('TELESCOPE_PATH', 'telescope'),
/*
|--------------------------------------------------------------------------
| Telescope Storage Driver
|--------------------------------------------------------------------------
|
| This configuration options determines the storage driver that will
| be used to store Telescope's data. In addition, you may set any
| custom options as needed by the particular driver you choose.
|
*/
'driver' => env('TELESCOPE_DRIVER', 'database'),
'storage' => [
'database' => [
'connection' => env('DB_CONNECTION', 'mysql'),
'chunk' => 1000,
],
],
/*
|--------------------------------------------------------------------------
| Telescope Queue
|--------------------------------------------------------------------------
|
| This configuration options determines the queue connection and queue
| which will be used to process ProcessPendingUpdate jobs. This can
| be changed if you would prefer to use a non-default connection.
|
*/
'queue' => [
'connection' => env('TELESCOPE_QUEUE_CONNECTION', null),
'queue' => env('TELESCOPE_QUEUE', null),
'delay' => env('TELESCOPE_QUEUE_DELAY', 10),
],
/*
|--------------------------------------------------------------------------
| Telescope Route Middleware
|--------------------------------------------------------------------------
|
| These middleware will be assigned to every Telescope route, giving you
| the chance to add your own middleware to this list or change any of
| the existing middleware. Or, you can simply stick with this list.
|
*/
'middleware' => [
'web',
// Authorize::class,
],
/*
|--------------------------------------------------------------------------
| Allowed / Ignored Paths & Commands
|--------------------------------------------------------------------------
|
| The following array lists the URI paths and Artisan commands that will
| not be watched by Telescope. In addition to this list, some Laravel
| commands, like migrations and queue commands, are always ignored.
|
*/
'only_paths' => [
// 'api/*'
],
'ignore_paths' => [
'livewire*',
'nova-api*',
'pulse*',
],
'ignore_commands' => [
//
],
/*
|--------------------------------------------------------------------------
| Telescope Watchers
|--------------------------------------------------------------------------
|
| The following array lists the "watchers" that will be registered with
| Telescope. The watchers gather the application's profile data when
| a request or task is executed. Feel free to customize this list.
|
*/
'watchers' => [
Watchers\BatchWatcher::class => env('TELESCOPE_BATCH_WATCHER', true),
Watchers\CacheWatcher::class => [
'enabled' => env('TELESCOPE_CACHE_WATCHER', true),
'hidden' => [],
],
Watchers\ClientRequestWatcher::class => env('TELESCOPE_CLIENT_REQUEST_WATCHER', true),
Watchers\CommandWatcher::class => [
'enabled' => env('TELESCOPE_COMMAND_WATCHER', true),
'ignore' => [],
],
Watchers\DumpWatcher::class => [
'enabled' => env('TELESCOPE_DUMP_WATCHER', true),
'always' => env('TELESCOPE_DUMP_WATCHER_ALWAYS', false),
],
Watchers\EventWatcher::class => [
'enabled' => env('TELESCOPE_EVENT_WATCHER', true),
'ignore' => [],
],
Watchers\ExceptionWatcher::class => env('TELESCOPE_EXCEPTION_WATCHER', true),
Watchers\GateWatcher::class => [
'enabled' => env('TELESCOPE_GATE_WATCHER', true),
'ignore_abilities' => [],
'ignore_packages' => true,
'ignore_paths' => [],
],
Watchers\JobWatcher::class => env('TELESCOPE_JOB_WATCHER', true),
Watchers\LogWatcher::class => [
'enabled' => env('TELESCOPE_LOG_WATCHER', true),
'level' => 'error',
],
Watchers\MailWatcher::class => env('TELESCOPE_MAIL_WATCHER', true),
Watchers\ModelWatcher::class => [
'enabled' => env('TELESCOPE_MODEL_WATCHER', true),
'events' => ['eloquent.*'],
'hydrations' => true,
],
Watchers\NotificationWatcher::class => env('TELESCOPE_NOTIFICATION_WATCHER', true),
Watchers\QueryWatcher::class => [
'enabled' => env('TELESCOPE_QUERY_WATCHER', true),
'ignore_packages' => true,
'ignore_paths' => [],
'slow' => 100,
],
Watchers\RedisWatcher::class => env('TELESCOPE_REDIS_WATCHER', true),
Watchers\RequestWatcher::class => [
'enabled' => env('TELESCOPE_REQUEST_WATCHER', true),
'size_limit' => env('TELESCOPE_RESPONSE_SIZE_LIMIT', 64),
'ignore_http_methods' => [],
'ignore_status_codes' => [],
],
Watchers\ScheduleWatcher::class => env('TELESCOPE_SCHEDULE_WATCHER', true),
Watchers\ViewWatcher::class => env('TELESCOPE_VIEW_WATCHER', true),
],
];
@@ -0,0 +1,70 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
/**
* Get the migration connection name.
*/
public function getConnection(): ?string
{
return config('telescope.storage.database.connection');
}
/**
* Run the migrations.
*/
public function up(): void
{
$schema = Schema::connection($this->getConnection());
$schema->create('telescope_entries', function (Blueprint $table) {
$table->bigIncrements('sequence');
$table->uuid('uuid');
$table->uuid('batch_id');
$table->string('family_hash')->nullable();
$table->boolean('should_display_on_index')->default(true);
$table->string('type', 20);
$table->longText('content');
$table->dateTime('created_at')->nullable();
$table->unique('uuid');
$table->index('batch_id');
$table->index('family_hash');
$table->index('created_at');
$table->index(['type', 'should_display_on_index']);
});
$schema->create('telescope_entries_tags', function (Blueprint $table) {
$table->uuid('entry_uuid');
$table->string('tag');
$table->primary(['entry_uuid', 'tag']);
$table->index('tag');
$table->foreign('entry_uuid')
->references('uuid')
->on('telescope_entries')
->onDelete('cascade');
});
$schema->create('telescope_monitoring', function (Blueprint $table) {
$table->string('tag')->primary();
});
}
/**
* Reverse the migrations.
*/
public function down(): void
{
$schema = Schema::connection($this->getConnection());
$schema->dropIfExists('telescope_entries_tags');
$schema->dropIfExists('telescope_entries');
$schema->dropIfExists('telescope_monitoring');
}
};
@@ -0,0 +1,32 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
/**
* Run the migrations.
*/
public function up(): void
{
Schema::create('failed_jobs', function (Blueprint $table) {
$table->id();
$table->string('uuid')->unique();
$table->text('connection');
$table->text('queue');
$table->longText('payload');
$table->longText('exception');
$table->timestamp('failed_at')->useCurrent();
});
}
/**
* Reverse the migrations.
*/
public function down(): void
{
Schema::dropIfExists('failed_jobs');
}
};
@@ -0,0 +1,44 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration {
/**
* Run the migrations.
*/
public function up(): void
{
$jobId = 3;
\App\Models\Job::forcecreate([
'id' => $jobId,
'name' => 'Jeu gratuit Epic Games',
'description' => 'Prends le jeu gratuit Epic games. Tourne tous les jours.',
]);
\App\Models\JobInfo::forceCreate([
"key" => "epicgames_account_email",
"name" => "E-mail",
"description" => "L'adresse e-mail utilisée pour votre compte Epic Games.",
"job_info_type_id" => 2,
"job_id" => $jobId,
], );
\App\Models\JobInfo::forceCreate([
"key" => "epicgames_account_password",
"name" => "Mot de passe",
"description" => "Le mot de passe utilisé pour votre compte Epic Games.",
"job_info_type_id" => 3,
"job_id" => $jobId,
]);
}
/**
* Reverse the migrations.
*/
public function down(): void
{
\App\Models\Job::find(3)->delete();
\App\Models\JobInfo::where('job_id', 3)->delete();
}
};
+12
View File
@@ -0,0 +1,12 @@
[program:laravel-worker]
process_name=%(program_name)s_%(process_num)02d
command=php /var/www/artisan queue:work --queue=high,default --tries=3 --timeout=300 --sleep=3 --no-interaction --max-time=3600 --max-jobs=1
autostart=true
autorestart=true
stopasgroup=true
killasgroup=true
user=root
numprocs=1
redirect_stderr=true
stdout_logfile=/var/www/worker.log
stopwaitsecs=3600
+7
View File
@@ -0,0 +1,7 @@
[supervisord]
nodaemon=true
user=root
[include]
files = /etc/supervisor/conf.d/*.conf
+7 -1
View File
@@ -3,9 +3,15 @@
# Migrate the database # Migrate the database
php ./artisan migrate --force php ./artisan migrate --force
# Cache
php ./artisan optimize:clear && php ./artisan optimize
# Scheduler
crond -b -L /dev/stdout
# Queue worker # Queue worker
php ./artisan queue:work --queue=high,default --tries=3 --timeout=90 --sleep=3 --daemon --no-interaction & supervisord --nodaemon --configuration /etc/supervisord.conf &
supervisorctl start "laravel-worker:*"
# Start all of the server sumulataneously # Start all of the server sumulataneously
php ./artisan serve --no-interaction -vvv --port=80 --host=0.0.0.0 php ./artisan serve --no-interaction -vvv --port=80 --host=0.0.0.0
+2
View File
@@ -12,8 +12,10 @@
"autoprefixer": "^10.4.12", "autoprefixer": "^10.4.12",
"axios": "^1.7.4", "axios": "^1.7.4",
"concurrently": "^9.0.1", "concurrently": "^9.0.1",
"laravel-echo": "^2.0.2",
"laravel-vite-plugin": "^1.2.0", "laravel-vite-plugin": "^1.2.0",
"postcss": "^8.4.31", "postcss": "^8.4.31",
"pusher-js": "^8.4.0",
"sass-embedded": "^1.83.4", "sass-embedded": "^1.83.4",
"tailwindcss": "^3.2.1", "tailwindcss": "^3.2.1",
"typescript": "^5.6.3", "typescript": "^5.6.3",
+231
View File
@@ -8,6 +8,9 @@ importers:
.: .:
dependencies: dependencies:
'@vueuse/core':
specifier: ^12.5.0
version: 12.7.0(typescript@5.7.3)
class-variance-authority: class-variance-authority:
specifier: ^0.7.1 specifier: ^0.7.1
version: 0.7.1 version: 0.7.1
@@ -17,6 +20,12 @@ importers:
lucide-react: lucide-react:
specifier: ^0.474.0 specifier: ^0.474.0
version: 0.474.0(react@19.0.0) version: 0.474.0(react@19.0.0)
lucide-vue-next:
specifier: ^0.474.0
version: 0.474.0(vue@3.5.13(typescript@5.7.3))
radix-vue:
specifier: ^1.9.13
version: 1.9.16(vue@3.5.13(typescript@5.7.3))
tailwind-merge: tailwind-merge:
specifier: ^2.6.0 specifier: ^2.6.0
version: 2.6.0 version: 2.6.0
@@ -42,12 +51,18 @@ importers:
concurrently: concurrently:
specifier: ^9.0.1 specifier: ^9.0.1
version: 9.1.2 version: 9.1.2
laravel-echo:
specifier: ^2.0.2
version: 2.0.2
laravel-vite-plugin: laravel-vite-plugin:
specifier: ^1.2.0 specifier: ^1.2.0
version: 1.2.0(vite@6.0.11(jiti@1.21.7)(sass-embedded@1.83.4)(yaml@2.7.0)) version: 1.2.0(vite@6.0.11(jiti@1.21.7)(sass-embedded@1.83.4)(yaml@2.7.0))
postcss: postcss:
specifier: ^8.4.31 specifier: ^8.4.31
version: 8.5.1 version: 8.5.1
pusher-js:
specifier: ^8.4.0
version: 8.4.0
sass-embedded: sass-embedded:
specifier: ^1.83.4 specifier: ^1.83.4
version: 1.83.4 version: 1.83.4
@@ -243,6 +258,18 @@ packages:
cpu: [x64] cpu: [x64]
os: [win32] os: [win32]
'@floating-ui/core@1.6.9':
resolution: {integrity: sha512-uMXCuQ3BItDUbAMhIXw7UPXRfAlOAvZzdK9BWpE60MCn+Svt3aLn9jsPTi/WNGlRUu2uI0v5S7JiIUsbsvh3fw==}
'@floating-ui/dom@1.6.13':
resolution: {integrity: sha512-umqzocjDgNRGTuO7Q8CU32dkHkECqI8ZdMZ5Swb6QAM0t5rnlrN3lGo1hdpscRd3WS8T6DKYK4ephgIH9iRh3w==}
'@floating-ui/utils@0.2.9':
resolution: {integrity: sha512-MDWhGtE+eHw5JW7lq4qhc5yRLS11ERl1c7Z6Xd0a58DozHES6EnNNwUWbMiG4J9Cgj053Bhk8zvlhFYKVhULwg==}
'@floating-ui/vue@1.1.6':
resolution: {integrity: sha512-XFlUzGHGv12zbgHNk5FN2mUB7ROul3oG2ENdTpWdE+qMFxyNxWSRmsoyhiEnpmabNm6WnUvR1OvJfUfN4ojC1A==}
'@inertiajs/core@2.0.3': '@inertiajs/core@2.0.3':
resolution: {integrity: sha512-JvXzqc2XAt3WgEDMyxCyXO6bDLMCsBjFsYREU1/+3wtNTib7QKwK71+aF+MrhILpz+kRTi29TsLqnbkPHBAZjw==} resolution: {integrity: sha512-JvXzqc2XAt3WgEDMyxCyXO6bDLMCsBjFsYREU1/+3wtNTib7QKwK71+aF+MrhILpz+kRTi29TsLqnbkPHBAZjw==}
@@ -251,6 +278,12 @@ packages:
peerDependencies: peerDependencies:
vue: ^3.0.0 vue: ^3.0.0
'@internationalized/date@3.7.0':
resolution: {integrity: sha512-VJ5WS3fcVx0bejE/YHfbDKR/yawZgKqn/if+oEeLqNwBtPzVB06olkfcnojTmEMX+gTpH+FlQ69SHNitJ8/erQ==}
'@internationalized/number@3.6.0':
resolution: {integrity: sha512-PtrRcJVy7nw++wn4W2OuePQQfTqDzfusSuY1QTtui4wa7r+rGVtR75pO8CyKvHvzyQYi3Q1uO5sY0AsB4e65Bw==}
'@isaacs/cliui@8.0.2': '@isaacs/cliui@8.0.2':
resolution: {integrity: sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==} resolution: {integrity: sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==}
engines: {node: '>=12'} engines: {node: '>=12'}
@@ -384,14 +417,28 @@ packages:
cpu: [x64] cpu: [x64]
os: [win32] os: [win32]
'@swc/helpers@0.5.15':
resolution: {integrity: sha512-JQ5TuMi45Owi4/BIMAJBoSQoOJu12oOk/gADqlcUL9JEdHB8vyjUSsxqeNXnmXHjYKMi2WcYtezGEEhqUI/E2g==}
'@tailwindcss/forms@0.5.10': '@tailwindcss/forms@0.5.10':
resolution: {integrity: sha512-utI1ONF6uf/pPNO68kmN1b8rEwNXv3czukalo8VtJH8ksIkZXr3Q3VYudZLkCsDd4Wku120uF02hYK25XGPorw==} resolution: {integrity: sha512-utI1ONF6uf/pPNO68kmN1b8rEwNXv3czukalo8VtJH8ksIkZXr3Q3VYudZLkCsDd4Wku120uF02hYK25XGPorw==}
peerDependencies: peerDependencies:
tailwindcss: '>=3.0.0 || >= 3.0.0-alpha.1 || >= 4.0.0-alpha.20 || >= 4.0.0-beta.1' tailwindcss: '>=3.0.0 || >= 3.0.0-alpha.1 || >= 4.0.0-alpha.20 || >= 4.0.0-beta.1'
'@tanstack/virtual-core@3.13.2':
resolution: {integrity: sha512-Qzz4EgzMbO5gKrmqUondCjiHcuu4B1ftHb0pjCut661lXZdGoHeze9f/M8iwsK1t5LGR6aNuNGU7mxkowaW6RQ==}
'@tanstack/vue-virtual@3.13.2':
resolution: {integrity: sha512-z4swzjdhzCh95n9dw9lTvw+t3iwSkYRlVkYkra3C9mul/m5fTzHR7KmtkwH4qXMTXGJUbngtC/bz2cHQIHkO8g==}
peerDependencies:
vue: ^2.7.0 || ^3.0.0
'@types/estree@1.0.6': '@types/estree@1.0.6':
resolution: {integrity: sha512-AYnb1nQyY49te+VRAVgmzfcgjYS91mY5P0TKUDCLEM+gNnA+3T6rWITXRLYCpahpqSQbN5cE+gHpnPyXjHWxcw==} resolution: {integrity: sha512-AYnb1nQyY49te+VRAVgmzfcgjYS91mY5P0TKUDCLEM+gNnA+3T6rWITXRLYCpahpqSQbN5cE+gHpnPyXjHWxcw==}
'@types/web-bluetooth@0.0.20':
resolution: {integrity: sha512-g9gZnnXVq7gM7v3tJCWV/qw7w+KeOlSHAhgF9RytFyifW6AF61hdT2ucrYhPq9hLs5JIryeupHV3qGk95dH9ow==}
'@vitejs/plugin-vue@5.2.1': '@vitejs/plugin-vue@5.2.1':
resolution: {integrity: sha512-cxh314tzaWwOLqVes2gnnCtvBDcM1UMdn+iFR+UjAn411dPT3tOmqrJjbMd7koZpMAmBM/GqeV4n9ge7JSiJJQ==} resolution: {integrity: sha512-cxh314tzaWwOLqVes2gnnCtvBDcM1UMdn+iFR+UjAn411dPT3tOmqrJjbMd7koZpMAmBM/GqeV4n9ge7JSiJJQ==}
engines: {node: ^18.0.0 || >=20.0.0} engines: {node: ^18.0.0 || >=20.0.0}
@@ -448,6 +495,24 @@ packages:
'@vue/shared@3.5.13': '@vue/shared@3.5.13':
resolution: {integrity: sha512-/hnE/qP5ZoGpol0a5mDi45bOd7t3tjYJBjsgCsivow7D48cJeV5l05RD82lPqi7gRiphZM37rnhW1l6ZoCNNnQ==} resolution: {integrity: sha512-/hnE/qP5ZoGpol0a5mDi45bOd7t3tjYJBjsgCsivow7D48cJeV5l05RD82lPqi7gRiphZM37rnhW1l6ZoCNNnQ==}
'@vueuse/core@10.11.1':
resolution: {integrity: sha512-guoy26JQktXPcz+0n3GukWIy/JDNKti9v6VEMu6kV2sYBsWuGiTU8OWdg+ADfUbHg3/3DlqySDe7JmdHrktiww==}
'@vueuse/core@12.7.0':
resolution: {integrity: sha512-jtK5B7YjZXmkGNHjviyGO4s3ZtEhbzSgrbX+s5o+Lr8i2nYqNyHuPVOeTdM1/hZ5Tkxg/KktAuAVDDiHMraMVA==}
'@vueuse/metadata@10.11.1':
resolution: {integrity: sha512-IGa5FXd003Ug1qAZmyE8wF3sJ81xGLSqTqtQ6jaVfkeZ4i5kS2mwQF61yhVqojRnenVew5PldLyRgvdl4YYuSw==}
'@vueuse/metadata@12.7.0':
resolution: {integrity: sha512-4VvTH9mrjXqFN5LYa5YfqHVRI6j7R00Vy4995Rw7PQxyCL3z0Lli86iN4UemWqixxEvYfRjG+hF9wL8oLOn+3g==}
'@vueuse/shared@10.11.1':
resolution: {integrity: sha512-LHpC8711VFZlDaYUXEBbFBCQ7GS3dVU9mjOhhMhXP6txTV4EhYQg/KGnQuvt/sPAtoUKq7VVUnL6mVtFoL42sA==}
'@vueuse/shared@12.7.0':
resolution: {integrity: sha512-coLlUw2HHKsm7rPN6WqHJQr18WymN4wkA/3ThFaJ4v4gWGWAQQGK+MJxLuJTBs4mojQiazlVWAKNJNpUWGRkNw==}
alien-signals@0.4.14: alien-signals@0.4.14:
resolution: {integrity: sha512-itUAVzhczTmP2U5yX67xVpsbbOiquusbWVyA9N+sy6+r6YVbFkahXvNCeEPWEOMhwDYwbVbGHFkVL03N9I5g+Q==} resolution: {integrity: sha512-itUAVzhczTmP2U5yX67xVpsbbOiquusbWVyA9N+sy6+r6YVbFkahXvNCeEPWEOMhwDYwbVbGHFkVL03N9I5g+Q==}
@@ -477,6 +542,10 @@ packages:
arg@5.0.2: arg@5.0.2:
resolution: {integrity: sha512-PYjyFOLKQ9y57JvQ6QLo8dAgNqswh8M1RMJYdQduT6xbWSgK36P/Z/v+p888pM69jMMfS8Xd8F6I1kQ/I9HUGg==} resolution: {integrity: sha512-PYjyFOLKQ9y57JvQ6QLo8dAgNqswh8M1RMJYdQduT6xbWSgK36P/Z/v+p888pM69jMMfS8Xd8F6I1kQ/I9HUGg==}
aria-hidden@1.2.4:
resolution: {integrity: sha512-y+CcFFwelSXpLZk/7fMB2mUbGtX9lKycf1MWJ7CaTIERyitVlyQx6C+sxcROU2BAJ24OiZyK+8wj2i8AlBoS3A==}
engines: {node: '>=10'}
asynckit@0.4.0: asynckit@0.4.0:
resolution: {integrity: sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==} resolution: {integrity: sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==}
@@ -588,6 +657,9 @@ packages:
resolution: {integrity: sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A==} resolution: {integrity: sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A==}
engines: {node: '>=0.10.0'} engines: {node: '>=0.10.0'}
defu@6.1.4:
resolution: {integrity: sha512-mEQCMmwJu317oSz8CwdIOdwf3xMif1ttiM8LTufzc3g6kR+9Pe236twL8j3IYT1F7GfRgGcW6MWxzZjLIkuHIg==}
delayed-stream@1.0.0: delayed-stream@1.0.0:
resolution: {integrity: sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==} resolution: {integrity: sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==}
engines: {node: '>=0.4.0'} engines: {node: '>=0.4.0'}
@@ -642,6 +714,9 @@ packages:
estree-walker@2.0.2: estree-walker@2.0.2:
resolution: {integrity: sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==} resolution: {integrity: sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==}
fast-deep-equal@3.1.3:
resolution: {integrity: sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==}
fast-glob@3.3.3: fast-glob@3.3.3:
resolution: {integrity: sha512-7MptL8U0cqcFdzIzwOTHoilX9x5BrNqye7Z/LuC7kCMRio1EMSyqRK3BEAUD7sXRq4iT4AzTVuZdhgQ2TCvYLg==} resolution: {integrity: sha512-7MptL8U0cqcFdzIzwOTHoilX9x5BrNqye7Z/LuC7kCMRio1EMSyqRK3BEAUD7sXRq4iT4AzTVuZdhgQ2TCvYLg==}
engines: {node: '>=8.6.0'} engines: {node: '>=8.6.0'}
@@ -762,6 +837,10 @@ packages:
resolution: {integrity: sha512-/imKNG4EbWNrVjoNC/1H5/9GFy+tqjGBHCaSsN+P2RnPqjsLmv6UD3Ej+Kj8nBWaRAwyk7kK5ZUc+OEatnTR3A==} resolution: {integrity: sha512-/imKNG4EbWNrVjoNC/1H5/9GFy+tqjGBHCaSsN+P2RnPqjsLmv6UD3Ej+Kj8nBWaRAwyk7kK5ZUc+OEatnTR3A==}
hasBin: true hasBin: true
laravel-echo@2.0.2:
resolution: {integrity: sha512-Ciai6hA7r35MFqNRb8G034cvm9WiveSTFQQKRGJhWtZGbng7C8BBa5QvqDxk/Mw5GeJ+q19jrEwQhf7r1b1lcg==}
engines: {node: '>=20'}
laravel-vite-plugin@1.2.0: laravel-vite-plugin@1.2.0:
resolution: {integrity: sha512-R0pJ+IcTVeqEMoKz/B2Ij57QVq3sFTABiFmb06gAwFdivbOgsUtuhX6N2MGLEArajrS3U5JbberzwOe7uXHMHQ==} resolution: {integrity: sha512-R0pJ+IcTVeqEMoKz/B2Ij57QVq3sFTABiFmb06gAwFdivbOgsUtuhX6N2MGLEArajrS3U5JbberzwOe7uXHMHQ==}
engines: {node: ^18.0.0 || ^20.0.0 || >=22.0.0} engines: {node: ^18.0.0 || ^20.0.0 || >=22.0.0}
@@ -794,6 +873,11 @@ packages:
peerDependencies: peerDependencies:
react: ^16.5.1 || ^17.0.0 || ^18.0.0 || ^19.0.0 react: ^16.5.1 || ^17.0.0 || ^18.0.0 || ^19.0.0
lucide-vue-next@0.474.0:
resolution: {integrity: sha512-bQaSBjfJ33xiPQCxCf4JD3rcUgZFgWZzxSY8SScNa4Mcq2vWGlbvQx6icTL1UXRqsxzfoT13RXawePSmgg4iWw==}
peerDependencies:
vue: '>=3.0.1'
magic-string@0.30.17: magic-string@0.30.17:
resolution: {integrity: sha512-sNPKHvyjVf7gyjwS4xGTaW/mCnF8wnjtifKBEhxfZ7E/S8tQ0rssrwGNn6q8JH/ohItJfSQp9mBtQYuTlH5QnA==} resolution: {integrity: sha512-sNPKHvyjVf7gyjwS4xGTaW/mCnF8wnjtifKBEhxfZ7E/S8tQ0rssrwGNn6q8JH/ohItJfSQp9mBtQYuTlH5QnA==}
@@ -840,6 +924,11 @@ packages:
engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1} engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1}
hasBin: true hasBin: true
nanoid@5.1.2:
resolution: {integrity: sha512-b+CiXQCNMUGe0Ri64S9SXFcP9hogjAJ2Rd6GdVxhPLRm7mhGaM7VgOvCAJ1ZshfHbqVDI3uqTI5C8/GaKuLI7g==}
engines: {node: ^18 || >=20}
hasBin: true
node-releases@2.0.19: node-releases@2.0.19:
resolution: {integrity: sha512-xxOWJsBKtzAq7DY0J+DTzuz58K8e7sJbdgwkbMWQe8UYB6ekmsQ45q0M/tJDsGaZmbC+l7n57UV8Hl5tHxO9uw==} resolution: {integrity: sha512-xxOWJsBKtzAq7DY0J+DTzuz58K8e7sJbdgwkbMWQe8UYB6ekmsQ45q0M/tJDsGaZmbC+l7n57UV8Hl5tHxO9uw==}
@@ -939,6 +1028,9 @@ packages:
proxy-from-env@1.1.0: proxy-from-env@1.1.0:
resolution: {integrity: sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==} resolution: {integrity: sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==}
pusher-js@8.4.0:
resolution: {integrity: sha512-wp3HqIIUc1GRyu1XrP6m2dgyE9MoCsXVsWNlohj0rjSkLf+a0jLvEyVubdg58oMk7bhjBWnFClgp8jfAa6Ak4Q==}
qs@6.14.0: qs@6.14.0:
resolution: {integrity: sha512-YWWTjgABSKcvs/nWBi9PycY/JiPJqOD4JA6o9Sej2AtvSGarXxKC3OQSk4pAarbdQlKAh5D4FCQkJNkW+GAn3w==} resolution: {integrity: sha512-YWWTjgABSKcvs/nWBi9PycY/JiPJqOD4JA6o9Sej2AtvSGarXxKC3OQSk4pAarbdQlKAh5D4FCQkJNkW+GAn3w==}
engines: {node: '>=0.6'} engines: {node: '>=0.6'}
@@ -946,6 +1038,11 @@ packages:
queue-microtask@1.2.3: queue-microtask@1.2.3:
resolution: {integrity: sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==} resolution: {integrity: sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==}
radix-vue@1.9.16:
resolution: {integrity: sha512-xwkTfQ7Ub/0XmT40JDc3g03xuYqKIJzVKGazcIkk8mUksj/tbw1pcCVRP0e3hKvPHKeQ0cktI1MvRnlUwCRvoQ==}
peerDependencies:
vue: '>= 3.2.0'
react@19.0.0: react@19.0.0:
resolution: {integrity: sha512-V8AVnmPIICiWpGfm6GLzCR/W5FXLchHop40W4nXBmdlEceh16rCN8O8LNWm5bh5XUX91fh7KpA+W0TgMKmgTpQ==} resolution: {integrity: sha512-V8AVnmPIICiWpGfm6GLzCR/W5FXLchHop40W4nXBmdlEceh16rCN8O8LNWm5bh5XUX91fh7KpA+W0TgMKmgTpQ==}
engines: {node: '>=0.10.0'} engines: {node: '>=0.10.0'}
@@ -1217,6 +1314,9 @@ packages:
tslib@2.8.1: tslib@2.8.1:
resolution: {integrity: sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==} resolution: {integrity: sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==}
tweetnacl@1.0.3:
resolution: {integrity: sha512-6rt+RN7aOi1nGMyC4Xa5DdYiukl2UWCbcJft7YhxReBGQD7OAM8Pbxw6YMo4r2diNEA8FEmu32YOn9rhaiE5yw==}
typescript@5.7.3: typescript@5.7.3:
resolution: {integrity: sha512-84MVSjMEHP+FQRPy3pX9sTVV/INIex71s9TL2Gm5FG/WG1SqXeKyZ0k7/blY/4FdOzI12CBy1vGc4og/eus0fw==} resolution: {integrity: sha512-84MVSjMEHP+FQRPy3pX9sTVV/INIex71s9TL2Gm5FG/WG1SqXeKyZ0k7/blY/4FdOzI12CBy1vGc4og/eus0fw==}
engines: {node: '>=14.17'} engines: {node: '>=14.17'}
@@ -1280,6 +1380,17 @@ packages:
vscode-uri@3.0.8: vscode-uri@3.0.8:
resolution: {integrity: sha512-AyFQ0EVmsOZOlAnxoFOGOq1SQDWAB7C6aqMGS23svWAllfOaxbuFvcT8D1i8z3Gyn8fraVeZNNmN6e9bxxXkKw==} resolution: {integrity: sha512-AyFQ0EVmsOZOlAnxoFOGOq1SQDWAB7C6aqMGS23svWAllfOaxbuFvcT8D1i8z3Gyn8fraVeZNNmN6e9bxxXkKw==}
vue-demi@0.14.10:
resolution: {integrity: sha512-nMZBOwuzabUO0nLgIcc6rycZEebF6eeUfaiQx9+WSk8e29IbLvPU9feI6tqW4kTo3hvoYAJkMh8n8D0fuISphg==}
engines: {node: '>=12'}
hasBin: true
peerDependencies:
'@vue/composition-api': ^1.0.0-rc.1
vue: ^3.0.0-0 || ^2.6.0
peerDependenciesMeta:
'@vue/composition-api':
optional: true
vue-tsc@2.2.0: vue-tsc@2.2.0:
resolution: {integrity: sha512-gtmM1sUuJ8aSb0KoAFmK9yMxb8TxjewmxqTJ1aKphD5Cbu0rULFY6+UQT51zW7SpUcenfPUuflKyVwyx9Qdnxg==} resolution: {integrity: sha512-gtmM1sUuJ8aSb0KoAFmK9yMxb8TxjewmxqTJ1aKphD5Cbu0rULFY6+UQT51zW7SpUcenfPUuflKyVwyx9Qdnxg==}
hasBin: true hasBin: true
@@ -1418,6 +1529,26 @@ snapshots:
'@esbuild/win32-x64@0.24.2': '@esbuild/win32-x64@0.24.2':
optional: true optional: true
'@floating-ui/core@1.6.9':
dependencies:
'@floating-ui/utils': 0.2.9
'@floating-ui/dom@1.6.13':
dependencies:
'@floating-ui/core': 1.6.9
'@floating-ui/utils': 0.2.9
'@floating-ui/utils@0.2.9': {}
'@floating-ui/vue@1.1.6(vue@3.5.13(typescript@5.7.3))':
dependencies:
'@floating-ui/dom': 1.6.13
'@floating-ui/utils': 0.2.9
vue-demi: 0.14.10(vue@3.5.13(typescript@5.7.3))
transitivePeerDependencies:
- '@vue/composition-api'
- vue
'@inertiajs/core@2.0.3': '@inertiajs/core@2.0.3':
dependencies: dependencies:
axios: 1.7.9 axios: 1.7.9
@@ -1435,6 +1566,14 @@ snapshots:
transitivePeerDependencies: transitivePeerDependencies:
- debug - debug
'@internationalized/date@3.7.0':
dependencies:
'@swc/helpers': 0.5.15
'@internationalized/number@3.6.0':
dependencies:
'@swc/helpers': 0.5.15
'@isaacs/cliui@8.0.2': '@isaacs/cliui@8.0.2':
dependencies: dependencies:
string-width: 5.1.2 string-width: 5.1.2
@@ -1533,13 +1672,26 @@ snapshots:
'@rollup/rollup-win32-x64-msvc@4.32.1': '@rollup/rollup-win32-x64-msvc@4.32.1':
optional: true optional: true
'@swc/helpers@0.5.15':
dependencies:
tslib: 2.8.1
'@tailwindcss/forms@0.5.10(tailwindcss@3.4.17)': '@tailwindcss/forms@0.5.10(tailwindcss@3.4.17)':
dependencies: dependencies:
mini-svg-data-uri: 1.4.4 mini-svg-data-uri: 1.4.4
tailwindcss: 3.4.17 tailwindcss: 3.4.17
'@tanstack/virtual-core@3.13.2': {}
'@tanstack/vue-virtual@3.13.2(vue@3.5.13(typescript@5.7.3))':
dependencies:
'@tanstack/virtual-core': 3.13.2
vue: 3.5.13(typescript@5.7.3)
'@types/estree@1.0.6': {} '@types/estree@1.0.6': {}
'@types/web-bluetooth@0.0.20': {}
'@vitejs/plugin-vue@5.2.1(vite@6.0.11(jiti@1.21.7)(sass-embedded@1.83.4)(yaml@2.7.0))(vue@3.5.13(typescript@5.7.3))': '@vitejs/plugin-vue@5.2.1(vite@6.0.11(jiti@1.21.7)(sass-embedded@1.83.4)(yaml@2.7.0))(vue@3.5.13(typescript@5.7.3))':
dependencies: dependencies:
vite: 6.0.11(jiti@1.21.7)(sass-embedded@1.83.4)(yaml@2.7.0) vite: 6.0.11(jiti@1.21.7)(sass-embedded@1.83.4)(yaml@2.7.0)
@@ -1629,6 +1781,42 @@ snapshots:
'@vue/shared@3.5.13': {} '@vue/shared@3.5.13': {}
'@vueuse/core@10.11.1(vue@3.5.13(typescript@5.7.3))':
dependencies:
'@types/web-bluetooth': 0.0.20
'@vueuse/metadata': 10.11.1
'@vueuse/shared': 10.11.1(vue@3.5.13(typescript@5.7.3))
vue-demi: 0.14.10(vue@3.5.13(typescript@5.7.3))
transitivePeerDependencies:
- '@vue/composition-api'
- vue
'@vueuse/core@12.7.0(typescript@5.7.3)':
dependencies:
'@types/web-bluetooth': 0.0.20
'@vueuse/metadata': 12.7.0
'@vueuse/shared': 12.7.0(typescript@5.7.3)
vue: 3.5.13(typescript@5.7.3)
transitivePeerDependencies:
- typescript
'@vueuse/metadata@10.11.1': {}
'@vueuse/metadata@12.7.0': {}
'@vueuse/shared@10.11.1(vue@3.5.13(typescript@5.7.3))':
dependencies:
vue-demi: 0.14.10(vue@3.5.13(typescript@5.7.3))
transitivePeerDependencies:
- '@vue/composition-api'
- vue
'@vueuse/shared@12.7.0(typescript@5.7.3)':
dependencies:
vue: 3.5.13(typescript@5.7.3)
transitivePeerDependencies:
- typescript
alien-signals@0.4.14: {} alien-signals@0.4.14: {}
ansi-regex@5.0.1: {} ansi-regex@5.0.1: {}
@@ -1650,6 +1838,10 @@ snapshots:
arg@5.0.2: {} arg@5.0.2: {}
aria-hidden@1.2.4:
dependencies:
tslib: 2.8.1
asynckit@0.4.0: {} asynckit@0.4.0: {}
autoprefixer@10.4.20(postcss@8.5.1): autoprefixer@10.4.20(postcss@8.5.1):
@@ -1772,6 +1964,8 @@ snapshots:
deepmerge@4.3.1: {} deepmerge@4.3.1: {}
defu@6.1.4: {}
delayed-stream@1.0.0: {} delayed-stream@1.0.0: {}
didyoumean@1.2.2: {} didyoumean@1.2.2: {}
@@ -1834,6 +2028,8 @@ snapshots:
estree-walker@2.0.2: {} estree-walker@2.0.2: {}
fast-deep-equal@3.1.3: {}
fast-glob@3.3.3: fast-glob@3.3.3:
dependencies: dependencies:
'@nodelib/fs.stat': 2.0.5 '@nodelib/fs.stat': 2.0.5
@@ -1949,6 +2145,8 @@ snapshots:
jiti@1.21.7: {} jiti@1.21.7: {}
laravel-echo@2.0.2: {}
laravel-vite-plugin@1.2.0(vite@6.0.11(jiti@1.21.7)(sass-embedded@1.83.4)(yaml@2.7.0)): laravel-vite-plugin@1.2.0(vite@6.0.11(jiti@1.21.7)(sass-embedded@1.83.4)(yaml@2.7.0)):
dependencies: dependencies:
picocolors: 1.1.1 picocolors: 1.1.1
@@ -1971,6 +2169,10 @@ snapshots:
dependencies: dependencies:
react: 19.0.0 react: 19.0.0
lucide-vue-next@0.474.0(vue@3.5.13(typescript@5.7.3)):
dependencies:
vue: 3.5.13(typescript@5.7.3)
magic-string@0.30.17: magic-string@0.30.17:
dependencies: dependencies:
'@jridgewell/sourcemap-codec': 1.5.0 '@jridgewell/sourcemap-codec': 1.5.0
@@ -2008,6 +2210,8 @@ snapshots:
nanoid@3.3.8: {} nanoid@3.3.8: {}
nanoid@5.1.2: {}
node-releases@2.0.19: {} node-releases@2.0.19: {}
normalize-path@3.0.0: {} normalize-path@3.0.0: {}
@@ -2080,12 +2284,33 @@ snapshots:
proxy-from-env@1.1.0: {} proxy-from-env@1.1.0: {}
pusher-js@8.4.0:
dependencies:
tweetnacl: 1.0.3
qs@6.14.0: qs@6.14.0:
dependencies: dependencies:
side-channel: 1.1.0 side-channel: 1.1.0
queue-microtask@1.2.3: {} queue-microtask@1.2.3: {}
radix-vue@1.9.16(vue@3.5.13(typescript@5.7.3)):
dependencies:
'@floating-ui/dom': 1.6.13
'@floating-ui/vue': 1.1.6(vue@3.5.13(typescript@5.7.3))
'@internationalized/date': 3.7.0
'@internationalized/number': 3.6.0
'@tanstack/vue-virtual': 3.13.2(vue@3.5.13(typescript@5.7.3))
'@vueuse/core': 10.11.1(vue@3.5.13(typescript@5.7.3))
'@vueuse/shared': 10.11.1(vue@3.5.13(typescript@5.7.3))
aria-hidden: 1.2.4
defu: 6.1.4
fast-deep-equal: 3.1.3
nanoid: 5.1.2
vue: 3.5.13(typescript@5.7.3)
transitivePeerDependencies:
- '@vue/composition-api'
react@19.0.0: {} react@19.0.0: {}
read-cache@1.0.0: read-cache@1.0.0:
@@ -2368,6 +2593,8 @@ snapshots:
tslib@2.8.1: {} tslib@2.8.1: {}
tweetnacl@1.0.3: {}
typescript@5.7.3: {} typescript@5.7.3: {}
update-browserslist-db@1.1.2(browserslist@4.24.4): update-browserslist-db@1.1.2(browserslist@4.24.4):
@@ -2398,6 +2625,10 @@ snapshots:
vscode-uri@3.0.8: {} vscode-uri@3.0.8: {}
vue-demi@0.14.10(vue@3.5.13(typescript@5.7.3)):
dependencies:
vue: 3.5.13(typescript@5.7.3)
vue-tsc@2.2.0(typescript@5.7.3): vue-tsc@2.2.0(typescript@5.7.3):
dependencies: dependencies:
'@volar/typescript': 2.4.11 '@volar/typescript': 2.4.11
+1
View File
@@ -0,0 +1 @@
/home/ninluc/Documents/codage/DatBrowser/app/Browser/console
+1
View File
@@ -0,0 +1 @@
/home/ninluc/Documents/codage/DatBrowser/app/Browser/downloads
Binary file not shown.

Before

Width:  |  Height:  |  Size: 0 B

After

Width:  |  Height:  |  Size: 15 KiB

+1
View File
@@ -0,0 +1 @@
/home/ninluc/Documents/codage/DatBrowser/app/Browser/screenshots
+1
View File
@@ -0,0 +1 @@
/home/ninluc/Documents/codage/DatBrowser/app/Browser/source
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
Binary file not shown.

After

Width:  |  Height:  |  Size: 26 KiB

+5
View File
@@ -0,0 +1,5 @@
{
"/app.js": "/app.js?id=a04a99f77a55ffcecde23cd7304b481b",
"/app-dark.css": "/app-dark.css?id=1ea407db56c5163ae29311f1f38eb7b9",
"/app.css": "/app.css?id=de4c978567bfd90b38d186937dee5ccf"
}
+1 -1
View File
@@ -11,7 +11,7 @@ const jobs = ref<Job[]>([]);
async function fetchJobs() { async function fetchJobs() {
let jobsRaw = await httpApi<Job[]>("/jobs"); let jobsRaw = await httpApi<Job[]>("/jobs");
jobs.value = jobsRaw.sort((a, b) => new Date(b.created_at).getTime() - new Date(a.created_at).getTime()); jobs.value = jobsRaw.sort((a, b) => new Date(a.created_at).getTime() - new Date(b.created_at).getTime());
} }
onMounted(fetchJobs); onMounted(fetchJobs);
+1 -1
View File
@@ -11,7 +11,7 @@ defineProps<{
</script> </script>
<template> <template>
<Head title="Welcome" /> <Head :title="job.name" />
<JobCard :job="job" /> <JobCard :job="job" />
+14
View File
@@ -0,0 +1,14 @@
import Echo from 'laravel-echo';
import Pusher from 'pusher-js';
window.Pusher = Pusher;
window.Echo = new Echo({
broadcaster: 'reverb',
key: import.meta.env.VITE_REVERB_APP_KEY,
wsHost: import.meta.env.VITE_REVERB_HOST,
wsPort: import.meta.env.VITE_REVERB_PORT ?? 80,
wssPort: import.meta.env.VITE_REVERB_PORT ?? 443,
forceTLS: (import.meta.env.VITE_REVERB_SCHEME ?? 'https') === 'https',
enabledTransports: ['ws', 'wss'],
});
+4
View File
@@ -0,0 +1,4 @@
<?php
use Illuminate\Support\Facades\Broadcast;
+14 -1
View File
@@ -1,7 +1,8 @@
<?php <?php
use App\Browser\Jobs\EpicGames\EpicGamesJob;
use App\Browser\Jobs\Hellcase\HellcaseJob; use App\Browser\Jobs\Hellcase\HellcaseJob;
use App\Models\Job; use App\Jobs\PruneOldJobRuns;
use App\Services\BrowserJobsInstances; use App\Services\BrowserJobsInstances;
use Illuminate\Foundation\Inspiring; use Illuminate\Foundation\Inspiring;
use Illuminate\Support\Facades\Artisan; use Illuminate\Support\Facades\Artisan;
@@ -10,5 +11,17 @@ Artisan::command('inspire', function () {
$this->comment(Inspiring::quote()); $this->comment(Inspiring::quote());
})->purpose('Display an inspiring quote'); })->purpose('Display an inspiring quote');
// Telescope
Schedule::command('telescope:prune')->monthly();
// Prune old job runs
Schedule::job(new PruneOldJobRuns)->monthly()->onOneServer()->withoutOverlapping()->name('prune-old-job-runs')->description('Prune old job runs')->skip(function () {
return !config('jobs.pruneOldJobRuns.enabled');
});
// Jobs
Schedule::job(new HellcaseJob)->daily()->onOneServer()->withoutOverlapping()->name('hellcase')->description('Hellcase job'); Schedule::job(new HellcaseJob)->daily()->onOneServer()->withoutOverlapping()->name('hellcase')->description('Hellcase job');
// Schedule::job(new HellcaseJob)->everyMinute()->onOneServer()->withoutOverlapping()->name('hellcase')->description('Hellcase job'); // Schedule::job(new HellcaseJob)->everyMinute()->onOneServer()->withoutOverlapping()->name('hellcase')->description('Hellcase job');
Schedule::job(new EpicGamesJob())->daily()->onOneServer()->withoutOverlapping()->name('epic-games')->description('Epic Games job');
+20
View File
@@ -0,0 +1,20 @@
# TODO
- Fix hellcase, fermer lespopups à chaque nouvelle visite
- Voir si le scheduler fonctionne au démmarage
- Mettre un timeout pour pas overwhelm le pc au démmarage
- Image pour le join de giveaway
- → Notification
- Ou ajouter des images base64 dans les jobRun
- Risque de devenir volumineux
- Sauf avec le job qui enlève les vieilles jobRun
- Notification live websocket
- Websocket installé
- Serveur php plus propre (nginx, apache, n'importe)
- Epic games
## Pour deploy Lama
- Version Lama du compose
- Tuto installation
Binary file not shown.
+20 -1
View File
@@ -1 +1,20 @@
sudo docker run --rm -it -p 3389:3389 -v ./undetectedChromedriver:/root/.local/share/undetected_chromedriver/ ultrafunk/undetected-chromedriver:latest #!/bin/bash
# From undetected chromedriver docker
#sudo docker run --rm -it -p 3389:3389 -v ./undetectedChromedriver:/root/.local/share/undetected_chromedriver/ ultrafunk/undetected-chromedriver:latest
# With undetected chromedriver patcher
# Run the selenium/standalone-chrome:latest with a specific container name in the background
sudo docker run -d --name standalone-chrome selenium/standalone-chrome:latest
sleep 5
# Copy the chromedriver binary from the container to the host
sudo docker cp -L standalone-chrome:/bin/chromedriver ./chromedriver
# Stop the container
sudo docker stop standalone-chrome
sudo chmod 777 ./chromedriver
# Patch the chromedriver binary
python3 ./patchChromedriver.py
@@ -0,0 +1,8 @@
#!/bin/python3
import undetected_chromedriver as uc
options = uc.ChromeOptions()
# Chromedriver is in current directory
driver = uc.Chrome(options = options, browser_executable_path="/usr/bin/google-chrome", driver_executable_path="/home/ninluc/Documents/codage/DatBrowser/undetectedChromedriver/chromedriver")
driver.get('https://nowsecure.nl')
@@ -1,6 +1,7 @@
FROM selenium/standalone-chrome:108.0 AS final # FROM selenium/standalone-chrome:108.0 AS final
FROM selenium/standalone-chrome:latest AS final
COPY undetectedChromedriver/chromedriver-linux /bin/chromedriver COPY undetectedChromedriver/chromedriver /bin/chromedriver
RUN mkdir -p /home/seluser/profile/ RUN mkdir -p /home/seluser/profile/
ENV TZ=Europe/Brussels ENV TZ=Europe/Brussels