Restructure static site generation
parent
918a94b8b4
commit
8edb363efe
@ -0,0 +1,19 @@
|
||||
<?php
|
||||
$PROJECT_ROOT=__DIR__;
|
||||
$CACHE_ROOT="$PROJECT_ROOT/cache";
|
||||
$QR_CODES="$CACHE_ROOT/qr-codes";
|
||||
$ROOMS_FILE="$CACHE_ROOT/rooms.json";
|
||||
$DOCUMENT_ROOT="$PROJECT_ROOT/output";
|
||||
$TEMPLATES_ROOT="$PROJECT_ROOT/sites";
|
||||
$LANGUAGES_ROOT="$PROJECT_ROOT/languages"
|
||||
|
||||
// set timeout for file_get_contents()
|
||||
ini_set('default_socket_timeout', 6); // in seconds, default is 60
|
||||
|
||||
// curl timeout is millisecons
|
||||
$curl_connecttimeout_ms = 3000; // time for initiation of the connection
|
||||
$curl_timeout_ms = 6000; // max time for whole connection (incl. transfer)
|
||||
|
||||
// do not report warnings (timeouts, SSL/TLS errors)
|
||||
error_reporting(E_ALL & ~E_WARNING);
|
||||
?>
|
@ -1,201 +0,0 @@
|
||||
<?php
|
||||
/*
|
||||
* Build valid HTML5 page from provided (table) html
|
||||
*/
|
||||
function create_html_page_from_html_data($html_data, $title, $timestamp) {
|
||||
$pre =
|
||||
"<!DOCTYPE html>" . PHP_EOL .
|
||||
"<html lang=\"en\">" . PHP_EOL .
|
||||
" <head>" . PHP_EOL .
|
||||
" <meta charset=\"UTF-8\">" . PHP_EOL .
|
||||
" <link rel=\"icon\" type=\"image/svg+xml\" href=\"favicon.svg\" sizes=\"any\">" . PHP_EOL .
|
||||
" <link rel=\"stylesheet\" href=\"styles2.css\">" . PHP_EOL .
|
||||
" <script src=\"script2.js\" defer></script>" . PHP_EOL .
|
||||
" <title>" . $title . "</title>" . PHP_EOL .
|
||||
" </head>" . PHP_EOL .
|
||||
" <body onload=\"onLoad(" . $timestamp . ")\">" . PHP_EOL;
|
||||
|
||||
$post =
|
||||
" </body>" . PHP_EOL .
|
||||
"</html>" . PHP_EOL;
|
||||
|
||||
$html5 = $pre . $html_data . $post;
|
||||
|
||||
return $html5;
|
||||
}
|
||||
|
||||
/*
|
||||
* Writes HTML table with the following info:
|
||||
* Token + shortened pubkey | Name | Description | Users | View Links(?) | Join URL
|
||||
*/
|
||||
function get_table_html($info_arrays) {
|
||||
$table_lines = array();
|
||||
foreach($info_arrays as $id => $content) {
|
||||
/*
|
||||
* $id is "room token+shortened_pubkey", e.g. "example+09af"
|
||||
* Each $content looks like this:
|
||||
* $info_array = array(
|
||||
* "name" => "Name of the room",
|
||||
* "language" => "🇩🇪",
|
||||
* "description" => "Some text that describes the community",
|
||||
* "active_users" => 1234,
|
||||
* "preview_link" => "https://example.com/r/example",
|
||||
* "join_link" => "https://example.com/example?public_key=[64_hex_chars]"
|
||||
* );
|
||||
*/
|
||||
$exploded = explode("/", $content["join_link"]); // https: + "" + 1.2.3.4:56789 + token?public_key=0123456789abcdef
|
||||
$server_url = $exploded[0] . "//" . $exploded[2]; // extract server_url
|
||||
$token = explode("?", $exploded[3])[0]; // extract token
|
||||
|
||||
$line =
|
||||
" <tr id=\"" . $id . "\">" . PHP_EOL .
|
||||
" <td class=\"td_identifier\">" . $id . "</td>" . PHP_EOL .
|
||||
" <td>" . $content["language"] . "</td>" . PHP_EOL .
|
||||
" <td>" . $content["name"] . "</td>" . PHP_EOL .
|
||||
" <td>" . $content["description"] . "</td>" . PHP_EOL .
|
||||
" <td class=\"td_users\">" . $content["active_users"] . "</td>" . PHP_EOL .
|
||||
" <td><a href=\"" . $content["preview_link"] . "\">" . $content["preview_link"] . "</a></td>" . PHP_EOL .
|
||||
" <td><img class=\"qr-code-icon\" src=\"qrcode-solid.svg\" onclick=\"displayQRModal('" . $id . "')\" alt=\"Pictogram of an QR code\"></td>" . PHP_EOL .
|
||||
" <td class=\"td_join_url\"><a href=\"" . $content["join_link"] . "\">" . $content["join_link"] . "</a></td>" . PHP_EOL .
|
||||
" </tr>" . PHP_EOL;
|
||||
$table_lines[] = $line;
|
||||
}
|
||||
|
||||
// prefix
|
||||
$prefix =
|
||||
"<h1 id=\"headline\">Session Communities</h1>" . PHP_EOL .
|
||||
"<table id=\"tbl_communities\">" . PHP_EOL .
|
||||
" <tr>" . PHP_EOL .
|
||||
" <th onclick=\"sortTable(0)\" id=\"th_identifier\">Identifier</th>" . PHP_EOL .
|
||||
" <th onclick=\"sortTable(1)\" id=\"th_language\">L</th>" . PHP_EOL .
|
||||
" <th onclick=\"sortTable(2)\" id=\"th_name\">Name</th>" . PHP_EOL .
|
||||
" <th onclick=\"sortTable(3)\" id=\"th_description\">Description</th>" . PHP_EOL .
|
||||
" <th onclick=\"sortTable(4)\" id=\"th_users\">Users</th>" . PHP_EOL .
|
||||
" <th onclick=\"sortTable(5)\" id=\"th_preview\">Preview</th>" . PHP_EOL .
|
||||
" <th id=\"th_qr\">QR</th>" . PHP_EOL .
|
||||
" <th onclick=\"sortTable(7)\" id=\"th_join_url\">Join URL</th>" . PHP_EOL .
|
||||
" </tr>" . PHP_EOL;
|
||||
|
||||
// suffix
|
||||
$suffix =
|
||||
"</table>" . PHP_EOL .
|
||||
"<table id=\"tbl_footer\">" . PHP_EOL .
|
||||
" <tr>" . PHP_EOL .
|
||||
" <td id=\"td_summary\">" . count($table_lines) . " unique Session Communities on " . count_servers($info_arrays) . " servers have been found.</td>" . PHP_EOL .
|
||||
" </tr>" . PHP_EOL .
|
||||
" <tr>" . PHP_EOL .
|
||||
" <td id=\"td_last_checked\">Last checked X minutes ago.</td>" . PHP_EOL .
|
||||
" </tr>" . PHP_EOL .
|
||||
"</table>" . PHP_EOL;
|
||||
|
||||
// concatenate html
|
||||
$html = $prefix;
|
||||
foreach($table_lines as $line) {
|
||||
$html = $html . $line;
|
||||
}
|
||||
$html = $html . $suffix;
|
||||
|
||||
return $html;
|
||||
}
|
||||
|
||||
/*
|
||||
* Needed until all Community servers reliably generate QR codes again
|
||||
*/
|
||||
function get_qr_img_element_from_join_url($join_url) {
|
||||
$data = get_base64_qr_code_from_join_url($join_url);
|
||||
$mime = "image/png";
|
||||
$src = "data:" . $mime . ";base64," . $data;
|
||||
|
||||
$result =
|
||||
"<img src=\"" . $src . "\" " .
|
||||
"alt=\"Community join link encoded as QR code image\" " .
|
||||
"class=\"qr-code\">";
|
||||
// echo($result . PHP_EOL);
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/*
|
||||
* Use Google API to generate QR codes and encode them as base64
|
||||
*/
|
||||
function get_base64_qr_code_from_join_url($join_url) {
|
||||
// https://developers.google.com/chart/infographics/docs/qr_codes
|
||||
$data = urlencode($join_url);
|
||||
$size = "512x512";
|
||||
$api_url =
|
||||
"https://chart.googleapis.com/chart?cht=qr" .
|
||||
"&chs=" . $size .
|
||||
"&chl=" . $data .
|
||||
"&chld=L|0"; // error correction level: L = 7%, M = 15%, Q = 25%, H = 30% | margin in number of rows
|
||||
$img_base64 = base64_encode(file_get_contents($api_url));
|
||||
// echo($img_base64 . PHP_EOL);
|
||||
|
||||
return $img_base64;
|
||||
}
|
||||
|
||||
/*
|
||||
* TODO: Description
|
||||
*/
|
||||
function create_qr_code_modals_html($info_arrays) {
|
||||
$html = "";
|
||||
foreach($info_arrays as $id => $content) {
|
||||
/*
|
||||
* $id is "room token+shortened_pubkey", e.g. "example+09af"
|
||||
* Each $content looks like this:
|
||||
* $info_array = array(
|
||||
* "name" => "Name of the room",
|
||||
* "language" => "🇩🇪",
|
||||
* "description" => "Some text that describes the community",
|
||||
* "active_users" => 1234,
|
||||
* "preview_link" => "https://example.com/r/example",
|
||||
* "join_link" => "https://example.com/example?public_key=[64_hex_chars]"
|
||||
* );
|
||||
*/
|
||||
$img_elem = get_qr_img_element_from_join_url($content["join_link"]); // TODO: incorporate ID to use in js function
|
||||
$modal_html =
|
||||
"<div id=\"modal_" . $id . "\" class=\"qr-code-modal\">" . PHP_EOL .
|
||||
" <div class=\"qr-code-modal-content\">" . PHP_EOL .
|
||||
" <span class=\"qr-code-modal-close\" onclick=\"hideQRModal('" . $id . "')\">×</span>" . PHP_EOL .
|
||||
" " . $img_elem . PHP_EOL .
|
||||
" </div>" . PHP_EOL .
|
||||
"</div>" . PHP_EOL;
|
||||
|
||||
$html = $html . $modal_html;
|
||||
}
|
||||
|
||||
return $html;
|
||||
}
|
||||
|
||||
/*
|
||||
* Generate the HTML for the toast/snackbar when you copy a join link
|
||||
*/
|
||||
function get_copy_snackbar() {
|
||||
$snackbar_html =
|
||||
"<div id=\"copy-snackbar\">" .
|
||||
"Copied URL to clipboard. Paste into Session app to join." .
|
||||
"</div>";
|
||||
|
||||
return $snackbar_html;
|
||||
}
|
||||
|
||||
/*
|
||||
* TODO: Description
|
||||
*/
|
||||
function generateHTML($timestamp, $info_arrays) {
|
||||
$title = "Self-updating list of active Session Communities";
|
||||
|
||||
$table_html = get_table_html($info_arrays);
|
||||
$modal_html = create_qr_code_modals_html($info_arrays);
|
||||
$snackbar_html = get_copy_snackbar();
|
||||
|
||||
$html =
|
||||
$table_html . PHP_EOL .
|
||||
$modal_html . PHP_EOL .
|
||||
$snackbar_html . PHP_EOL;
|
||||
|
||||
$final_html = create_html_page_from_html_data($html, $title, $timestamp);
|
||||
|
||||
return $final_html;
|
||||
}
|
||||
|
||||
?>
|
@ -0,0 +1,33 @@
|
||||
<?php
|
||||
// Perform static site generation.
|
||||
|
||||
require_once "getenv.php";
|
||||
|
||||
// https://stackoverflow.com/a/17161106
|
||||
function rglob($pattern, $flags = 0) {
|
||||
$files = glob($pattern, $flags);
|
||||
foreach (glob(dirname($pattern).'/*', GLOB_ONLYDIR|GLOB_NOSORT) as $dir) {
|
||||
$files = array_merge(
|
||||
[],
|
||||
...[$files, rglob($dir . "/" . basename($pattern), $flags)]
|
||||
);
|
||||
}
|
||||
return $files;
|
||||
}
|
||||
|
||||
foreach (rglob("$TEMPLATES_ROOT/*.php") as $phppath) {
|
||||
// Do not render auxilliary PHP files.
|
||||
if (str_contains("$phppath", "/+") || $phppath[0] == "+")
|
||||
continue;
|
||||
|
||||
$docpath = str_replace($TEMPLATES_ROOT, $DOCUMENT_ROOT, $phppath);
|
||||
$docpath = str_replace(".php", ".html", $docpath);
|
||||
|
||||
// This works? Yes, yes it does.
|
||||
// We do this to isolate the environment and include-once triggers,
|
||||
// otherwise we could include the documents in an ob_* wrapper.
|
||||
$document = `php $phppath`;
|
||||
|
||||
file_put_contents($docpath, $document);
|
||||
}
|
||||
?>
|
@ -0,0 +1,13 @@
|
||||
<?php
|
||||
$PROJECT_ROOT = dirname(__FILE__);
|
||||
|
||||
while (!file_exists("$PROJECT_ROOT/.phpenv")) {
|
||||
if ($PROJECT_ROOT == "/" || $PROJECT_ROOT == "")
|
||||
throw new RuntimeException("Could not find .phpenv file.");
|
||||
$PROJECT_ROOT = dirname($PROJECT_ROOT);
|
||||
}
|
||||
|
||||
require_once "$PROJECT_ROOT/.phpenv";
|
||||
|
||||
// set_include_path(get_include_path() . PATH_SEPARATOR . $PROJECT_ROOT);
|
||||
?>
|
@ -0,0 +1,5 @@
|
||||
<?php
|
||||
// Perform full update of community list.
|
||||
require_once "fetch-servers.php";
|
||||
require_once "generate-html.php";
|
||||
?>
|
@ -0,0 +1,45 @@
|
||||
<?php
|
||||
function room_qr_code_cached($room_id) {
|
||||
global $QR_CODES;
|
||||
return "$QR_CODES/$room_id.png";
|
||||
}
|
||||
|
||||
/*
|
||||
* Use Google API to generate QR codes and encode them as base64
|
||||
*/
|
||||
function base64_qr_code($room_id, $join_url, $size = "512x512") {
|
||||
// Could use http_build_query() instead, but I won't break what works.
|
||||
// https://developers.google.com/chart/infographics/docs/qr_codes
|
||||
$png_cached = room_qr_code_cached($room_id);
|
||||
if (file_exists($png_cached))
|
||||
return base64_encode(file_get_contents($png_cached));
|
||||
$data = urlencode($join_url);
|
||||
$api_url =
|
||||
"https://chart.googleapis.com/chart?cht=qr" .
|
||||
"&chs=$size" .
|
||||
"&chl=$data" .
|
||||
"&chld=L|0";
|
||||
// error correction level: L = 7%, M = 15%, Q = 25%, H = 30%
|
||||
// | margin in number of rows
|
||||
$png = file_get_contents($api_url);
|
||||
file_put_contents($png_cached, $png);
|
||||
return base64_encode($png);
|
||||
}
|
||||
|
||||
file_exists($QR_CODES) or mkdir($QR_CODES, 700);
|
||||
?>
|
||||
|
||||
<?php foreach ($rooms as $id => $room): ?>
|
||||
<div id="modal_<?=$id?>" class="qr-code-modal">
|
||||
<div class="qr-code-modal-content">
|
||||
<span class="qr-code-modal-close" onclick='hideQRModal("<?=$id?>")'>
|
||||
×
|
||||
</span>
|
||||
<img
|
||||
src="data:image/png;base64,<?=base64_qr_code($id, $room->join_link)?>"
|
||||
alt="Community join link encoded as QR code"
|
||||
class="qr-code"
|
||||
>
|
||||
</div>
|
||||
</div>
|
||||
<?php endforeach; ?>
|
@ -0,0 +1,67 @@
|
||||
<?php
|
||||
// Once handlers are attached in JS, this check ceases to be useful.
|
||||
function column_sortable($id) {
|
||||
return $id != "qr";
|
||||
}
|
||||
|
||||
function sort_onclick($colno) {
|
||||
global $TABLE_COLUMNS;
|
||||
$column = $TABLE_COLUMNS[$colno];
|
||||
if (!column_sortable($column['id'])) return "";
|
||||
return " onclick='sortTable($colno)'";
|
||||
}
|
||||
|
||||
$TABLE_COLUMNS = [
|
||||
['id' => "identifier", 'name' => "Identifier"],
|
||||
['id' => "language", 'name' => "L"],
|
||||
['id' => "name", 'name' => "Name"],
|
||||
['id' => "description", 'name' => "Description"],
|
||||
['id' => "users", 'name' => "Users"],
|
||||
['id' => "preview", 'name' => "Preview"],
|
||||
['id' => "qr", 'name' => "QR"],
|
||||
['id' => "join_url", 'name' => "Join URL"],
|
||||
];
|
||||
?>
|
||||
|
||||
<table id="tbl_communities">
|
||||
<tr>
|
||||
<?php foreach ($TABLE_COLUMNS as $colno => $column): ?>
|
||||
<th<?=sort_onclick($colno)?> id="th_<?=$column['id']?>">
|
||||
<?=$column['name']?>
|
||||
|
||||
</th>
|
||||
<?php endforeach; ?>
|
||||
</tr>
|
||||
<?php foreach ($rooms as $id => $room): ?>
|
||||
<tr id="<?=$id?>">
|
||||
<td class="td_identifier"><?=$id?></td>
|
||||
<td class="td_language"><?=$room->language?></td>
|
||||
<td class="td_name"><?=$room->name?></td>
|
||||
<td class="td_description">
|
||||
<?=$room->description?>
|
||||
|
||||
</td>
|
||||
<td class="td_users"><?=$room->active_users?></td>
|
||||
<td class="td_preview">
|
||||
<a href="<?=$room->preview_link?>">
|
||||
<?=$room->preview_link?>
|
||||
|
||||
</a>
|
||||
</td>
|
||||
<td class="td_qr_code">
|
||||
<img
|
||||
class="qr-code-icon"
|
||||
src="qrcode-solid.svg"
|
||||
onclick='displayQRModal("<?=$id?>")'
|
||||
alt="Pictogram of a QR code"
|
||||
>
|
||||
</td>
|
||||
<td class="td_join_url">
|
||||
<a href="<?=$room->join_link?>">
|
||||
<?=$room->join_link?>
|
||||
|
||||
</a>
|
||||
</td>
|
||||
</tr>
|
||||
<?php endforeach; ?>
|
||||
</table>
|
@ -0,0 +1 @@
|
||||
../php/getenv.php
|
@ -0,0 +1,42 @@
|
||||
<?php
|
||||
// prerequisite include for sites and components
|
||||
require_once "+getenv.php";
|
||||
require_once "$PROJECT_ROOT/php/server-utils.php";
|
||||
|
||||
$rooms_raw = file_get_contents($ROOMS_FILE);
|
||||
$rooms = json_decode($rooms_raw);
|
||||
$rooms_assoc = json_decode($rooms_raw, true);
|
||||
$timestamp = filemtime($ROOMS_FILE);
|
||||
?>
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<link rel="icon" type="image/svg+xml" href="favicon.svg" sizes="any">
|
||||
<link rel="stylesheet" href="styles2.css">
|
||||
<script src="script2.js" defer></script>
|
||||
<title>Self-updating list of active Session communities</title>
|
||||
</head>
|
||||
<body onload="onLoad(<?php echo $timestamp ?>)">
|
||||
<h1 id="headline">Session Communities</h1>
|
||||
<?php include "+components/qr_modals.php" ?>
|
||||
|
||||
<?php include "+components/tbl_communities.php" ?>
|
||||
|
||||
<table id="tbl_footer">
|
||||
<tr>
|
||||
<td id="td_summary">
|
||||
<?=count($rooms_assoc)?> unique Session Communities
|
||||
on <?=count_servers($rooms_assoc)?> servers have been found.
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td id="td_last_checked">Last checked X minutes ago.</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
<div id="copy-snackbar">
|
||||
Copied URL to clipboard. Paste into Session app to join
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
Reference in New Issue