Add new img size

Fix update generation status
This commit is contained in:
Knah Tsaeb 2024-03-15 12:17:10 +01:00
parent 5a89cdb205
commit 05024c8065
11 changed files with 427 additions and 57 deletions

View file

@ -23,7 +23,23 @@ class Backend {
private $title = 'Settings'; private $title = 'Settings';
private $passwordRequired = false; private $passwordRequired = false;
public function index($params, $conf) { /**
* Handles the index action for the controller.
*
* This method performs various actions based on the provided parameters and
* configuration. It checks if the user is logged in, sets the page to display,
* checks if a job is running, and handles displaying images. It sets the
* configuration and parameters for the object. If the page is set to 'settings',
* it handles first run installation and option settings. Finally, it generates
* the HTML content for the page by requiring the navigation, infos or settings,
* and footer templates.
*
* @param object $params The parameters object.
* @param object $conf The configuration object.
*
* @return string The generated HTML content for the page.
*/
public function index(object $params, object $conf): string {
if (isset($params->loginPassword)) { if (isset($params->loginPassword)) {
if (!Login::login($params->loginPassword, $conf->password)) { if (!Login::login($params->loginPassword, $conf->password)) {
$content = $this->showLogin(); $content = $this->showLogin();
@ -79,6 +95,17 @@ class Backend {
return $content; return $content;
} }
/**
* Displays information about the generated data.
*
* This method sets the start and end index for the data to display based on the
* provided parameters. It retrieves the data list, total count, error count, and
* queue count from the `DataBase` class. It calculates the start, maximum, next,
* and previous index values for pagination. It then requires the 'infos.php'
* template to display the information.
*
* @return void
*/
private function showInfos() { private function showInfos() {
if (!empty($this->params->start)) { if (!empty($this->params->start)) {
$this->start = $this->params->start; $this->start = $this->params->start;
@ -109,6 +136,17 @@ class Backend {
require __DIR__ . '/../../tpl/infos.php'; require __DIR__ . '/../../tpl/infos.php';
} }
/**
* Displays the settings page.
*
* This method sets the start and end index for the data to display based on the
* provided parameters. It retrieves the data list and total count from the
* `DataBase` class. It calculates the start and maximum index values for
* pagination. It generates a CSRF token using the `Page::genToken` method. It
* then requires the 'settings.php' template to display the settings page.
*
* @return void
*/
private function showSettings() { private function showSettings() {
if (!empty($this->params->start)) { if (!empty($this->params->start)) {
$this->start = $this->params->start; $this->start = $this->params->start;
@ -131,7 +169,23 @@ class Backend {
require __DIR__ . '/../../tpl/settings.php'; require __DIR__ . '/../../tpl/settings.php';
} }
private function setOption($post) { /**
* Sets and saves user configuration options.
*
* This method checks if the configuration file exists and creates an empty one if
* it doesn't. It then loads the user configuration from the file using the `Config`
* class. It sets various configuration options based on the provided `$post`
* parameter, such as server settings, logging, PDF generation, icon size, cache
* expiration, maximum generations per batch, permit types, file format, password,
* key, and Chrome path. It saves the updated configuration to the file using the
* `Config` class. Finally, it loads the updated configuration from the file and
* returns it as an object.
*
* @param object $post The POST data containing the configuration options.
*
* @return object The updated configuration object.
*/
private function setOption(object $post): object {
if (!file_exists(__DIR__ . '/../../datas/config.json')) { if (!file_exists(__DIR__ . '/../../datas/config.json')) {
file_put_contents(__DIR__ . '/../../datas/config.json', json_encode([])); file_put_contents(__DIR__ . '/../../datas/config.json', json_encode([]));
unset($_SESSION['login']); unset($_SESSION['login']);
@ -207,7 +261,16 @@ class Backend {
return (object)$newConfig->all(); return (object)$newConfig->all();
} }
private function getInQueue() { /**
* Gets the number of files in the queue directory.
*
* This method uses the `glob` function to search for JSON files in the queue
* directory. If any files are found, it returns the count of files. Otherwise,
* it returns 0.
*
* @return int The number of files in the queue directory.
*/
private function getInQueue(): int {
if (glob(__DIR__ . '/../../cache/queue/*.json') != false) { if (glob(__DIR__ . '/../../cache/queue/*.json') != false) {
$fileCount = count(glob(__DIR__ . '/../../cache/queue/*.json')); $fileCount = count(glob(__DIR__ . '/../../cache/queue/*.json'));
} else { } else {
@ -216,7 +279,16 @@ class Backend {
return $fileCount; return $fileCount;
} }
private function showLogin() { /**
* Displays the login page.
*
* This method generates a CSRF token using the `Page::genToken` method. It then
* requires the 'login.php' template to display the login page. Finally, it returns
* the generated HTML content as a string.
*
* @return string The generated HTML content for the login page.
*/
private function showLogin(): string {
ob_start(); ob_start();
$token = Page::genToken(); $token = Page::genToken();
require_once __DIR__ . '/../../tpl/login.php'; require_once __DIR__ . '/../../tpl/login.php';

View file

@ -5,6 +5,8 @@ namespace App\DataBase;
use Exception; use Exception;
use PDO; use PDO;
use function App\Soshot\n_print as SoshotN_print;
if (!function_exists('n_print')) { if (!function_exists('n_print')) {
function n_print($data, $name = '') { function n_print($data, $name = '') {
print_r($data, 1); print_r($data, 1);
@ -21,6 +23,7 @@ class DataBase {
'complete' => '', 'complete' => '',
'full' => '', 'full' => '',
'hd' => '', 'hd' => '',
'nhd' => '',
'thumb' => '', 'thumb' => '',
'fav' => '', 'fav' => '',
'og' => '', 'og' => '',
@ -28,12 +31,27 @@ class DataBase {
'created' => '' 'created' => ''
]; ];
/**
* Constructs a new instance of the DataBase class.
*
* This method creates a new SQLite database connection and sets the default fetch
* mode to PDO::FETCH_ASSOC. It also sets the error mode to PDO::ERRMODE_EXCEPTION.
* If the database file does not exist, it creates a new table named 'soshot' with
* the specified schema. If the $params parameter is not empty, the setParams()
* method is called to set the object's properties.
*
* @param object $params An associative array of parameters to set the object's
* properties.
*
* @return DataBase The constructed DataBase object.
*/
function __construct($params = null) { function __construct($params = null) {
try { try {
if (!file_exists($this->dataBase)) { if (!file_exists($this->dataBase)) {
$this->db = new PDO('sqlite:' . $this->dataBase); $this->db = new PDO('sqlite:' . $this->dataBase);
$this->db->setAttribute(PDO::ATTR_DEFAULT_FETCH_MODE, PDO::FETCH_ASSOC); $this->db->setAttribute(PDO::ATTR_DEFAULT_FETCH_MODE, PDO::FETCH_ASSOC);
$this->db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); // ERRMODE_WARNING | ERRMODE_EXCEPTION | ERRMODE_SILENT $this->db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION, PDO::ERRMODE_WARNING); // ERRMODE_WARNING | ERRMODE_EXCEPTION | ERRMODE_SILENT
$this->db->query("CREATE TABLE IF NOT EXISTS soshot ( $this->db->query("CREATE TABLE IF NOT EXISTS soshot (
id string PRIMARY KEY NOT NULL, id string PRIMARY KEY NOT NULL,
@ -41,6 +59,7 @@ class DataBase {
complete tinyint, complete tinyint,
full tinyint, full tinyint,
hd tinyint, hd tinyint,
nhd tinuyint,
thumb tinyint, thumb tinyint,
fav tinyint, fav tinyint,
og tinyint, og tinyint,
@ -51,6 +70,8 @@ class DataBase {
$this->db = new PDO('sqlite:' . $this->dataBase); $this->db = new PDO('sqlite:' . $this->dataBase);
$this->db->setAttribute(PDO::ATTR_DEFAULT_FETCH_MODE, PDO::FETCH_ASSOC); $this->db->setAttribute(PDO::ATTR_DEFAULT_FETCH_MODE, PDO::FETCH_ASSOC);
$this->db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); // ERRMODE_WARNING | ERRMODE_EXCEPTION | ERRMODE_SILENT $this->db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); // ERRMODE_WARNING | ERRMODE_EXCEPTION | ERRMODE_SILENT
$this->updateTable();
} }
} catch (Exception $e) { } catch (Exception $e) {
echo $e->getMessage(); echo $e->getMessage();
@ -63,7 +84,37 @@ class DataBase {
return $this; return $this;
} }
public function setParams($params) {
public function updateTable() {
$stmt = $this->db->prepare("SELECT * FROM soshot LIMIT 1;");
$stmt->execute();
$existingColumns = $stmt->fetch(PDO::FETCH_ASSOC);
if (empty($existingColumns)) {
return true;
}
$existingColumns = array_keys($existingColumns);
$newColumns = array_diff(array_keys($this->params), $existingColumns);
foreach ($newColumns as $column) {
$sql = "ALTER TABLE soshot ADD `{$column}` tinyint";
$this->db->exec($sql);
}
}
/**
* Sets the parameters for the database query.
*
* This method takes an object containing the parameters for the database query and
* sets the corresponding properties of the object.
*
* @param object $params An object containing the parameters for the database query.
*
* @return void
*/
public function setParams(object $params) {
$this->params = (object)$this->params; $this->params = (object)$this->params;
$this->params->id = $params->hmac; $this->params->id = $params->hmac;
$this->params->url = $params->url; $this->params->url = $params->url;
@ -72,7 +123,21 @@ class DataBase {
$this->params = $this->params; $this->params = $this->params;
} }
public function addUpdate($update, $type = '') { /**
* Adds or updates a record in the database.
*
* This method takes an update value and an optional type parameter. If the type
* parameter is not empty, it sets the type property of the object. It then checks
* if a record with the same ID already exists in the database using the testExit
* method. If a record exists, it calls the update method to update the existing
* record. If no record exists, it calls the insert method to insert a new record.
*
* @param int $update The update value to be inserted or updated in the database.
* @param string $type The type of the update.
*
* @return void
*/
public function addUpdate(int $update, string $type = '') {
if (!empty($type)) { if (!empty($type)) {
$this->params->type = $type; $this->params->type = $type;
} }
@ -83,7 +148,17 @@ class DataBase {
} }
} }
public function insert($update) { /**
* Inserts a new record into the database.
*
* This method prepares an SQL INSERT statement using the provided parameters, and
* executes it to insert a new record into the "soshot" table in the database.
*
* @param int $update The value to insert into the type column of the new record.
*
* @return void
*/
public function insert(int $update) {
$stmt = $this->db->prepare("INSERT INTO soshot (id, url, " . $this->params->type . ", created) VALUES $stmt = $this->db->prepare("INSERT INTO soshot (id, url, " . $this->params->type . ", created) VALUES
(:id, :url, :" . $this->params->type . ", :created)"); (:id, :url, :" . $this->params->type . ", :created)");
//$stmt->debugDumpParams(); //$stmt->debugDumpParams();
@ -96,7 +171,17 @@ class DataBase {
)); ));
} }
private function update($update) { /**
* Updates a record in the database.
*
* This method prepares an SQL UPDATE statement using the provided parameters, and
* executes it to update a record in the "soshot" table in the database.
*
* @param string $update The value to update in the type column of the record.
*
* @return void
*/
private function update(string $update) {
$stmt = $this->db->prepare("UPDATE soshot $stmt = $this->db->prepare("UPDATE soshot
SET " . $this->params->type . "=:" . $this->params->type . " SET " . $this->params->type . "=:" . $this->params->type . "
WHERE id=:id;"); WHERE id=:id;");
@ -105,10 +190,20 @@ class DataBase {
':' . $this->params->type => $update, ':' . $this->params->type => $update,
':id' => $this->params->id ':id' => $this->params->id
]); ]);
//$stmt->debugDumpParams();
} }
private function testExit($id) { /**
* Checks if a record with the given ID exists in the database.
*
* This method prepares an SQL SELECT statement using the provided ID, and executes
* it to retrieve the corresponding record from the "soshot" table in the database.
* If a record is found, the method returns true. Otherwise, it returns false.
*
* @param string $id The ID of the record to check.
*
* @return bool True if a record with the given ID exists in the database, false otherwise.
*/
private function testExit(string $id): bool {
$stmt = $this->db->prepare("SELECT id FROM soshot WHERE id=:id LIMIT 1;"); $stmt = $this->db->prepare("SELECT id FROM soshot WHERE id=:id LIMIT 1;");
$stmt->execute(array(':id' => $id)); $stmt->execute(array(':id' => $id));
$result = $stmt->fetchAll(PDO::FETCH_OBJ); $result = $stmt->fetchAll(PDO::FETCH_OBJ);
@ -118,18 +213,35 @@ class DataBase {
return false; return false;
} }
public function getTotal() { /**
* Retrieves the total number of records in the "soshot" table.
*
* This method prepares an SQL SELECT statement to retrieve the total number of
* records in the "soshot" table, executes the statement, and returns the result.
*
* @return int The total number of records in the "soshot" table.
*/
public function getTotal(): int {
$stmt = $this->db->prepare("SELECT COUNT(id) AS nb FROM soshot;"); $stmt = $this->db->prepare("SELECT COUNT(id) AS nb FROM soshot;");
$stmt->execute(); $stmt->execute();
$result = $stmt->fetch(); $result = $stmt->fetch();
return $result['nb']; return $result['nb'];
} }
public function getInError() { /**
* Retrieves the number of records with errors in the "soshot" table.
*
* This method prepares an SQL SELECT statement to retrieve the number of records
* with errors in the "soshot" table, executes the statement, and returns the result.
*
* @return int The number of records with errors in the "soshot" table.
*/
public function getInError(): int {
$stmt = $this->db->prepare("SELECT COUNT(DISTINCT id) AS nb FROM soshot WHERE $stmt = $this->db->prepare("SELECT COUNT(DISTINCT id) AS nb FROM soshot WHERE
complete = 2 OR complete = 2 OR
full = 2 OR full = 2 OR
hd = 2 OR hd = 2 OR
nhd = 2 OR
thumb = 2 OR thumb = 2 OR
fav = 2 OR fav = 2 OR
og = 2 OR og = 2 OR
@ -139,7 +251,20 @@ class DataBase {
return $result['nb']; return $result['nb'];
} }
public function getList($start, $end) { /**
* Retrieves a list of records from the "soshot" table.
*
* This method prepares an SQL SELECT statement to retrieve a list of records from
* the "soshot" table, based on the specified start and end indices, orders the
* results by the "created" column in descending order, executes the statement, and
* returns the result set as an array of objects.
*
* @param int $start The starting index of the record to retrieve.
* @param int $end The ending index of the record to retrieve.
*
* @return array An array of objects representing the records in the "soshot" table.
*/
public function getList(int $start, int $end) {
$stmt = $this->db->prepare("SELECT * FROM soshot ORDER BY created DESC limit :start, :end;"); $stmt = $this->db->prepare("SELECT * FROM soshot ORDER BY created DESC limit :start, :end;");
$stmt->execute(array(':start' => $start, ':end' => $end)); $stmt->execute(array(':start' => $start, ':end' => $end));
$result = $stmt->fetchAll(PDO::FETCH_OBJ); $result = $stmt->fetchAll(PDO::FETCH_OBJ);

View file

@ -9,6 +9,18 @@ use Zebra_Image;
class GetFav extends GetThumb { class GetFav extends GetThumb {
/**
* Creates a favicon for a given URL.
*
* This method takes the URL provided in the `demande` object and uses the Embed
* library to extract the favicon or icon from the website. If the favicon or icon
* cannot be extracted, a default error image is used. The favicon is then resized
* to the specified size and saved to the specified file path. If the favicon is in
* ICO or SVG format, it is converted to PNG format using the ConvertIco class. The
* method updates the database with the status of the favicon creation.
*
* @return bool True if the favicon was successfully created, false otherwise.
*/
public function makeFavicon() { public function makeFavicon() {
if (!is_dir($this->filePath)) { if (!is_dir($this->filePath)) {
@ -22,18 +34,18 @@ class GetFav extends GetThumb {
if (!is_null($info->favicon)) { if (!is_null($info->favicon)) {
if (!$favicon = @file_get_contents($info->favicon)) { if (!$favicon = @file_get_contents($info->favicon)) {
copy(__DIR__ . '/../../src/images/error_fav.' . $this->fileFormat, $this->demande->requestImg); copy(__DIR__ . '/../../src/images/error_fav.' . $this->fileFormat, $this->demande->requestImg);
$this->db->addUpdate(2); $this->db->addUpdate(2, $this->type);
return true; return true;
} }
} elseif (!is_null($info->icon)) { } elseif (!is_null($info->icon)) {
if (!$favicon = @file_get_contents($info->icon)) { if (!$favicon = @file_get_contents($info->icon)) {
copy(__DIR__ . '/../../src/images/error_fav.' . $this->fileFormat, $this->demande->requestImg); copy(__DIR__ . '/../../src/images/error_fav.' . $this->fileFormat, $this->demande->requestImg);
$this->db->addUpdate(2); $this->db->addUpdate(2, $this->type);
return true; return true;
} }
} else { } else {
copy(__DIR__ . '/../../src/images/error_fav.' . $this->fileFormat, $this->demande->requestImg); copy(__DIR__ . '/../../src/images/error_fav.' . $this->fileFormat, $this->demande->requestImg);
$this->db->addUpdate(2); $this->db->addUpdate(2, $this->type);
return true; return true;
} }
@ -56,27 +68,33 @@ class GetFav extends GetThumb {
$image->enlarge_smaller_images = false; $image->enlarge_smaller_images = false;
$image->resize($this->conf->icoSize, $this->conf->icoSize, ZEBRA_IMAGE_CROP_TOPLEFT); $image->resize($this->conf->icoSize, $this->conf->icoSize, ZEBRA_IMAGE_CROP_TOPLEFT);
} catch (\Exception $e) { } catch (\Exception $e) {
$this->db->addUpdate(2); $this->db->addUpdate(2, $this->type);
copy(__DIR__ . '/../../src/images/error_fav.png', $this->demande->requestImg); copy(__DIR__ . '/../../src/images/error_fav.png', $this->demande->requestImg);
return true; return true;
} }
if (!is_file($this->demande->requestImg)) { if (!is_file($this->demande->requestImg)) {
copy(__DIR__ . '/../../src/images/error_fav.png', $this->demande->requestImg); copy(__DIR__ . '/../../src/images/error_fav.png', $this->demande->requestImg);
$this->db->addUpdate(2); $this->db->addUpdate(2, $this->type);
return true; return true;
} else { } else {
$this->db->addUpdate(1); $this->db->addUpdate(1, $this->type);
} }
} }
/**
* Displays the requested image.
*
* This method checks if the requested image file exists. If the requested image is
* a favicon and does not exist, it calls the makeFavicon method to generate it.
* Then, it sets the appropriate headers for the image and outputs its contents.
*
* @return void
*/
public function show() { public function show() {
if (!file_exists($this->requestImg) && $this->type === 'fav') { if (!file_exists($this->requestImg) && $this->type === 'fav') {
$this->makeFavicon(); $this->makeFavicon();
} }
//n_print($this);
//echo '<img src="data:image/png;base64,'.base64_encode(file_get_contents($this->requestImg)).'">'; //echo '<img src="data:image/png;base64,'.base64_encode(file_get_contents($this->requestImg)).'">';
header("Content-type: image/$this->fileFormat"); header("Content-type: image/$this->fileFormat");
header('Expires: ', gmdate('D, d M Y H:i:s', time()) . ' GMT'); header('Expires: ', gmdate('D, d M Y H:i:s', time()) . ' GMT');

View file

@ -8,6 +8,17 @@ use App\Utils\ConvertToPng;
class GetOg extends GetThumb { class GetOg extends GetThumb {
/**
* Generate the OG image for a given URL.
*
* This method retrieves the OG image from the provided URL using the Embed library.
* If the image cannot be retrieved, an error image is used instead. The image is
* then saved to the specified file path. If the image format is not PNG, it is
* converted to PNG using the ConvertToPng class. The method updates the database
* with the status of the OG image creation.
*
* @return bool True if the OG image was successfully created, false otherwise.
*/
public function makeOg() { public function makeOg() {
if (!is_dir($this->filePath)) { if (!is_dir($this->filePath)) {
@ -21,18 +32,18 @@ class GetOg extends GetThumb {
if (!is_null($info->image)) { if (!is_null($info->image)) {
if (!$image = file_get_contents($info->image)) { if (!$image = file_get_contents($info->image)) {
copy(__DIR__ . '/../../src/images/error_thumb.png', $this->demande->requestImg); copy(__DIR__ . '/../../src/images/error_thumb.png', $this->demande->requestImg);
$this->db->addUpdate(2); $this->db->addUpdate(2, $this->type);
return true; return true;
} }
} else { } else {
copy(__DIR__ . '/../../src/images/error_thumb.png', $this->demande->requestImg); copy(__DIR__ . '/../../src/images/error_thumb.png', $this->demande->requestImg);
$this->db->addUpdate(2); $this->db->addUpdate(2, $this->type);
return true; return true;
} }
if (empty($image)) { if (empty($image)) {
copy(__DIR__ . '/../../src/images/error_thumb.png', $this->demande->requestImg); copy(__DIR__ . '/../../src/images/error_thumb.png', $this->demande->requestImg);
$this->db->addUpdate(2); $this->db->addUpdate(2, $this->type);
return true; return true;
} }
@ -44,16 +55,25 @@ class GetOg extends GetThumb {
} }
} catch (\Exception $e) { } catch (\Exception $e) {
copy(__DIR__ . '/../../src/images/error_thumb.png', $this->demande->requestImg); copy(__DIR__ . '/../../src/images/error_thumb.png', $this->demande->requestImg);
$this->db->addUpdate(2); $this->db->addUpdate(2, $this->type);
} }
if (!is_file($this->demande->requestImg)) { if (!is_file($this->demande->requestImg)) {
copy(__DIR__ . '/../../src/images/error_thumb.png', $this->demande->requestImg); copy(__DIR__ . '/../../src/images/error_thumb.png', $this->demande->requestImg);
$this->db->addUpdate(2); $this->db->addUpdate(2, $this->type);
} else { } else {
$this->db->addUpdate(1); $this->db->addUpdate(1, $this->type);
} }
} }
/**
* Display the OG image for a given URL.
*
* This method checks if the OG image file exists and if the type is 'og'. If the
* file does not exist, it calls the makeOg() method to generate the OG image. It
* then sets the appropriate headers and outputs the contents of the OG image file.
*
* @return void
*/
public function show() { public function show() {
if (file_exists($this->requestImg) && $this->type === 'og') { if (file_exists($this->requestImg) && $this->type === 'og') {
} else { } else {

View file

@ -21,7 +21,21 @@ class GetThumb {
protected $demande; protected $demande;
protected $fileFormat; protected $fileFormat;
function __construct($params, $conf) { /**
* Constructs a new object.
*
* This method initializes the object properties based on the provided parameters
* and configuration. It first checks if the provided HMAC is valid using the
* Hmac class. If the HMAC is invalid, it returns an error message. It then sets
* the object properties for the request URL, HMAC, type, file format, file path,
* request image path, complete image path, and database connection.
*
* @param object $params The request parameters object containing the URL, HMAC, and type.
* @param object $conf The configuration object containing the file format and key.
*
* @return GetOg The constructed GetOg object.
*/
function __construct(object $params, object $conf) {
$hmac = new Hmac($conf->key); $hmac = new Hmac($conf->key);
$this->conf = $conf; $this->conf = $conf;
$this->receiveHmac = $params->hmac; $this->receiveHmac = $params->hmac;
@ -56,6 +70,17 @@ class GetThumb {
return $this; return $this;
} }
/**
* Display the requested image or PDF.
*
* This method checks if the requested file exists and serves it with the appropriate
* headers. If the requested file does not exist, it checks if a complete image exists
* and resizes it to the requested type. If neither the requested file nor a complete
* image exists, it adds a job to the queue to generate the requested image and serves
* a placeholder image.
*
* @return void
*/
public function show() { public function show() {
if ($this->type === 'pdf' && file_exists($this->requestImg)) { if ($this->type === 'pdf' && file_exists($this->requestImg)) {
header("Content-type:application/pdf"); header("Content-type:application/pdf");
@ -64,19 +89,19 @@ class GetThumb {
readfile($this->requestImg); readfile($this->requestImg);
echo file_get_contents($this->requestImg); echo file_get_contents($this->requestImg);
exit(); exit();
} else if (file_exists($this->requestImg) && in_array($this->type, ['complete', 'full', 'hd', 'thumb'])) { } else if (file_exists($this->requestImg) && in_array($this->type, ['complete', 'full', 'hd', 'nhd', 'thumb'])) {
header("Content-type: image/$this->fileFormat"); header("Content-type: image/$this->fileFormat");
header('Expires: ', gmdate('D, d M Y H:i:s', time()) . ' GMT'); header('Expires: ', gmdate('D, d M Y H:i:s', time()) . ' GMT');
echo file_get_contents($this->requestImg); echo file_get_contents($this->requestImg);
exit(); exit();
} }
if (file_exists($this->complete) && in_array($this->type, ['complete', 'full', 'hd', 'thumb'])) { if (file_exists($this->complete) && in_array($this->type, ['complete', 'full', 'hd', 'nhd', 'thumb'])) {
if (ResizeToDemande::makeDemande((object)[ if (ResizeToDemande::makeDemande((object)[
'complete' => $this->complete, 'complete' => $this->complete,
'filePath' => $this->requestImg, 'filePath' => $this->requestImg,
'type' => $this->type 'type' => $this->type
])) { ])) {
$this->db->addUpdate(1); $this->db->addUpdate(1, $this->type);
header("Content-type: image/$this->fileFormat"); header("Content-type: image/$this->fileFormat");
header('Expires: ', gmdate('D, d M Y H:i:s', time()) . ' GMT'); header('Expires: ', gmdate('D, d M Y H:i:s', time()) . ' GMT');
echo file_get_contents($this->requestImg); echo file_get_contents($this->requestImg);
@ -102,7 +127,7 @@ class GetThumb {
'type' => 'complete' 'type' => 'complete'
]; ];
$complete = new DataBase($completeDemande); $complete = new DataBase($completeDemande);
$complete->addUpdate(3); $complete->addUpdate(3, $this->type);
if ($this->conf->alwaysMakePdf === true) { if ($this->conf->alwaysMakePdf === true) {
$complete->addUpdate(3, 'pdf'); $complete->addUpdate(3, 'pdf');
@ -121,9 +146,16 @@ class GetThumb {
} }
} }
/**
* Add a JSON object to the queue file.
*
* @param string $json The JSON object to add to the queue file.
*
* @return void
*/
private function addQueue($json) { private function addQueue($json) {
$file = $this->queuePath . $this->receiveHmac . '.json'; $file = $this->queuePath . $this->receiveHmac . '.json';
$this->db->addUpdate(3); $this->db->addUpdate(3, $this->type);
if (!file_exists($file)) { if (!file_exists($file)) {
file_put_contents($file, $json); file_put_contents($file, $json);
} }

View file

@ -4,6 +4,7 @@ namespace App\Soshot;
use App\DataBase\DataBase; use App\DataBase\DataBase;
use App\Utils\ResizeToDemande; use App\Utils\ResizeToDemande;
use HeadlessChromium\Browser;
use HeadlessChromium\BrowserFactory; use HeadlessChromium\BrowserFactory;
use HeadlessChromium\Page; use HeadlessChromium\Page;
use HeadlessChromium\Exception\BrowserConnectionFailed; use HeadlessChromium\Exception\BrowserConnectionFailed;
@ -30,6 +31,17 @@ class MakeThumb {
private $chromePath = ''; private $chromePath = '';
private $tmpDir = '/tmp/chrome_soshot'; private $tmpDir = '/tmp/chrome_soshot';
/**
* Creates a new instance of the class.
*
* This method loads the default and user configuration files using the `Config`
* class. It sets the maximum number of generations per batch, the Chrome path, and
* the queue path. It then retrieves the list of JSON files in the queue directory
* and decodes their contents to populate the `$demandes` property. Finally, it
* initializes the `DataBase` object and assigns it to the `$db` property.
*
* @return void
*/
function __construct() { function __construct() {
$this->conf = (object)Config::load([__DIR__ . '/../../datas/config.default.json', '?' . __DIR__ . '/../../datas/config.json'])->all(); $this->conf = (object)Config::load([__DIR__ . '/../../datas/config.default.json', '?' . __DIR__ . '/../../datas/config.json'])->all();
@ -47,6 +59,27 @@ class MakeThumb {
$this->db = new DataBase(); $this->db = new DataBase();
} }
/**
* Processes the demands in the queue.
*
* This method iterates over the list of demands in the `$demandes` property.
* For each demand, it sets the parameters for the `DataBase` object, writes the HMAC
* to a temporary file, and checks if the demand is already complete.
*
* If the demand is complete and not a PDF, it resizes the image to the demanded size using the
* `ResizeToDemande` class.
*
* If the demand is not complete, it generates the complete image using the `makeComplete` method.
*
* In either case, it deletes the demand from the queue using the `deleteQueue` method and
* updates the database using the `addUpdate` method.
*
* Finally, it sets the `$open` property to `true` to indicate that the queue is open.
* If the `$open` property is `true`, it generates a complete
* image for all demands in the queue using the `makeComplete` method.
*
* @return void
*/
public function compute() { public function compute() {
foreach ($this->demandes as $demande) { foreach ($this->demandes as $demande) {
$this->db->setParams($demande); $this->db->setParams($demande);
@ -57,7 +90,7 @@ class MakeThumb {
if ($this->testComplete($demande->complete) && $demande->type !== 'pdf') { if ($this->testComplete($demande->complete) && $demande->type !== 'pdf') {
if (ResizeToDemande::makeDemande($demande)) { if (ResizeToDemande::makeDemande($demande)) {
$this->deleteQueue($demande->hmac); $this->deleteQueue($demande->hmac);
$this->db->addUpdate(1); $this->db->addUpdate(1, $demande->type);
} }
} else { } else {
$this->makeComplete($demande); $this->makeComplete($demande);
@ -67,7 +100,7 @@ class MakeThumb {
} }
} }
$this->deleteQueue($demande->hmac); $this->deleteQueue($demande->hmac);
$this->db->addUpdate(1); $this->db->addUpdate(1, $demande->type);
$completeDemande = (object)[ $completeDemande = (object)[
'hmac' => $demande->hmac, 'hmac' => $demande->hmac,
@ -75,7 +108,7 @@ class MakeThumb {
'type' => 'complete' 'type' => 'complete'
]; ];
$complete = new DataBase($completeDemande); $complete = new DataBase($completeDemande);
$complete->addUpdate(1); $complete->addUpdate(1, $demande->type);
} }
$this->open = true; $this->open = true;
@ -85,20 +118,70 @@ class MakeThumb {
} }
} }
private function deleteQueue($hmac) { /**
* Deletes a demand from the queue.
*
* This method takes an HMAC as a parameter and deletes the corresponding JSON file
* from the queue directory using the `unlink` function.
*
* @param string $hmac The HMAC of the demand to delete.
*
* @return void
*/
private function deleteQueue(string $hmac) {
if (file_exists($this->queuePath . $hmac . '.json')) { if (file_exists($this->queuePath . $hmac . '.json')) {
unlink($this->queuePath . $hmac . '.json'); unlink($this->queuePath . $hmac . '.json');
} }
} }
private function testComplete($complete) { /**
* Checks if a file exists.
*
* This method takes a file path as a parameter and checks if the file exists using
* the `file_exists` function. It returns `true` if the file exists, and `false`
* otherwise.
*
* @param string $complete The file path to check.
*
* @return bool `true` if the file exists, `false` otherwise.
*/
private function testComplete(string $complete): bool {
if (file_exists($complete)) { if (file_exists($complete)) {
return true; return true;
} }
return false; return false;
} }
private function makeComplete($demande, $close = false) { /**
* Generates a complete image or PDF for a demand.
*
* This method takes a demand object as a parameter and generates a complete image
* or PDF for the demand.
*
* If the `$close` parameter is set to `true`, it closes the browser and deletes the socket file.
* The method first checks if a socket file exists and connects to an existing browser if it does.
*
* If not, it creates a new browser instance using the `BrowserFactory` class.
*
* It then navigates to the URL specified in the demand and takes a screenshot of the page.
*
* If the demand type is 'pdf' or the `alwaysMakePdf` configuration option is set to `true`, it also
* generates a PDF of the page.
*
* Finally, it saves the screenshot and PDF to the appropriate file paths and
* updates the database using the `addUpdate` method.
*
* If an `OperationTimedOut` exception is thrown, it logs the error, closes the browser,
* deletes the socket file, copies an error image to the file path, and updates the
* database with an error status.
*
* @param object|null $demande The demand object containing the URL, HMAC, file path, and type of the demand.
* @param bool $close Whether to close the browser and delete the socket file after
* generating the complete image or PDF. Defaults to `false`.
*
* @return void
*/
private function makeComplete(object|null $demande, bool $close = false) {
if (file_exists($this->fileSocket)) { if (file_exists($this->fileSocket)) {
$socket = \file_get_contents($this->fileSocket); $socket = \file_get_contents($this->fileSocket);
try { try {
@ -170,7 +253,7 @@ class MakeThumb {
$this->db->addUpdate(1, 'pdf'); $this->db->addUpdate(1, 'pdf');
} }
} }
$this->db->addUpdate(1); $this->db->addUpdate(1, 'complete');
} catch (OperationTimedOut $e) { } catch (OperationTimedOut $e) {
// todo log // todo log
$socket = \file_get_contents($this->fileSocket); $socket = \file_get_contents($this->fileSocket);
@ -178,11 +261,20 @@ class MakeThumb {
$browser->close(); $browser->close();
unlink($this->fileSocket); unlink($this->fileSocket);
copy(__DIR__ . '/../../src/images/error_thumb.png', $demande->filePath); copy(__DIR__ . '/../../src/images/error_thumb.png', $demande->filePath);
$this->db->addUpdate(2); $this->db->addUpdate(2, $demande->type);
} }
} }
private function openBrowser() { /**
* Creates and opens a new browser instance.
*
* This method creates a new browser instance using the `BrowserFactory` class with
* the specified configuration options. It then saves the socket URI to a file and
* returns the browser instance.
*
* @return Browser The created browser instance.
*/
private function openBrowser(): Browser {
$factory = new BrowserFactory($this->chromePath); $factory = new BrowserFactory($this->chromePath);
// Mozilla/5.0 (compatible; Googlebot/2.1; +http://www.google.com/bot.html) // Mozilla/5.0 (compatible; Googlebot/2.1; +http://www.google.com/bot.html)

View file

@ -7,7 +7,6 @@ use Zebra_Image;
class ResizeToDemande { class ResizeToDemande {
static function makeDemande($demande) { static function makeDemande($demande) {
// todo add 640 360
$image = new Zebra_Image(); $image = new Zebra_Image();
$image->source_path = $demande->complete; $image->source_path = $demande->complete;
$image->target_path = $demande->filePath; $image->target_path = $demande->filePath;
@ -24,6 +23,11 @@ class ResizeToDemande {
return true; return true;
} }
if ($demande->type === 'nhd') {
$image->resize(640, 360, ZEBRA_IMAGE_CROP_TOPLEFT);
return true;
}
if ($demande->type === 'thumb') { if ($demande->type === 'thumb') {
$image->resize(160, 90, ZEBRA_IMAGE_CROP_TOPLEFT); $image->resize(160, 90, ZEBRA_IMAGE_CROP_TOPLEFT);
return true; return true;

View file

@ -47,6 +47,7 @@ if (!file_exists(__DIR__ . '/../datas/config.json')) {
$conf->webPage = true; $conf->webPage = true;
$_SESSION['login'] = 1; $_SESSION['login'] = 1;
$_SESSION['firstRun'] = 1; $_SESSION['firstRun'] = 1;
$_SESSION['webPage'] = 1;
if ($_SERVER['REQUEST_URI'] !== '/backend?page=settings') { if ($_SERVER['REQUEST_URI'] !== '/backend?page=settings') {
header("Location:/backend?page=settings"); header("Location:/backend?page=settings");
exit(); exit();

View file

@ -23,6 +23,7 @@ use App\Utils\Domains;
<td>Complete</td> <td>Complete</td>
<td>Full</td> <td>Full</td>
<td>HD</td> <td>HD</td>
<td>nHD</td>
<td>Thumb</td> <td>Thumb</td>
<td>Favicon</td> <td>Favicon</td>
<td>Og</td> <td>Og</td>
@ -37,6 +38,7 @@ use App\Utils\Domains;
<td><?= ConvertStatus::convertToIcon($value->complete); ?></td> <td><?= ConvertStatus::convertToIcon($value->complete); ?></td>
<td><?= ConvertStatus::convertToIcon($value->full); ?></td> <td><?= ConvertStatus::convertToIcon($value->full); ?></td>
<td><?= ConvertStatus::convertToIcon($value->hd); ?></td> <td><?= ConvertStatus::convertToIcon($value->hd); ?></td>
<td><?= ConvertStatus::convertToIcon($value->nhd); ?></td>
<td><?= ConvertStatus::convertToIcon($value->thumb); ?></td> <td><?= ConvertStatus::convertToIcon($value->thumb); ?></td>
<td><?= ConvertStatus::convertToIcon($value->fav); ?></td> <td><?= ConvertStatus::convertToIcon($value->fav); ?></td>
<td><?= ConvertStatus::convertToIcon($value->og); ?></td> <td><?= ConvertStatus::convertToIcon($value->og); ?></td>
@ -66,6 +68,7 @@ use App\Utils\Domains;
<img class="w3-border w3c-margin" src="" id="full" width="35%"> <img class="w3-border w3c-margin" src="" id="full" width="35%">
<img class="w3-border w3c-margin" src="" id="hd" width="30%"> <img class="w3-border w3c-margin" src="" id="hd" width="30%">
<img class="w3-border w3c-margin" src="" id="og" width="25%"> <img class="w3-border w3c-margin" src="" id="og" width="25%">
<img class="w3-border w3c-margin" src="" id="nhd" width="20%">
<img class="w3-border w3c-margin" src="" id="thumb" width="15%"> <img class="w3-border w3c-margin" src="" id="thumb" width="15%">
</div> </div>
</div> </div>
@ -106,6 +109,7 @@ use App\Utils\Domains;
let $complete = document.getElementById("complete"); let $complete = document.getElementById("complete");
let $full = document.getElementById("full"); let $full = document.getElementById("full");
let $hd = document.getElementById("hd"); let $hd = document.getElementById("hd");
let $nhd = document.getElementById("nhd");
let $thumb = document.getElementById("thumb"); let $thumb = document.getElementById("thumb");
let $og = document.getElementById("og"); let $og = document.getElementById("og");
let $fav = document.getElementById("fav"); let $fav = document.getElementById("fav");
@ -115,6 +119,7 @@ use App\Utils\Domains;
$complete.src = "?type=complete&showImg=" + $hmac; $complete.src = "?type=complete&showImg=" + $hmac;
$full.src = "?type=full&showImg=" + $hmac; $full.src = "?type=full&showImg=" + $hmac;
$hd.src = "?type=hd&showImg=" + $hmac; $hd.src = "?type=hd&showImg=" + $hmac;
$nhd.src = "?type=nhd&showImg=" + $hmac;
$thumb.src = "?type=thumb&showImg=" + $hmac; $thumb.src = "?type=thumb&showImg=" + $hmac;
$og.src = "?type=og&showImg=" + $hmac; $og.src = "?type=og&showImg=" + $hmac;
$fav.src = "?type=fav&showImg=" + $hmac; $fav.src = "?type=fav&showImg=" + $hmac;

View file

@ -42,6 +42,7 @@ use App\Utils\Page;
<option value="og" <?= Page::selected('og', $this->conf->permitType); ?>>Og image</option> <option value="og" <?= Page::selected('og', $this->conf->permitType); ?>>Og image</option>
<option value="pdf" <?= Page::selected('pdf', $this->conf->permitType); ?>>PDF</option> <option value="pdf" <?= Page::selected('pdf', $this->conf->permitType); ?>>PDF</option>
<option value="thumb" <?= Page::selected('thumb', $this->conf->permitType); ?>>ThumbShot (160x90)</option> <option value="thumb" <?= Page::selected('thumb', $this->conf->permitType); ?>>ThumbShot (160x90)</option>
<option value="nhd" <?= Page::selected('nhd', $this->conf->permitType); ?>>nHD (640x360)</option>
<option value="hd" <?= Page::selected('hd', $this->conf->permitType); ?>>HD (1080x720)</option> <option value="hd" <?= Page::selected('hd', $this->conf->permitType); ?>>HD (1080x720)</option>
<option value="full" <?= Page::selected('full', $this->conf->permitType); ?>>Full HD (1920x1080)</option> <option value="full" <?= Page::selected('full', $this->conf->permitType); ?>>Full HD (1920x1080)</option>
<option value="complete" <?= Page::selected('complete', $this->conf->permitType); ?>>Complete (1920x height of page)</option> <option value="complete" <?= Page::selected('complete', $this->conf->permitType); ?>>Complete (1920x height of page)</option>