|
<?php |
|
/** |
|
* pr0gramm-fliesentischPixel |
|
* |
|
* eventHandler.php CLI Script |
|
* |
|
* @author RundesBalli <GitHub@RundesBalli.com> |
|
* @copyright 2023 RundesBalli |
|
* @version 1.0 |
|
* @see https://RundesBalli.com |
|
*/ |
|
|
|
/** |
|
* ============================================= |
|
* |
|
* SETTINGS |
|
* |
|
* ============================================= |
|
*/ |
|
|
|
/** |
|
* |
|
* Template settings |
|
* |
|
*/ |
|
|
|
/** |
|
* First pixel top left of the template |
|
* |
|
* @var array |
|
*/ |
|
$templatePixel = [ |
|
'x' => 0, |
|
'y' => 0, |
|
]; |
|
|
|
/** |
|
* Replace alpha |
|
* |
|
* @var string|null hex code (without #) if replacement should occur, otherwise NULL. |
|
*/ |
|
$replaceAlpha = 'ffffff'; |
|
|
|
|
|
/** |
|
* |
|
* Account settings |
|
* |
|
*/ |
|
|
|
/** |
|
* Token |
|
* |
|
* Use `id` from `me`-cookie |
|
* |
|
* @var string |
|
*/ |
|
$token = ''; |
|
|
|
|
|
/** |
|
* |
|
* Database settings |
|
* |
|
*/ |
|
|
|
/** |
|
* MySQL-Credentials |
|
* |
|
* @var array |
|
* string host MySQL connection host |
|
* string user Username for the MySQL connection |
|
* string pass Password for the MySQL connection |
|
* string db Database on the SQL server in which to work. |
|
* string charset Charset of the connection. Default: utf8 |
|
*/ |
|
$mysqlCredentials = [ |
|
'host' => 'localhost', |
|
'user' => '', |
|
'pass' => '', |
|
'db' => '', |
|
'charset' => 'utf8' |
|
]; |
|
|
|
/** |
|
* ============================================= |
|
* |
|
* Functions |
|
* |
|
* ============================================= |
|
*/ |
|
/** |
|
* Database connection |
|
*/ |
|
$dbl = mysqli_connect($mysqlCredentials['host'], $mysqlCredentials['user'], $mysqlCredentials['pass'], $mysqlCredentials['db']) OR DIE(MYSQLI_ERROR($dbl)); |
|
mysqli_set_charset($dbl, $mysqlCredentials['charset']) OR DIE(MYSQLI_ERROR($dbl)); |
|
|
|
/** |
|
* Defuse |
|
* |
|
* Defuse function to prepare user inputs for the database. |
|
* |
|
* @param string $defuseString String that is to be "defused" in order to pass it into a database query. |
|
* @param bool $trim Specifies whether to remove spaces/lines at the beginning and end. |
|
* |
|
* @return string The prepared "defused" string. |
|
*/ |
|
function defuse($defuseString, bool $trim = TRUE) { |
|
if($trim === TRUE) { |
|
$defuseString = trim($defuseString); |
|
} |
|
global $dbl; |
|
return mysqli_real_escape_string($dbl, strip_tags($defuseString)); |
|
} |
|
|
|
|
|
/** |
|
* ============================================= |
|
* |
|
* EventHandler |
|
* |
|
* ============================================= |
|
*/ |
|
|
|
/** |
|
* EventHandler |
|
* |
|
* - loading and reading the snapshot |
|
* - read the template |
|
* - read continuous eventstream |
|
*/ |
|
|
|
while(TRUE) { |
|
/** |
|
* |
|
* SNAPSHOT |
|
* |
|
*/ |
|
|
|
/** |
|
* Initialize cURL and set options |
|
*/ |
|
echo 'Load snapshot.'."\n"; |
|
$ch = curl_init(); |
|
curl_setopt_array($ch, [ |
|
CURLOPT_RETURNTRANSFER => TRUE, |
|
CURLOPT_HEADER => TRUE, |
|
CURLOPT_URL => 'https://sse.pr0gramm.com/api/snapshot', |
|
CURLOPT_USERAGENT => 'RundesBalli :-)', |
|
CURLOPT_CONNECTTIMEOUT => 5, |
|
CURLOPT_TIMEOUT => 10, |
|
CURLOPT_HTTPHEADER => [ |
|
'Schmuser: true', |
|
'X-pr0gramm-token: '.$token, |
|
], |
|
]); |
|
|
|
/** |
|
* Execute cURL |
|
*/ |
|
$response = curl_exec($ch); |
|
|
|
/** |
|
* Error handling |
|
*/ |
|
$errNo = curl_errno($ch); |
|
$errStr = curl_error($ch); |
|
if($errNo != 0) { |
|
die("cURL snapshot - errno: ".$errNo." - errstr: ".$errStr."\n"); |
|
} |
|
$httpCode = curl_getinfo($ch, CURLINFO_RESPONSE_CODE); |
|
if($httpCode != 200) { |
|
die("cURL snapshot - httpcode: ".$httpCode."\n"); |
|
} |
|
|
|
/** |
|
* Extract and parse headers |
|
*/ |
|
echo 'Parse headers.'."\n"; |
|
$headerSize = curl_getinfo($ch, CURLINFO_HEADER_SIZE); |
|
$headers = []; |
|
foreach(explode("\n", trim(mb_substr($response, 0, $headerSize))) as $header) { |
|
if(stripos($header, ': ') === FALSE) { |
|
continue; |
|
} |
|
list($headerName, $value) = explode(': ', $header, 2); |
|
$headers[$headerName] = trim($value); |
|
} |
|
$eventIdSnapshot = $headers['X-pr0gramm-Event-Id']; |
|
echo 'eventIdSnapshot: '.$eventIdSnapshot."\n"; |
|
|
|
/** |
|
* Check if the response is image/png |
|
*/ |
|
if($headers['Content-Type'] != 'image/png') { |
|
die('Response is no image/png'."\n"); |
|
} |
|
|
|
/** |
|
* Close the cURL handle. |
|
*/ |
|
curl_close($ch); |
|
|
|
/** |
|
* Extract and parse snapshot |
|
*/ |
|
echo 'Parse snapshot.'."\n"; |
|
$image = imagecreatefromstring(trim(mb_substr($response, $headerSize))); |
|
mysqli_query($dbl, 'TRUNCATE TABLE `canvas`') OR DIE(MYSQLI_ERROR($dbl)); |
|
$values = []; |
|
for($x = 0; $x < imagesx($image); $x++) { |
|
for($y = 0; $y < imagesy($image); $y++) { |
|
$rgb = imagecolorsforindex($image, imagecolorat($image, $x, $y)); |
|
if($rgb['alpha'] != 0) { |
|
$values[] = '('.$x.', '.$y.', "ffffff")'; |
|
continue; |
|
} |
|
$values[] = '('.$x.', '.$y.', "'.defuse(strtolower(sprintf("%02x%02x%02x", $rgb['red'], $rgb['green'], $rgb['blue']))).'")'; |
|
} |
|
} |
|
mysqli_query($dbl, 'INSERT INTO `canvas` (`x`, `y`, `hex`) VALUES '.implode(',', $values)) OR DIE(MYSQLI_ERROR($dbl)); |
|
imagedestroy($image); |
|
|
|
|
|
/** |
|
* |
|
* availableColors |
|
* |
|
*/ |
|
|
|
/** |
|
* Initialize cURL and set options |
|
*/ |
|
echo 'Load availableColors.'."\n"; |
|
$ch = curl_init(); |
|
curl_setopt_array($ch, [ |
|
CURLOPT_RETURNTRANSFER => TRUE, |
|
CURLOPT_URL => 'https://sse.pr0gramm.com/api/status', |
|
CURLOPT_USERAGENT => 'eventHandler', |
|
CURLOPT_CONNECTTIMEOUT => 5, |
|
CURLOPT_TIMEOUT => 10, |
|
CURLOPT_HTTPHEADER => [ |
|
'Schmuser: true', |
|
'X-pr0gramm-token: '.$token, |
|
], |
|
]); |
|
|
|
/** |
|
* Execute cURL |
|
*/ |
|
$response = curl_exec($ch); |
|
|
|
/** |
|
* Error handling |
|
*/ |
|
$errNo = curl_errno($ch); |
|
$errStr = curl_error($ch); |
|
if($errNo != 0) { |
|
die("cURL availableColors - errno: ".$errNo." - errstr: ".$errStr."\n"); |
|
} |
|
$httpCode = curl_getinfo($ch, CURLINFO_RESPONSE_CODE); |
|
if($httpCode != 200) { |
|
die("cURL availableColors - httpcode: ".$httpCode."\n"); |
|
} |
|
|
|
/** |
|
* Read colors. |
|
*/ |
|
$availableColors = json_decode($response, TRUE)['availableColors']; |
|
echo 'Available colors: '.implode(', ', $availableColors)."\n"; |
|
|
|
/** |
|
* Close the cURL handle. |
|
*/ |
|
curl_close($ch); |
|
|
|
|
|
/** |
|
* |
|
* TEMPLATE |
|
* |
|
* Templatefile: template.png |
|
* Colors will not be checked and have to be correct in the template. |
|
* |
|
*/ |
|
|
|
/** |
|
* Read and parse template |
|
*/ |
|
echo 'Parse template.'."\n"; |
|
$image = imagecreatefrompng('./template.png'); |
|
$values = []; |
|
for($x = 0; $x < imagesx($image); $x++) { |
|
for($y = 0; $y < imagesy($image); $y++) { |
|
$rgb = imagecolorsforindex($image, imagecolorat($image, $x, $y)); |
|
if($rgb['alpha'] != 0) { |
|
$values[] = '('.($x+$templatePixel['x']).', '.($y+$templatePixel['y']).', '.($replaceAlpha !== NULL ? '"'.strtolower($replaceAlpha).'"' : 'NULL').')'; |
|
continue; |
|
} |
|
if(!in_array(strtolower(sprintf("%02x%02x%02x", $rgb['red'], $rgb['green'], $rgb['blue'])), $availableColors)) { |
|
echo 'Skipping '.($x+$templatePixel['x']).', '.($y+$templatePixel['y']).', "'.defuse(strtolower(sprintf("%02x%02x%02x", $rgb['red'], $rgb['green'], $rgb['blue']))).'" - not in availableColors'."\n"; |
|
continue; |
|
} |
|
$values[] = '('.($x+$templatePixel['x']).', '.($y+$templatePixel['y']).', "'.defuse(strtolower(sprintf("%02x%02x%02x", $rgb['red'], $rgb['green'], $rgb['blue']))).'")'; |
|
} |
|
} |
|
mysqli_query($dbl, 'INSERT INTO `canvas` (`x`, `y`, `targetHex`) VALUES '.implode(',', $values).' ON DUPLICATE KEY UPDATE `targetHex`=VALUES(`targetHex`)') OR DIE(MYSQLI_ERROR($dbl)); |
|
imagedestroy($image); |
|
|
|
|
|
/** |
|
* |
|
* EVENTS |
|
* |
|
*/ |
|
|
|
/** |
|
* Writefunction |
|
*/ |
|
if(!function_exists('eventParser')) { |
|
function eventParser($ch, $data) { |
|
foreach(explode("\n", $data) as $stream) { |
|
if(stripos($stream, 'data: ') === FALSE) { |
|
continue; |
|
} |
|
|
|
$json = json_decode(str_replace('data: ', '', $stream), TRUE); |
|
if(json_last_error() !== JSON_ERROR_NONE) { |
|
die('eventParser - JSON error: '."\n".var_export($json, TRUE)."\n"); |
|
} |
|
|
|
global $dbl; |
|
mysqli_query($dbl, 'UPDATE `canvas` SET `hex`="'.defuse(strtolower($json['color'])).'" WHERE `x`='.defuse($json['x']).' AND `y`='.defuse($json['y']).' LIMIT 1') OR DIE(MYSQLI_ERROR($dbl)); |
|
echo 'Updating '.$json['x'].','.$json['y'].': '.$json['color']."\n"; |
|
} |
|
|
|
return strlen($data); |
|
} |
|
} |
|
|
|
/** |
|
* Initialize cURL and set options |
|
*/ |
|
echo 'Listening to events...'."\n"; |
|
|
|
$ch = curl_init(); |
|
curl_setopt_array($ch, [ |
|
CURLOPT_URL => 'https://sse.pr0gramm.com/api/events', |
|
CURLOPT_USERAGENT => 'eventHandler', |
|
CURLOPT_CONNECTTIMEOUT => 5, |
|
CURLOPT_HTTPHEADER => [ |
|
'Schmuser: true', |
|
'X-pr0gramm-token: '.$token, |
|
'last-event-id: '.$eventIdSnapshot, |
|
], |
|
CURLOPT_WRITEFUNCTION => "eventParser", |
|
]); |
|
|
|
/** |
|
* Execute cURL |
|
*/ |
|
curl_exec($ch); |
|
$cURLError = curl_errno($ch); |
|
if($cURLError != 0) { |
|
if($cURLError == 18 OR $cURLError == 7) { |
|
echo 'Restarting...'."\n"; |
|
sleep(10); |
|
continue; |
|
} |
|
die("cURL events - errno: ".$cURLError." - errstr: ".curl_error($ch)."\n"); |
|
} |
|
curl_close($ch); |
|
} |
|
?> |