diff options
author | RaindropsSys <contact@minteck.org> | 2023-04-02 23:03:02 +0200 |
---|---|---|
committer | RaindropsSys <contact@minteck.org> | 2023-04-02 23:03:02 +0200 |
commit | 02eda3e4c9b4ba718f1fff70b7328ed8cdd5e63b (patch) | |
tree | 6d1dec61008998aadc6b69f7e750712794d99324 | |
parent | f559308a1b42a9036135d764374a8c007b7d70a9 (diff) | |
download | pluralconnect-02eda3e4c9b4ba718f1fff70b7328ed8cdd5e63b.tar.gz pluralconnect-02eda3e4c9b4ba718f1fff70b7328ed8cdd5e63b.tar.bz2 pluralconnect-02eda3e4c9b4ba718f1fff70b7328ed8cdd5e63b.zip |
Updated 35 files, added 11 files and deleted includes/components/search.inc (automated)
47 files changed, 1621 insertions, 1031 deletions
@@ -1,12 +1,21 @@ <?php -ob_start(); +$start = microtime(true); +$GLOBALS["ColdHazeStart"] = microtime(true); +$GLOBALS["ColdHazePerformance"] = []; + +if (!function_exists("formatPonypush")) { + function formatPonypush($message) { + return "Update to Ponypush 3.1.0 or later — (\$PA1$\$" . base64_encode($message) . "\$\$)"; + } +} require_once $_SERVER['DOCUMENT_ROOT'] . "/includes/util/language.inc"; global $lang; global $pages; require_once $_SERVER['DOCUMENT_ROOT'] . "/includes/util/session.inc"; global $isLoggedIn; global $isLowerLoggedIn; require_once $_SERVER['DOCUMENT_ROOT'] . "/includes/util/functions.inc"; -$app = json_decode(file_get_contents($_SERVER['DOCUMENT_ROOT'] . "/includes/app.json"), true); +global $app; +$app = $GLOBALS["ColdHazeApp"] = json_decode(file_get_contents($_SERVER['DOCUMENT_ROOT'] . "/includes/app.json"), true); if (str_ends_with($_GET['_'], "/")) { $pagename = substr($_GET['_'], 0, strlen($_GET['_']) - 1); @@ -25,6 +34,7 @@ if (in_array($toplevel, ["editor", "icons", "species", "uploads"])) { } } elseif ($toplevel === "") { $pageFile = $_SERVER['DOCUMENT_ROOT'] . "/pages/home.inc"; + $GLOBALS["ColdHazePerformance"]["router"] = (microtime(true) - $start) * 1000; require_once $_SERVER['DOCUMENT_ROOT'] . "/pages/home.inc"; } else { if ($toplevel === "-") { @@ -33,6 +43,7 @@ if (in_array($toplevel, ["editor", "icons", "species", "uploads"])) { if (file_exists($_SERVER['DOCUMENT_ROOT'] . "/pages/" . $toplevel . ".inc")) { $pageFile = $_SERVER['DOCUMENT_ROOT'] . "/pages/" . $toplevel . ".inc"; + $GLOBALS["ColdHazePerformance"]["router"] = (microtime(true) - $start) * 1000; require_once $_SERVER['DOCUMENT_ROOT'] . "/pages/" . $toplevel . ".inc"; } else { peh_error("Page not found: " . strip_tags($pagename), 404); @@ -40,6 +51,7 @@ if (in_array($toplevel, ["editor", "icons", "species", "uploads"])) { } else if ($toplevel === "api") { if (file_exists($_SERVER['DOCUMENT_ROOT'] . "/pages/" . $toplevel . ".inc")) { $pageFile = $_SERVER['DOCUMENT_ROOT'] . "/pages/" . $toplevel . ".inc"; + $GLOBALS["ColdHazePerformance"]["router"] = (microtime(true) - $start) * 1000; require_once $_SERVER['DOCUMENT_ROOT'] . "/pages/" . $toplevel . ".inc"; } } else if ($toplevel === "cloudburst" || $toplevel === "raindrops" || (($isLoggedIn || $isLowerLoggedIn) && $toplevel === $app["other"]["slug"])) { @@ -60,6 +72,7 @@ if (in_array($toplevel, ["editor", "icons", "species", "uploads"])) { } $pageFile = $_SERVER['DOCUMENT_ROOT'] . "/pages/page.inc"; + $GLOBALS["ColdHazePerformance"]["router"] = (microtime(true) - $start) * 1000; require_once $_SERVER['DOCUMENT_ROOT'] . "/pages/page.inc"; } else { if (file_exists($_SERVER['DOCUMENT_ROOT'] . "/pages/" . $toplevel . ".inc")) { @@ -81,10 +94,12 @@ if (in_array($toplevel, ["editor", "icons", "species", "uploads"])) { if ((in_array($toplevel, $namesCloudburst) || in_array($toplevel, $namesRaindrops) || in_array($toplevel, $namesOther)) && $toplevel !== "unknown") { $pageFile = $_SERVER['DOCUMENT_ROOT'] . "/pages/page.inc"; + $GLOBALS["ColdHazePerformance"]["router"] = (microtime(true) - $start) * 1000; require_once $_SERVER['DOCUMENT_ROOT'] . "/pages/page.inc"; } else { global $toplevel; $pageFile = $_SERVER['DOCUMENT_ROOT'] . "/includes/util/short.inc"; + $GLOBALS["ColdHazePerformance"]["router"] = (microtime(true) - $start) * 1000; require_once $_SERVER['DOCUMENT_ROOT'] . "/includes/util/short.inc"; } } diff --git a/auth/callback/index.php b/auth/callback/index.php index 8d040e9..3b9d6eb 100644 --- a/auth/callback/index.php +++ b/auth/callback/index.php @@ -8,7 +8,7 @@ if (!isset($_GET['code'])) { die(); } -$appdata = json_decode(file_get_contents($_SERVER['DOCUMENT_ROOT'] . "/includes/app.json"), true); +$appdata = $GLOBALS["ColdHazeApp"]; $crl = curl_init('https://' . $server . '/hub/api/rest/oauth2/token'); curl_setopt($crl, CURLOPT_RETURNTRANSFER, true); diff --git a/auth/init/index.php b/auth/init/index.php index 3a4e7b7..9428825 100644 --- a/auth/init/index.php +++ b/auth/init/index.php @@ -2,5 +2,5 @@ $server = "auth.equestria.horse"; -header("Location: https://$server/hub/api/rest/oauth2/auth?client_id=" . json_decode(file_get_contents($_SERVER['DOCUMENT_ROOT'] . "/includes/app.json"), true)["oauth"]["id"] . "&response_type=code&redirect_uri=https://ponies.equestria.horse/auth/callback&scope=Hub&request_credentials=default&access_type=offline"); +header("Location: https://$server/hub/api/rest/oauth2/auth?client_id=" . $GLOBALS["ColdHazeApp"]["oauth"]["id"] . "&response_type=code&redirect_uri=https://ponies.equestria.horse/auth/callback&scope=Hub&request_credentials=default&access_type=offline"); die(); diff --git a/includes/components/footer.inc b/includes/components/footer.inc index d75b480..059d956 100644 --- a/includes/components/footer.inc +++ b/includes/components/footer.inc @@ -1,7 +1,8 @@ <?php - +global $start; +$GLOBALS["ColdHazePerformance"]["page"] = (microtime(true) - $start) * 1000; +$start = microtime(true); global $pageFile; -require_once $_SERVER['DOCUMENT_ROOT'] . "/includes/util/functions.inc"; ?> @@ -16,8 +17,10 @@ require_once $_SERVER['DOCUMENT_ROOT'] . "/includes/util/functions.inc"; global $lang; global $pages; + $time = microtime(true) - $GLOBALS["ColdHazeStart"]; + ?> - © <?= date("Y") ?> <a href="https://equestria.horse" target="_blank" class="text-muted"><?= $lang["footer"]["copyright"] ?></a> · build <?= $version["build"] ?>.<?= $version["revision"] ?> + © <?= date("Y") ?> <a href="https://equestria.horse" target="_blank" class="text-muted"><?= $lang["footer"]["copyright"] ?></a> · build <?= $version["build"] ?>.<?= $version["revision"] ?>, took <?= round($time * 1000, 2) ?> ms <br><br><br><br><br> </div> </div> @@ -35,7 +38,9 @@ require_once $_SERVER['DOCUMENT_ROOT'] . "/includes/util/functions.inc"; }) </script> -<?php require_once $_SERVER['DOCUMENT_ROOT'] . "/includes/components/search.inc"; ?> +<?php if (isset($_GET["performance"])): ?> +<pre><?php $GLOBALS["ColdHazePerformance"]["footer"] = (microtime(true) - $start) * 1000; var_dump($GLOBALS["ColdHazePerformance"]); ?></pre> +<?php endif; ?> </body> </html>
\ No newline at end of file diff --git a/includes/components/header.inc b/includes/components/header.inc index 06b9bdb..0542314 100644 --- a/includes/components/header.inc +++ b/includes/components/header.inc @@ -1,14 +1,6 @@ -<?php global $title; global $pages; - +<?php global $title; global $pages; global $readOnly; +$start = microtime(true); $useNewUI = !isset($_GET['old']); -$readOnly = false; -file_put_contents($_SERVER['DOCUMENT_ROOT'] . "/includes/data/.test", "hello"); - -if (file_exists($_SERVER['DOCUMENT_ROOT'] . "/includes/data/.test")) { - unlink($_SERVER['DOCUMENT_ROOT'] . "/includes/data/.test"); -} else { - $readOnly = true; -} $isNormallyLoggedIn = false; @@ -69,7 +61,7 @@ require_once $_SERVER['DOCUMENT_ROOT'] . "/includes/util/functions.inc"; <title><?= $title && $title !== "-" ? $title . " · " : "" ?>Cold Haze</title> <link rel="shortcut icon" href="/assets/logo/newlogo<?= $isLoggedIn || $isLowerLoggedIn ? "3" : "" ?>.png" type="image/png"> </head> -<body<?php if ($page["rail"] && $isLoggedIn && !$useNewUI): ?> id="admin-page"<?php endif; ?>> +<body> <?php require_once $_SERVER['DOCUMENT_ROOT'] . "/includes/components/navigation.inc"; global $navigation; ?> <?php if (!$useNewUI): ?> @@ -246,4 +238,4 @@ require_once $_SERVER['DOCUMENT_ROOT'] . "/includes/util/functions.inc"; display: none; } </style> -<?php } ?> +<?php } $GLOBALS["ColdHazePerformance"]["header"] = (microtime(true) - $start) * 1000; $start = microtime(true); ?> diff --git a/includes/components/navigation.inc b/includes/components/navigation.inc index bd4ea4b..29168ec 100644 --- a/includes/components/navigation.inc +++ b/includes/components/navigation.inc @@ -4,7 +4,78 @@ $pages = json_decode(file_get_contents($_SERVER['DOCUMENT_ROOT'] . "/includes/pa global $navigation; global $toplevel; -global $lang; global $pages; global $app; global $isLowerLoggedIn; +global $lang; global $pages; global $app; global $isLowerLoggedIn; global $isLoggedIn; + +$cache = json_decode(file_get_contents($_SERVER['DOCUMENT_ROOT'] . "/includes/data/cache/navigation.json"), true); + +if (!isset($cache["raindrops"])) $cache["raindrops"] = []; +if (!isset($cache["cloudburst"])) $cache["cloudburst"] = []; +if (!isset($cache["other"])) $cache["other"] = []; + +foreach ([ + [ + "name" => "raindrops", + "id" => "gdapd" + ], + [ + "name" => "cloudburst", + "id" => "ynmuc" + ], + [ + "name" => "other", + "id" => $app["other"]["id"] + ] +] as $cacheSystem) { + if (!isset($cache[$cacheSystem["name"]]["public"])) { + $isLoggedInOldState = $isLoggedIn; + $isLowerLoggedInOldState = $isLowerLoggedIn; + + $isLoggedIn = false; + $isLowerLoggedIn = false; + + $cache[$cacheSystem["name"]]["public"] = array_map(function ($member) { + return [ + "name" => $member['display_name'] ?? $member['name'], + "icon" => getAsset($member["system"], $member["id"], "heads"), + "invert" => false, + "link" => "/$member[name]", + "stepped" => null, + "private" => false + ]; + }, array_filter(scoreOrder(withTravelers(json_decode(file_get_contents($_SERVER['DOCUMENT_ROOT'] . "/includes/data/$cacheSystem[id]/members.json"), true), "$cacheSystem[id]"), "$cacheSystem[id]"), function ($member) { + return $member['name'] !== "unknown" && $member['name'] !== "fusion" && $member['name'] !== "new"; + })); + + $isLoggedIn = $isLoggedInOldState; + $isLowerLoggedIn = $isLowerLoggedInOldState; + } + + if (!isset($cache[$cacheSystem["name"]]["private"])) { + $isLoggedInOldState = $isLoggedIn; + $isLowerLoggedInOldState = $isLowerLoggedIn; + + $isLoggedIn = true; + $isLowerLoggedIn = false; + + $cache[$cacheSystem["name"]]["private"] = array_map(function ($member) { + return [ + "name" => $member['display_name'] ?? $member['name'], + "icon" => getAsset($member["system"], $member["id"], "heads"), + "invert" => false, + "link" => "/$member[name]", + "stepped" => null, + "private" => false + ]; + }, array_filter(scoreOrder(withTravelers(json_decode(file_get_contents($_SERVER['DOCUMENT_ROOT'] . "/includes/data/$cacheSystem[id]/members.json"), true), "$cacheSystem[id]"), "$cacheSystem[id]"), function ($member) { + return $member['name'] !== "unknown" && $member['name'] !== "fusion" && $member['name'] !== "new"; + })); + + $isLoggedIn = $isLoggedInOldState; + $isLowerLoggedIn = $isLowerLoggedInOldState; + } +} + +file_put_contents($_SERVER['DOCUMENT_ROOT'] . "/includes/data/cache/navigation.json", json_encode($cache)); $navigation_admin = [ "admin" => !$isLowerLoggedIn, @@ -173,41 +244,7 @@ $navigation_admin = [ "private" => false ], ] - ], - /*"debug" => [ - "name" => $lang["navigation"]["debug"], - "minimal" => false, - "items" => [ - [ - "name" => $pages["debug"]["name"][$lang["_name"]], - "icon" => "/assets/icons/debug.svg", - "invert" => true, - "link" => "/-/debug", - "stepped" => null - ], - [ - "name" => $pages["bitset"]["name"][$lang["_name"]], - "icon" => "/assets/icons/bitset.svg", - "invert" => true, - "link" => "/-/bitset", - "stepped" => null - ], - [ - "name" => $pages["score"]["name"][$lang["_name"]], - "icon" => "/assets/icons/score.svg", - "invert" => true, - "link" => "/-/score", - "stepped" => null - ], - [ - "name" => $pages["logout"]["name"][$lang["_name"]], - "icon" => "/assets/icons/logout.svg", - "invert" => true, - "link" => "/-/logout", - "stepped" => null - ] - ] - ]*/ + ] ] ]; $navigation_global = [ @@ -287,18 +324,7 @@ $navigation_cloudburst = [ "members" => [ "name" => $lang["navigation"]["members"], "minimal" => false, - "items" => array_map(function ($member) { - return [ - "name" => $member['display_name'] ?? $member['name'], - "icon" => getAsset($member["system"], $member["id"], "heads"), - "invert" => false, - "link" => "/$member[name]", - "stepped" => null, - "private" => false - ]; - }, array_filter(scoreOrder(withTravelers(json_decode(file_get_contents($_SERVER['DOCUMENT_ROOT'] . "/includes/data/ynmuc/members.json"), true), "ynmuc"), "ynmuc"), function ($member) { - return $member['name'] !== "unknown" && $member['name'] !== "fusion" && $member['name'] !== "new"; - })) + "items" => $cache["cloudburst"][$isLoggedIn || $isLowerLoggedIn ? "private" : "public"] ] ] ]; @@ -341,18 +367,7 @@ $navigation_other = [ "members" => [ "name" => $lang["navigation"]["members"], "minimal" => false, - "items" => array_map(function ($member) { - return [ - "name" => $member['display_name'] ?? $member['name'], - "icon" => getAsset($member["system"], $member["id"], "heads"), - "invert" => false, - "link" => "/$member[name]", - "stepped" => null, - "private" => false - ]; - }, array_filter(scoreOrder(json_decode(file_get_contents($_SERVER['DOCUMENT_ROOT'] . "/includes/data/other/members.json"), true), $app["other"]["id"]), function ($member) { - return $member['name'] !== "unknown" && $member['name'] !== "fusion" && $member['name'] !== "new"; - })) + "items" => $cache["other"][$isLoggedIn || $isLowerLoggedIn ? "private" : "public"] ] ] ]; @@ -395,18 +410,7 @@ $navigation_raindrops = [ "members" => [ "name" => $lang["navigation"]["members"], "minimal" => false, - "items" => array_map(function ($member) { - return [ - "name" => $member['display_name'] ?? $member['name'], - "icon" => getAsset($member["system"], $member["id"], "heads"), - "invert" => false, - "link" => "/$member[name]", - "stepped" => null, - "private" => false - ]; - }, array_filter(scoreOrder(withTravelers(json_decode(file_get_contents($_SERVER['DOCUMENT_ROOT'] . "/includes/data/gdapd/members.json"), true), "gdapd"), "gdapd"), function ($member) { - return $member['name'] !== "unknown" && $member['name'] !== "fusion" && $member['name'] !== "new"; - })) + "items" => $cache["raindrops"][$isLoggedIn || $isLowerLoggedIn ? "private" : "public"] ] ] ]; diff --git a/includes/components/pane.inc b/includes/components/pane.inc index eb735f5..1ecbcdf 100644 --- a/includes/components/pane.inc +++ b/includes/components/pane.inc @@ -22,8 +22,9 @@ foreach ($list as $color) { </div> <?php if ($isLoggedIn || $isLowerLoggedIn): ?> - <a onclick="toggleGlobalSearch();" id="login-link" class="login-link-clickable"> - <?= $lang["navigation"]["search"] ?> + <a href="/-/logout" id="login-link" class="login-link-clickable"> + <img alt="" src="/assets/icons/logout.svg" style="filter:invert(1);width:24px;vertical-align: middle;"> + <span style="vertical-align: middle;"><?= $pages["logout"]["name"]["en"] ?></span> </a> <?php else: ?> <a href="/-/login" id="login-link" class="login-link-clickable"> diff --git a/includes/components/search.inc b/includes/components/search.inc deleted file mode 100644 index 278ec41..0000000 --- a/includes/components/search.inc +++ /dev/null @@ -1,534 +0,0 @@ -<?php global $lang; global $pages; global $isLowerLoggedIn; global $isLoggedIn; ?> - -<div id="global-search-container" style="display: none; position: fixed; z-index: 99999999;background-color: rgba(0, 0, 0, .75); inset: 0; backdrop-filter: blur(10px); -webkit-backdrop-filter: blur(10px); align-items: center; justify-content: center;"> - <div id="global-search-box" style="background: rgba(50, 50, 50, .5); color: white; backdrop-filter: blur(30px); -webkit-backdrop-filter: blur(30px); border-radius: 15px; width: 768px; max-width: 90vw;"> - <div id="global-search-input-container" onclick="document.getElementById('global-search-input').focus();" style="cursor:text;padding: 10px 50px; font-size: 22px; border: 1px solid rgba(100, 100, 100, .5); border-top-left-radius: 15px; border-top-right-radius: 15px; width: 768px; max-width: 90vw;"> - <span onchange="globalSearchPlaceholder(); globalSearch();" onkeyup="globalSearchPlaceholder(); globalSearch();" onkeydown="globalSearchPlaceholder(); globalSearch();" type="text" id="global-search-input" style="vertical-align: middle; display:inline-block; background: transparent; color: white; border: none;" spellcheck="false" contenteditable="true"></span><span id="global-search-placeholder" style="opacity:.5;"><?= $lang["search"]["title"] ?></span><span id="global-search-autocomplete" style="vertical-align: middle; opacity:.5;"></span><span id="global-search-action" style="vertical-align: middle; opacity:.5;font-size:16px;"></span> - </div> - <div id="global-search-results" style="border-bottom-left-radius: 15px; border-bottom-right-radius: 15px; border-top-style: none; border-right: 1px solid rgba(100, 100, 100, .5); border-bottom: 1px solid rgba(100, 100, 100, .5); border-left: 1px solid rgba(100, 100, 100, .5); width: 768px; max-width: 90vw; height: 400px; max-height: calc(90vh - 60px);"> - <div id="global-search-intro" style="display: flex; align-items: center; justify-content: center; height: 100%; text-align: center;"> - <div style="opacity: .5;"> - <img src="/assets/logo/newlogo<?= $isLoggedIn || $isLowerLoggedIn ? "3" : "" ?>.png" style="width: 64px; height: 64px; margin-bottom: 10px;"> - <p><?= $lang["search"]["placeholder"] ?></p> - </div> - </div> - <div id="global-search-list" style="overflow: auto; display: flex; align-items: center; justify-content: center; height: 100%; text-align: center;"></div> - </div> - </div> -</div> - -<script src="/assets/editor/fuse.js"></script> - -<!--suppress JSUnresolvedFunction --> -<script> - const pages_list = JSON.parse(atob(`<?php - - $base = array_values(array_filter(scandir($_SERVER['DOCUMENT_ROOT'] . "/pages"), function ($i) { - return !str_starts_with($i, ".") && $i !== "page.inc" && $i !== "api.inc" && $i !== "demo.inc" && $i !== "logout.inc" && $i !== "edit.inc" && $i !== "metadata.inc" && $i !== "edit-private.inc" && $i !== "app.inc" && !str_ends_with($i, ".bak.php") && !str_ends_with($i, ".old.php") && !str_ends_with($i, "-dev.php") && !str_ends_with($i, ".bak.inc") && !str_ends_with($i, ".old.inc") && !str_ends_with($i, "-dev.inc"); - })); - $list = array_values(array_filter(array_map(function ($i) use ($lang) { - global $pages; - global $isLoggedIn; - global $isLowerLoggedIn; - - if (in_array(substr($i, 0, strlen($i) - 4), array_keys($pages)) && $pages[substr($i, 0, strlen($i) - 4)]["admin"] && !((!$pages[substr($i, 0, strlen($i) - 4)]["limited"] && $isLoggedIn) || ($pages[substr($i, 0, strlen($i) - 4)]["limited"] && $isLowerLoggedIn))) { - return null; - } else if (in_array(substr($i, 0, strlen($i) - 4), array_keys($pages))) { - return [ - 'name' => in_array(substr($i, 0, strlen($i) - 4), array_keys($pages)) ? $pages[substr($i, 0, strlen($i) - 4)]["name"][$lang["_name"]] : substr($i, 0, strlen($i) - 4), - 'description' => in_array(substr($i, 0, strlen($i) - 4), array_keys($pages)) ? ($pages[substr($i, 0, strlen($i) - 4)]["short"] ?? $pages[substr($i, 0, strlen($i) - 4)]["name"][$lang["_name"]]) : substr($i, 0, strlen($i) - 4), - 'url' => "/-/" . substr($i, 0, strlen($i) - 4), - 'icon' => file_exists($_SERVER['DOCUMENT_ROOT'] . "/assets/icons/uncolored/" . substr($i, 0, strlen($i) - 4) . ".svg") ? ("/assets/icons/uncolored/" . (file_exists($_SERVER['DOCUMENT_ROOT'] . "/assets/icons/uncolored/" . substr($i, 0, strlen($i) - 4) . ".svg") ? substr($i, 0, strlen($i) - 4) : "") . ".svg") : ("/assets/icons/" . (file_exists($_SERVER['DOCUMENT_ROOT'] . "/assets/icons/" . substr($i, 0, strlen($i) - 4) . ".svg") ? substr($i, 0, strlen($i) - 4) : "") . ".svg"), - 'invert' => true - ]; - } else { - return null; - } - }, $base), function ($i) { - return isset($i); - })); - - echo(base64_encode(json_encode($list))); - - ?>`)); - const pages = new Fuse(pages_list, { - includeScore: true, - keys: [ - { - name: 'name', - weight: 0.7 - }, - { - name: 'description', - weight: 0.5 - }, - { - name: 'url', - weight: 0.2 - } - ] - }) - - const ponies_list = JSON.parse(atob(`<?php - - $base = array_values(scoreOrderGlobal()); - $list = array_map(function ($i) { - return [ - 'name' => $i["display_name"] ?? $i["name"], - 'description' => file_exists($_SERVER['DOCUMENT_ROOT'] . "/includes/data/content/$i[id].html") ? strip_tags(file_get_contents($_SERVER['DOCUMENT_ROOT'] . "/includes/data/content/$i[id].html")) : "", - 'url' => '/' . $i["name"], - 'icon' => getAsset($i["system"], $i["id"], "heads"), - 'invert' => false - ]; - }, $base); - - echo(base64_encode(json_encode($list))); - - ?>`)); - const ponies = new Fuse(ponies_list, { - includeScore: true, - keys: [ - { - name: 'name', - weight: 1 - }, - { - name: 'description', - weight: 0.7 - }, - { - name: 'url', - weight: 0.5 - } - ] - }) - - const toys_list = JSON.parse(atob(`<?php - - global $isLoggedIn; - - if (false && $isLoggedIn) { - $base = array_values(json_decode(file_get_contents($_SERVER['DOCUMENT_ROOT'] . "/includes/data/toys/toys.json"), true)); - $list = array_map(function ($i) { - return [ - 'name' => $i["name"], - 'description' => $i["description"], - 'icon' => "/assets/icons/toys.svg", - 'url' => "/-/toys/$i[id]", - 'invert' => true - ]; - }, $base); - - echo(base64_encode(json_encode($list))); - } else { - echo(base64_encode(json_encode([]))); - } - - ?>`)); - const toys = new Fuse(toys_list, { - includeScore: true, - keys: [ - { - name: 'name', - weight: 1 - }, - { - name: 'description', - weight: 0.7 - }, - { - name: 'url', - weight: 0.5 - } - ] - }) - - const actions_list = JSON.parse(atob(`<?php - - global $isLoggedIn; - - if (false && $isLoggedIn) { - $base = array_values(json_decode(file_get_contents($_SERVER['DOCUMENT_ROOT'] . "/includes/data/actions/actions.json"), true)); - $list = array_map(function ($i) { - return [ - 'name' => $i["name"], - 'description' => $i["description"], - 'icon' => "/assets/icons/actions.svg", - 'url' => "/-/actions/$i[id]", - 'invert' => true - ]; - }, $base); - - echo(base64_encode(json_encode($list))); - } else { - echo(base64_encode(json_encode([]))); - } - - ?>`)); - const actions = new Fuse(actions_list, { - includeScore: true, - keys: [ - { - name: 'name', - weight: 1 - }, - { - name: 'description', - weight: 0.7 - }, - { - name: 'url', - weight: 0.5 - } - ] - }) - - const documents_list = JSON.parse(atob(`<?php - - global $isLoggedIn; - - if ($isLoggedIn) { - $base = array_values(array_map(function ($i) { - return [ - "id" => substr($i, 0, -5), - ...(json_decode(file_get_contents($_SERVER['DOCUMENT_ROOT'] . "/includes/data/docs/" . $i), true) ?? []) - ]; - }, array_filter(scandir($_SERVER['DOCUMENT_ROOT'] . "/includes/data/docs"), function ($i) { - return !str_starts_with($i, ".") && str_ends_with($i, ".json"); - }))); - $list = array_map(function ($i) { - return [ - 'name' => $i["name"], - 'content' => strip_tags($i["contents"]), - 'category' => $i["category"], - 'icon' => "/assets/icons/docs.svg", - 'url' => "/-/docs/$i[id]", - 'invert' => true - ]; - }, $base); - - echo(base64_encode(json_encode($list))); - } else { - echo(base64_encode(json_encode([]))); - } - - ?>`)); - const documents = new Fuse(documents_list, { - includeScore: true, - keys: [ - { - name: 'name', - weight: 1 - }, - { - name: 'category', - weight: 0.7 - }, - { - name: 'content', - weight: 0.4 - }, - { - name: 'url', - weight: 0.5 - } - ] - }) - - window.shiftPresses = 0; - window.searchBoxOpen = false; - window.lastKnownSearchQuery = null; - - function toggleGlobalSearch() { - window.shiftPresses = 0; - console.log("Search!"); - - if (document.getElementById("global-search-container").style.display === "none") { - document.getElementById("global-search-container").style.display = "flex"; - document.getElementById("global-search-list").style.display = "none"; - document.getElementById("global-search-intro").style.display = "flex"; - document.getElementById("global-search-input").focus(); - document.getElementById("global-search-input").value = ""; - window.searchBoxOpen = true; - } else if (document.getElementById("global-search-container").style.display === "flex") { - document.getElementById("global-search-container").style.display = "none"; - window.searchBoxOpen = false; - } - } - - function globalSearchPlaceholder() { - if (document.getElementById("global-search-input").innerText === "") { - document.getElementById("global-search-placeholder").style.display = ""; - document.getElementById("global-search-autocomplete").innerText = ""; - document.getElementById("global-search-action").innerText = ""; - } else { - document.getElementById("global-search-placeholder").style.display = "none"; - } - } - - function globalSearchAutocomplete(firstResult) { - let querySearch = document.getElementById("global-search-input").innerText.toLowerCase(); - let firstResultSearch = firstResult.name.toLowerCase(); - let isAutocomplete = true; - - if (firstResultSearch.length > querySearch.length) { - let count = 0; - - for (let i = 0; i < querySearch.length; i++) { - if (querySearch.substring(i, i + 1) === firstResultSearch.substring(i, i + 1)) { - count++; - } else { - isAutocomplete = false; - } - } - - if (isAutocomplete) { - document.getElementById("global-search-autocomplete").innerText = firstResult.name.substring(count); - document.getElementById("global-search-action").innerText = " — <?= $lang["search"]["view"] ?>"; - } else { - document.getElementById("global-search-autocomplete").innerText = ""; - document.getElementById("global-search-action").innerText = " — " + firstResult.name; - } - } else { - document.getElementById("global-search-autocomplete").innerText = ""; - document.getElementById("global-search-action").innerText = ""; - } - } - - function globalSearch() { - let query = document.getElementById("global-search-input").innerText.trim(); - - if (query !== lastKnownSearchQuery) { - window.lastKnownSearchQuery = query; - } else { - return; - } - - let results, scores; - let categories = []; - console.log("Query:", query); - - if (query.trim() === "") { - document.getElementById("global-search-list").style.display = "none"; - document.getElementById("global-search-intro").style.display = "flex"; - return; - } else { - document.getElementById("global-search-list").style.display = "block"; - document.getElementById("global-search-intro").style.display = "none"; - } - - results = ponies.search(query).map((i) => { - i.item.score = i.score; - return i.item; - }); - scores = results.map((i) => { return i.score; }); - let results_ponies = { - category: { - name: "<?= $lang["search"]["categories"][0] ?>", - id: "ponies" - }, - average: scores.length > 0 ? scores.reduce((a, b) => { return a + b; }) / results.length : 1, - results - }; - - results = pages.search(query).map((i) => { - i.item.score = i.score; - return i.item; - }); - scores = results.map((i) => { return i.score; }); - let results_pages = { - category: { - name: "<?= $lang["search"]["categories"][1] ?>", - id: "pages" - }, - average: scores.length > 0 ? scores.reduce((a, b) => { return a + b; }) / results.length : 1, - results - }; - - results = actions.search(query).map((i) => { - i.item.score = i.score; - return i.item; - }); - scores = results.map((i) => { return i.score; }); - let results_actions = { - category: { - name: "<?= $lang["search"]["categories"][2] ?>", - id: "actions" - }, - average: scores.length > 0 ? scores.reduce((a, b) => { return a + b; }) / results.length : 1, - results - }; - - results = documents.search(query).map((i) => { - i.item.score = i.score; - return i.item; - }); - scores = results.map((i) => { return i.score; }); - let results_documents = { - category: { - name: "<?= $lang["search"]["categories"][3] ?>", - id: "docs" - }, - average: scores.length > 0 ? scores.reduce((a, b) => { return a + b; }) / results.length : 1, - results - }; - - results = toys.search(query).map((i) => { - i.item.score = i.score; - return i.item; - }); - scores = results.map((i) => { return i.score; }); - let results_toys = { - category: { - name: "<?= $lang["search"]["categories"][4] ?>", - id: "toys" - }, - average: scores.length > 0 ? scores.reduce((a, b) => { return a + b; }) / results.length : 1, - results - }; - - window.allSearchResults = []; - categories.push(results_ponies, results_pages, results_documents, results_actions, results_toys); - categories = categories.sort((a, b) => { - return a.average - b.average; - }).filter((i) => i.results.length > 0); - - console.log(categories); - - index = -1; - document.getElementById("global-search-list").innerHTML = categories.map((i) => ` - <div class="global-search-category"> - <div class="global-search-category-header">${i.category.name}</div> - <div class="global-search-category-items"> - ${i.results.map((j) => { index++; allSearchResults.push(j); return ` - <a href="${j.url}" class="global-search-item ${index === 0 ? 'selected' : ''}" id="global-search-item-${index}"> - <img src="${j.icon}" class="global-search-item-icon" ${j['invert'] ? 'style="filter:invert(1) brightness(5);"' : ""}> - <span class="global-search-item-title">${j.name}</span> - </a> - ` }).join("")} - </div> - </div> - `).join(""); - - globalSearchAutocomplete(allSearchResults[0]); - - console.log("================================="); - } - - document.onkeydown = (event) => { - if (window.searchBoxOpen) { - console.log(event); - - if (event.key === "Escape") { - if (document.getElementById("global-search-input").innerText.trim() === "") { - toggleGlobalSearch(); - } else { - document.getElementById("global-search-input").innerText = ""; - globalSearch(); - } - } - - if (event.key === "ArrowDown") { - let id = parseInt(document.querySelector(".global-search-item.selected").id.split("-")[3]); - - if (document.getElementById("global-search-item-" + (id + 1)) !== null) { - document.getElementById("global-search-item-" + id).classList.remove("selected"); - document.getElementById("global-search-item-" + (id + 1)).classList.add("selected"); - document.getElementById("global-search-item-" + (id + 1)).scrollIntoView({ - block: "center", - inline: "center" - }); - - globalSearchAutocomplete(allSearchResults[id + 1]); - } - - event.preventDefault(); - } - - if (event.key === "ArrowUp") { - let id = parseInt(document.querySelector(".global-search-item.selected").id.split("-")[3]); - - if (document.getElementById("global-search-item-" + (id - 1)) !== null) { - document.getElementById("global-search-item-" + id).classList.remove("selected"); - document.getElementById("global-search-item-" + (id - 1)).classList.add("selected"); - document.getElementById("global-search-item-" + (id - 1)).scrollIntoView({ - block: "center", - inline: "center" - }); - - globalSearchAutocomplete(allSearchResults[id - 1]); - } - - event.preventDefault(); - } - - if (event.key === "Enter") { - document.querySelector(".global-search-item.selected").click(); - - event.preventDefault(); - } - } - - if (event.key === "Shift") { - window.shiftPresses++; - } - - if ((event.code === "Space" && event.ctrlKey) || window.shiftPresses === 2 && document.getElementsByClassName("ck-focused").length === 0) { - toggleGlobalSearch(); - } - } - - document.getElementById("global-search-container").onclick = (event) => { - if (event.target === document.getElementById("global-search-container")) toggleGlobalSearch(); - } - - setInterval(() => { - window.shiftPresses = 0; - }, 500); -</script> - -<style> - .global-search-category { - text-align: left; - padding: 10px 20px; - } - - .global-search-category-header { - font-size: 12px; - opacity: .5; - margin-bottom: 5px; - margin-top: 10px; - } - - .global-search-item-icon { - vertical-align: middle; - width: 24px; - height: 24px; - margin-right: 5px; - } - - .global-search-item-title { - vertical-align: middle; - } - - .global-search-item { - text-decoration: none; - display: block; - color: white !important; - border-radius: 10px; - padding: 3px 5px; - height: 32px; - } - - .global-search-item:hover, .global-search-item:focus, .global-search-item.selected { - background-color: rgba(255, 255, 255, .1); - } - - .global-search-item:active { - background-color: rgba(255, 255, 255, .2); - } - - #global-search-container * { - outline: none !important; - } -</style>
\ No newline at end of file diff --git a/includes/components/wakeup.inc b/includes/components/wakeup.inc index 818378a..cc54821 100644 --- a/includes/components/wakeup.inc +++ b/includes/components/wakeup.inc @@ -104,7 +104,7 @@ if (window.alertIntervalCounter === 0) { sendNotification(); } else if (window.alertIntervalCounter > -1) { - document.getElementById("next-notification").innerText = window.alertIntervalCounter + " second" + (window.alertIntervalCounter > 1 ? "s" : ""); + document.getElementById("next-notification").innerText = "in " + window.alertIntervalCounter + " second" + (window.alertIntervalCounter > 1 ? "s" : ""); } }, 1000); } diff --git a/includes/external/chvfs/index.js b/includes/external/chvfs/index.js new file mode 100644 index 0000000..0dfd958 --- /dev/null +++ b/includes/external/chvfs/index.js @@ -0,0 +1,104 @@ +let active = true; +let queue = []; + +const watch = require('node-watch'); +const child_process = require('child_process'); +const fs = require('fs').promises; +const fss = require('fs'); + +process.on('uncaughtException', (e) => { + console.error(e); +}); + +function start() { + console.log("Mounting chvfs..."); + child_process.execSync("mount -t tmpfs -o size=1G chvfs /_ch"); + console.log("Mounted chvfs to /_ch"); + + console.log("Preparing filesystem..."); + child_process.execSync("cp -r /opt/peh_save/* /_ch"); + child_process.execSync("chmod -Rf 777 /_ch"); + console.log("Filesystem is ready"); + + console.log("Watching for changes..."); + watch("/_ch", { recursive: true }, (event, filename) => { + try { + if (!active || !filename) return; + + if (event === "update") { + console.log(filename + " was created or affected"); + + queue.push({ + file: filename, + remove: false + }); + } else if (event === "remove") { + console.log(filename + " was dropped"); + + queue.push({ + file: filename, + remove: true + }); + } + } catch (e) { + console.error(e); + } + }) +} + +function stop() { + active = false; + + console.log("Unmounting chvfs..."); + child_process.execSync("umount -l /_ch"); + console.log("Unmounted chvfs"); +} + +start(); +setInterval(async () => { + for (let item of queue) { + try { + if (item.remove) { + console.log("Dropping " + item.file); + await fs.unlink("/opt/peh_save/" + item.file.substring(5)); + } else { + console.log("Copying " + item.file); + await fs.copyFile(item.file, "/opt/peh_save/" + item.file.substring(5)); + } + } catch (e) { + console.error(e); + } + + queue.splice(0, 1); + } +}); + +process.on('exit', () => { + process.stdout.write("\n"); + + for (let item of queue) { + try { + if (item.remove) { + console.log("Dropping " + item.file); + fss.unlinkSync("/opt/peh_save/" + item.file.substring(5)); + } else { + console.log("Copying " + item.file); + fss.copyFileSync(item.file, "/opt/peh_save/" + item.file.substring(5)); + } + } catch (e) { + console.error(e); + } + + queue.splice(0, 1); + } + + stop(); +}); + +process.on('SIGINT', () => { + process.exit(); +}); + +process.on('SIGTERM', () => { + process.exit(); +});
\ No newline at end of file diff --git a/includes/external/chvfs/node_modules/.package-lock.json b/includes/external/chvfs/node_modules/.package-lock.json new file mode 100644 index 0000000..6f51c8f --- /dev/null +++ b/includes/external/chvfs/node_modules/.package-lock.json @@ -0,0 +1,15 @@ +{ + "name": "chvfs", + "lockfileVersion": 2, + "requires": true, + "packages": { + "node_modules/node-watch": { + "version": "0.7.3", + "resolved": "https://registry.npmjs.org/node-watch/-/node-watch-0.7.3.tgz", + "integrity": "sha512-3l4E8uMPY1HdMMryPRUAl+oIHtXtyiTlIiESNSVSNxcPfzAFzeTbXFQkZfAwBbo0B1qMSG8nUABx+Gd+YrbKrQ==", + "engines": { + "node": ">=6" + } + } + } +} diff --git a/includes/external/chvfs/node_modules/node-watch/LICENSE b/includes/external/chvfs/node_modules/node-watch/LICENSE new file mode 100644 index 0000000..3718eaa --- /dev/null +++ b/includes/external/chvfs/node_modules/node-watch/LICENSE @@ -0,0 +1,22 @@ +(The MIT License) + +Copyright (c) 2012-2021 Yuan Chuan <yuanchuan23@gmail.com> + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +'Software'), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/includes/external/chvfs/node_modules/node-watch/README.md b/includes/external/chvfs/node_modules/node-watch/README.md new file mode 100644 index 0000000..c0f8bd2 --- /dev/null +++ b/includes/external/chvfs/node_modules/node-watch/README.md @@ -0,0 +1,233 @@ +# node-watch [![Status](https://github.com/yuanchuan/node-watch/actions/workflows/ci.yml/badge.svg)](https://github.com/yuanchuan/node-watch/actions/workflows/ci.yml/badge.svg) + +A wrapper and enhancements for [fs.watch](http://nodejs.org/api/fs.html#fs_fs_watch_filename_options_listener). + +[![NPM](https://nodei.co/npm/node-watch.png?downloads=true&downloadRank=true&stars=true)](https://nodei.co/npm/node-watch.png/) + + +## Installation + +```bash +npm install node-watch +``` + +## Example + +```js +var watch = require('node-watch'); + +watch('file_or_dir', { recursive: true }, function(evt, name) { + console.log('%s changed.', name); +}); +``` + +Now it's fast to watch **deep** directories on macOS and Windows, since the `recursive` option is natively supported except on Linux. + +```js +// watch the whole disk +watch('/', { recursive: true }, console.log); +``` + + +## Why? + +* Some editors will generate temporary files which will cause the callback function to be triggered multiple times. +* The callback function will only be triggered once on watching a single file. +* <del>Missing an option to watch a directory recursively.</del> +* Recursive watch is not supported on Linux or in older versions of nodejs. +* Keep it simple, stupid. + + +## Options + +The usage and options of `node-watch` are compatible with [fs.watch](https://nodejs.org/dist/latest-v7.x/docs/api/fs.html#fs_fs_watch_filename_options_listener). +* `persistent: Boolean` (default **true**) +* `recursive: Boolean` (default **false**) +* `encoding: String` (default **'utf8'**) + +**Extra options** + +* `filter: RegExp | Function` + + Return that matches the filter expression. + + ```js + // filter with regular expression + watch('./', { filter: /\.json$/ }); + + // filter with custom function + watch('./', { filter: f => !/node_modules/.test(f) }); + + ``` + + Each file and directory will be passed to the filter to determine whether + it will then be passed to the callback function. Like `Array.filter` does in `JavaScript`. + There are three kinds of return values for filter function: + + * **`true`**: Will be passed to callback. + * **`false`**: Will not be passed to callback. + * **`skip`**: Same with `false`, and skip to watch all its subdirectories. + + On Linux, where the `recursive` option is not natively supported, + it is more efficient to skip ignored directories by returning the `skip` flag: + + ```js + watch('./', { + recursive: true, + filter(f, skip) { + // skip node_modules + if (/\/node_modules/.test(f)) return skip; + // skip .git folder + if (/\.git/.test(f)) return skip; + // only watch for js files + return /\.js$/.test(f); + } + }); + + ``` + + If you prefer glob patterns you can use [minimatch](https://www.npmjs.com/package/minimatch) or [picomatch](https://www.npmjs.com/package/picomatch) + together with filter: + + ```js + const pm = require('picomatch'); + let isMatch = pm('*.js'); + + watch('./', { + filter: f => isMatch(f) + }); + ``` + +* `delay: Number` (in ms, default **200**) + + Delay time of the callback function. + + ```js + // log after 5 seconds + watch('./', { delay: 5000 }, console.log); + ``` + +## Events + +The events provided by the callback function is either `update` or `remove`, which is less confusing to `fs.watch`'s `rename` or `change`. + +```js +watch('./', function(evt, name) { + + if (evt == 'update') { + // on create or modify + } + + if (evt == 'remove') { + // on delete + } + +}); +``` + + +## Watcher object + +The watch function returns a [fs.FSWatcher](https://nodejs.org/api/fs.html#fs_class_fs_fswatcher) like object as the same as `fs.watch` (>= v0.4.0). + +#### Watcher events + +```js +let watcher = watch('./', { recursive: true }); + +watcher.on('change', function(evt, name) { + // callback +}); + +watcher.on('error', function(err) { + // handle error +}); + +watcher.on('ready', function() { + // the watcher is ready to respond to changes +}); +``` + +#### Close + +```js +// close +watcher.close(); + +// is closed? +watcher.isClosed() +``` + +#### List of methods + +* `.on` +* `.once` +* `.emit` +* `.close` +* `.listeners` +* `.setMaxListeners` +* `.getMaxListeners` + +##### Extra methods +* `.isClosed` detect if the watcher is closed +* `.getWatchedPaths` get all the watched paths + + +## Known issues + +**Windows, node < v4.2.5** + + * Failed to detect `remove` event + * Failed to get deleted filename or directory name + +**MacOS, node 0.10.x** + * Will emit double event if the directory name is of one single character. + + +## Misc + +#### 1. Watch multiple files or directories in one place +```js +watch(['file1', 'file2'], console.log); +``` + +#### 2. Customize watch command line tool +```js +#!/usr/bin/env node + +// https://github.com/nodejs/node-v0.x-archive/issues/3211 +require('epipebomb')(); + +let watcher = require('node-watch')( + process.argv[2] || './', { recursive: true }, console.log +); + +process.on('SIGINT', watcher.close); +``` +Monitoring chrome from disk: +```bash +$ watch / | grep -i chrome +``` + +#### 3. Got ENOSPC error? + +If you get ENOSPC error, but you actually have free disk space - it means that your OS watcher limit is too low and you probably want to recursively watch a big tree of files. + +Follow this description to increase the limit: +[https://confluence.jetbrains.com/display/IDEADEV/Inotify+Watches+Limit](https://confluence.jetbrains.com/display/IDEADEV/Inotify+Watches+Limit) + + +## Alternatives + +* [chokidar](https://github.com/paulmillr/chokidar) +* [gaze](https://github.com/shama/gaze) +* [mikeal/watch](https://github.com/mikeal/watch) + +## Contributors + +Thanks goes to [all wonderful people](https://github.com/yuanchuan/node-watch/graphs/contributors) who have helped this project. + +## License +MIT + +Copyright (c) 2012-2021 [yuanchuan](https://github.com/yuanchuan) diff --git a/includes/external/chvfs/node_modules/node-watch/lib/has-native-recursive.js b/includes/external/chvfs/node_modules/node-watch/lib/has-native-recursive.js new file mode 100644 index 0000000..19c1b88 --- /dev/null +++ b/includes/external/chvfs/node_modules/node-watch/lib/has-native-recursive.js @@ -0,0 +1,115 @@ +var fs = require('fs'); +var os = require('os'); +var path = require('path'); +var is = require('./is'); + +var IS_SUPPORT; +var TEMP_DIR = os.tmpdir && os.tmpdir() + || process.env.TMPDIR + || process.env.TEMP + || process.cwd(); + +function TempStack() { + this.stack = []; +} + +TempStack.prototype = { + create: function(type, base) { + var name = path.join(base, + 'node-watch-' + Math.random().toString(16).substr(2) + ); + this.stack.push({ name: name, type: type }); + return name; + }, + write: function(/* file */) { + for (var i = 0; i < arguments.length; ++i) { + fs.writeFileSync(arguments[i], ' '); + } + }, + mkdir: function(/* dirs */) { + for (var i = 0; i < arguments.length; ++i) { + fs.mkdirSync(arguments[i]); + } + }, + cleanup: function(fn) { + try { + var temp; + while ((temp = this.stack.pop())) { + var type = temp.type; + var name = temp.name; + if (type === 'file' && is.file(name)) { + fs.unlinkSync(name); + } + else if (type === 'dir' && is.directory(name)) { + fs.rmdirSync(name); + } + } + } + finally { + if (is.func(fn)) fn(); + } + } +}; + +var pending = false; + +module.exports = function hasNativeRecursive(fn) { + if (!is.func(fn)) { + return false; + } + if (IS_SUPPORT !== undefined) { + return fn(IS_SUPPORT); + } + + if (!pending) { + pending = true; + } + // check again later + else { + return setTimeout(function() { + hasNativeRecursive(fn); + }, 300); + } + + var stack = new TempStack(); + var parent = stack.create('dir', TEMP_DIR); + var child = stack.create('dir', parent); + var file = stack.create('file', child); + + stack.mkdir(parent, child); + + var options = { recursive: true }; + var watcher; + + try { + watcher = fs.watch(parent, options); + } catch (e) { + if (e.code == 'ERR_FEATURE_UNAVAILABLE_ON_PLATFORM') { + return fn(IS_SUPPORT = false); + } else { + throw e; + } + } + + if (!watcher) { + return false; + } + + var timer = setTimeout(function() { + watcher.close(); + stack.cleanup(function() { + fn(IS_SUPPORT = false); + }); + }, 200); + + watcher.on('change', function(evt, name) { + if (path.basename(file) === path.basename(name)) { + watcher.close(); + clearTimeout(timer); + stack.cleanup(function() { + fn(IS_SUPPORT = true); + }); + } + }); + stack.write(file); +} diff --git a/includes/external/chvfs/node_modules/node-watch/lib/is.js b/includes/external/chvfs/node_modules/node-watch/lib/is.js new file mode 100644 index 0000000..ebe0600 --- /dev/null +++ b/includes/external/chvfs/node_modules/node-watch/lib/is.js @@ -0,0 +1,78 @@ +var fs = require('fs'); +var path = require('path'); +var os = require('os'); + +function matchObject(item, str) { + return Object.prototype.toString.call(item) + === '[object ' + str + ']'; +} + +function checkStat(name, fn) { + try { + return fn(name); + } catch (err) { + if (/^(ENOENT|EPERM|EACCES)$/.test(err.code)) { + if (err.code !== 'ENOENT') { + console.warn('Warning: Cannot access %s', name); + } + return false; + } + throw err; + } +} + +var is = { + nil: function(item) { + return item == null; + }, + array: function(item) { + return Array.isArray(item); + }, + emptyObject: function(item) { + for (var key in item) { + return false; + } + return true; + }, + buffer: function(item) { + return Buffer.isBuffer(item); + }, + regExp: function(item) { + return matchObject(item, 'RegExp'); + }, + string: function(item) { + return matchObject(item, 'String'); + }, + func: function(item) { + return typeof item === 'function'; + }, + number: function(item) { + return matchObject(item, 'Number'); + }, + exists: function(name) { + return fs.existsSync(name); + }, + file: function(name) { + return checkStat(name, function(n) { + return fs.statSync(n).isFile() + }); + }, + samePath: function(a, b) { + return path.resolve(a) === path.resolve(b); + }, + directory: function(name) { + return checkStat(name, function(n) { + return fs.statSync(n).isDirectory() + }); + }, + symbolicLink: function(name) { + return checkStat(name, function(n) { + return fs.lstatSync(n).isSymbolicLink(); + }); + }, + windows: function() { + return os.platform() === 'win32'; + } +}; + +module.exports = is; diff --git a/includes/external/chvfs/node_modules/node-watch/lib/watch.d.ts b/includes/external/chvfs/node_modules/node-watch/lib/watch.d.ts new file mode 100644 index 0000000..9eca5d4 --- /dev/null +++ b/includes/external/chvfs/node_modules/node-watch/lib/watch.d.ts @@ -0,0 +1,75 @@ +import { FSWatcher } from 'fs'; + +/** + * Watch for changes on `filename`, where filename is either a file or a directory. + * The second argument is optional. + * + * If `options` is provided as a string, it specifies the encoding. + * Otherwise `options` should be passed as an object. + * + * The listener callback gets two arguments, `(eventType, filePath)`, + * which is the same with `fs.watch`. + * `eventType` is either `update` or `remove`, + * `filePath` is the name of the file which triggered the event. + * + * @param {Filename} filename File or directory to watch. + * @param {Options|string} options + * @param {Function} callback + */ +declare function watch(pathName: PathName): Watcher; +declare function watch(pathName: PathName, options: Options) : Watcher; +declare function watch(pathName: PathName, callback: Callback): Watcher; +declare function watch(pathName: PathName, options: Options, callback: Callback): Watcher; + +type EventType = 'update' | 'remove'; +type Callback = (eventType: EventType, filePath: string) => any; +type PathName = string | Array<string>; +type FilterReturn = boolean | symbol; + +type Options = { + /** + * Indicates whether the process should continue to run + * as long as files are being watched. + * @default true + */ + persistent ?: boolean; + + /** + * Indicates whether all subdirectories should be watched. + * @default false + */ + recursive ?: boolean; + + /** + * Specifies the character encoding to be used for the filename + * passed to the listener. + * @default 'utf8' + */ + encoding ?: string; + + /** + * Only files which pass this filter (when it returns `true`) + * will be sent to the listener. + */ + filter ?: RegExp | ((file: string, skip: symbol) => FilterReturn); + + /** + * Delay time of the callback function. + * @default 200 + */ + delay ?: number; +}; + +declare interface Watcher extends FSWatcher { + /** + * Returns `true` if the watcher has been closed. + */ + isClosed(): boolean; + + /** + * Returns all watched paths. + */ + getWatchedPaths(): Array<string>; +} + +export default watch; diff --git a/includes/external/chvfs/node_modules/node-watch/lib/watch.js b/includes/external/chvfs/node_modules/node-watch/lib/watch.js new file mode 100644 index 0000000..b3d6889 --- /dev/null +++ b/includes/external/chvfs/node_modules/node-watch/lib/watch.js @@ -0,0 +1,530 @@ +var fs = require('fs'); +var path = require('path'); +var util = require('util'); +var events = require('events'); + +var hasNativeRecursive = require('./has-native-recursive'); +var is = require('./is'); + +var EVENT_UPDATE = 'update'; +var EVENT_REMOVE = 'remove'; + +var SKIP_FLAG = Symbol('skip'); + +function hasDup(arr) { + return arr.some(function(v, i, self) { + return self.indexOf(v) !== i; + }); +} + +function unique(arr) { + return arr.filter(function(v, i, self) { + return self.indexOf(v) === i; + }); +} + +// One level flat +function flat1(arr) { + return arr.reduce(function(acc, v) { + return acc.concat(v); + }, []); +} + +function assertEncoding(encoding) { + if (encoding && encoding !== 'buffer' && !Buffer.isEncoding(encoding)) { + throw new Error('Unknown encoding: ' + encoding); + } +} + +function guard(fn) { + if (is.func(fn)) { + return function(arg, action) { + if (fn(arg, false)) action(); + } + } + if (is.regExp(fn)) { + return function(arg, action) { + if (fn.test(arg)) action(); + } + } + return function(arg, action) { + action(); + } +} + +function composeMessage(names) { + return names.map(function(n) { + return is.exists(n) + ? [EVENT_UPDATE, n] + : [EVENT_REMOVE, n]; + }); +} + +function getMessages(cache) { + var filtered = unique(cache); + + // Saving file from an editor? If so, assuming the + // non-existed files in the cache are temporary files + // generated by an editor and thus be filtered. + var reg = /~$|^\.#|^##$/g; + var hasSpecialChar = cache.some(function(c) { + return reg.test(c); + }); + + if (hasSpecialChar) { + var dup = hasDup(cache.map(function(c) { + return c.replace(reg, ''); + })); + if (dup) { + filtered = filtered.filter(function(m) { + return is.exists(m); + }); + } + } + + return composeMessage(filtered); +} + +function debounce(info, fn) { + var timer, cache = []; + var encoding = info.options.encoding; + var delay = info.options.delay; + if (!is.number(delay)) { + delay = 200; + } + function handle() { + getMessages(cache).forEach(function(msg) { + msg[1] = Buffer.from(msg[1]); + if (encoding !== 'buffer') { + msg[1] = msg[1].toString(encoding); + } + fn.apply(null, msg); + }); + timer = null; + cache = []; + } + return function(rawEvt, name) { + cache.push(name); + if (!timer) { + timer = setTimeout(handle, delay); + } + } +} + +function createDupsFilter() { + var memo = {}; + return function(fn) { + return function(evt, name) { + memo[evt + name] = [evt, name]; + setTimeout(function() { + Object.keys(memo).forEach(function(n) { + fn.apply(null, memo[n]); + }); + memo = {}; + }); + } + } +} + +function getSubDirectories(dir, fn, done = function() {}) { + if (is.directory(dir)) { + fs.readdir(dir, function(err, all) { + if (err) { + // don't throw permission errors. + if (/^(EPERM|EACCES)$/.test(err.code)) { + console.warn('Warning: Cannot access %s.', dir); + } else { + throw err; + } + } + else { + all.forEach(function(f) { + var sdir = path.join(dir, f); + if (is.directory(sdir)) fn(sdir); + }); + done(); + } + }); + } else { + done(); + } +} + +function semaphore(final) { + var counter = 0; + return function start() { + counter++; + return function stop() { + counter--; + if (counter === 0) final(); + }; + }; +} + +function nullCounter() { + return function nullStop() {}; +} + +function shouldNotSkip(filePath, filter) { + // watch it only if the filter is not function + // or not being skipped explicitly. + return !is.func(filter) || filter(filePath, SKIP_FLAG) !== SKIP_FLAG; +} + +var deprecationWarning = util.deprecate( + function() {}, + '(node-watch) First param in callback function\ + is replaced with event name since 0.5.0, use\ + `(evt, filename) => {}` if you want to get the filename' +); + +function Watcher() { + events.EventEmitter.call(this); + this.watchers = {}; + this._isReady = false; + this._isClosed = false; +} + +util.inherits(Watcher, events.EventEmitter); + +Watcher.prototype.expose = function() { + var expose = {}; + var self = this; + var methods = [ + 'on', 'emit', 'once', + 'close', 'isClosed', + 'listeners', 'setMaxListeners', 'getMaxListeners', + 'getWatchedPaths' + ]; + methods.forEach(function(name) { + expose[name] = function() { + return self[name].apply(self, arguments); + } + }); + return expose; +} + +Watcher.prototype.isClosed = function() { + return this._isClosed; +} + +Watcher.prototype.close = function(fullPath) { + var self = this; + if (fullPath) { + var watcher = this.watchers[fullPath]; + if (watcher && watcher.close) { + watcher.close(); + delete self.watchers[fullPath]; + } + getSubDirectories(fullPath, function(fpath) { + self.close(fpath); + }); + } + else { + Object.keys(self.watchers).forEach(function(fpath) { + var watcher = self.watchers[fpath]; + if (watcher && watcher.close) { + watcher.close(); + } + }); + this.watchers = {}; + } + // Do not close the Watcher unless all child watchers are closed. + // https://github.com/yuanchuan/node-watch/issues/75 + if (is.emptyObject(self.watchers)) { + // should emit once + if (!this._isClosed) { + this._isClosed = true; + process.nextTick(emitClose, this); + } + } +} + +Watcher.prototype.getWatchedPaths = function(fn) { + if (is.func(fn)) { + var self = this; + if (self._isReady) { + fn(Object.keys(self.watchers)); + } else { + self.on('ready', function() { + fn(Object.keys(self.watchers)); + }); + } + } +} + +function emitReady(self) { + if (!self._isReady) { + self._isReady = true; + // do not call emit for 'ready' until after watch() has returned, + // so that consumer can call on(). + process.nextTick(function () { + self.emit('ready'); + }); + } +} + +function emitClose(self) { + self.emit('close'); +} + +Watcher.prototype.add = function(watcher, info) { + var self = this; + info = info || { fpath: '' }; + var watcherPath = path.resolve(info.fpath); + this.watchers[watcherPath] = watcher; + + // Internal callback for handling fs.FSWatcher 'change' events + var internalOnChange = function(rawEvt, rawName) { + if (self.isClosed()) { + return; + } + + // normalise lack of name and convert to full path + var name = rawName; + if (is.nil(name)) { + name = ''; + } + name = path.join(info.fpath, name); + + if (info.options.recursive) { + hasNativeRecursive(function(has) { + if (!has) { + var fullPath = path.resolve(name); + // remove watcher on removal + if (!is.exists(name)) { + self.close(fullPath); + } + // watch new created directory + else { + var shouldWatch = is.directory(name) + && !self.watchers[fullPath] + && shouldNotSkip(name, info.options.filter); + + if (shouldWatch) { + self.watchDirectory(name, info.options); + } + } + } + }); + } + + handlePublicEvents(rawEvt, name); + }; + + // Debounced based on the 'delay' option + var handlePublicEvents = debounce(info, function (evt, name) { + // watch single file + if (info.compareName) { + if (info.compareName(name)) { + self.emit('change', evt, name); + } + } + // watch directory + else { + var filterGuard = guard(info.options.filter); + filterGuard(name, function() { + if (self.flag) self.flag = ''; + else self.emit('change', evt, name); + }); + } + }); + + watcher.on('error', function(err) { + if (self.isClosed()) { + return; + } + if (is.windows() && err.code === 'EPERM') { + watcher.emit('change', EVENT_REMOVE, info.fpath && ''); + self.flag = 'windows-error'; + self.close(watcherPath); + } else { + self.emit('error', err); + } + }); + + watcher.on('change', internalOnChange); +} + +Watcher.prototype.watchFile = function(file, options, fn) { + var parent = path.join(file, '../'); + var opts = Object.assign({}, options, { + // no filter for single file + filter: null, + encoding: 'utf8' + }); + + // no need to watch recursively + delete opts.recursive; + + var watcher = fs.watch(parent, opts); + this.add(watcher, { + type: 'file', + fpath: parent, + options: Object.assign({}, opts, { + encoding: options.encoding + }), + compareName: function(n) { + return is.samePath(n, file); + } + }); + + if (is.func(fn)) { + if (fn.length === 1) deprecationWarning(); + this.on('change', fn); + } +} + +Watcher.prototype.watchDirectory = function(dir, options, fn, counter = nullCounter) { + var self = this; + var done = counter(); + hasNativeRecursive(function(has) { + // always specify recursive + options.recursive = !!options.recursive; + // using utf8 internally + var opts = Object.assign({}, options, { + encoding: 'utf8' + }); + if (!has) { + delete opts.recursive; + } + + // check if it's closed before calling watch. + if (self._isClosed) { + done(); + return self.close(); + } + + var watcher = fs.watch(dir, opts); + + self.add(watcher, { + type: 'dir', + fpath: dir, + options: options + }); + + if (is.func(fn)) { + if (fn.length === 1) deprecationWarning(); + self.on('change', fn); + } + + if (options.recursive && !has) { + getSubDirectories(dir, function(d) { + if (shouldNotSkip(d, options.filter)) { + self.watchDirectory(d, options, null, counter); + } + }, counter()); + } + + done(); + }); +} + +function composeWatcher(watchers) { + var watcher = new Watcher(); + var filterDups = createDupsFilter(); + var counter = watchers.length; + + watchers.forEach(function(w) { + w.on('change', filterDups(function(evt, name) { + watcher.emit('change', evt, name); + })); + w.on('error', function(err) { + watcher.emit('error', err); + }); + w.on('ready', function() { + if (!(--counter)) { + emitReady(watcher); + } + }); + }); + + watcher.close = function() { + watchers.forEach(function(w) { + w.close(); + }); + process.nextTick(emitClose, watcher); + } + + watcher.getWatchedPaths = function(fn) { + if (is.func(fn)) { + var promises = watchers.map(function(w) { + return new Promise(function(resolve) { + w.getWatchedPaths(resolve); + }); + }); + Promise.all(promises).then(function(result) { + var ret = unique(flat1(result)); + fn(ret); + }); + } + } + + return watcher.expose(); +} + +function watch(fpath, options, fn) { + var watcher = new Watcher(); + + if (is.buffer(fpath)) { + fpath = fpath.toString(); + } + + if (!is.array(fpath) && !is.exists(fpath)) { + watcher.emit('error', + new Error(fpath + ' does not exist.') + ); + } + + if (is.string(options)) { + options = { + encoding: options + } + } + + if (is.func(options)) { + fn = options; + options = {}; + } + + if (arguments.length < 2) { + options = {}; + } + + if (options.encoding) { + assertEncoding(options.encoding); + } else { + options.encoding = 'utf8'; + } + + if (is.array(fpath)) { + if (fpath.length === 1) { + return watch(fpath[0], options, fn); + } + var filterDups = createDupsFilter(); + return composeWatcher(unique(fpath).map(function(f) { + var w = watch(f, options); + if (is.func(fn)) { + w.on('change', filterDups(fn)); + } + return w; + })); + } + + if (is.file(fpath)) { + watcher.watchFile(fpath, options, fn); + emitReady(watcher); + } + + else if (is.directory(fpath)) { + var counter = semaphore(function () { + emitReady(watcher); + }); + watcher.watchDirectory(fpath, options, fn, counter); + } + + return watcher.expose(); +} + +module.exports = watch; +module.exports.default = watch; diff --git a/includes/external/chvfs/node_modules/node-watch/package.json b/includes/external/chvfs/node_modules/node-watch/package.json new file mode 100644 index 0000000..241dc81 --- /dev/null +++ b/includes/external/chvfs/node_modules/node-watch/package.json @@ -0,0 +1,36 @@ +{ + "description": "A wrapper and enhancements for fs.watch", + "license": "MIT", + "name": "node-watch", + "repository": { + "url": "git://github.com/yuanchuan/node-watch.git", + "type": "git" + }, + "keywords": [ + "fs.watch", + "watch", + "watchfile" + ], + "version": "0.7.3", + "bugs": { + "url": "https://github.com/yuanchuan/node-watch/issues" + }, + "url": "https://github.com/yuanchuan/node-watch", + "author": "yuanchuan <yuanchuan23@gmail.com> (http://yuanchuan.name)", + "main": "./lib/watch", + "types": "./lib/watch.d.ts", + "files": [ + "lib/" + ], + "homepage": "https://github.com/yuanchuan/node-watch#readme", + "scripts": { + "test": "mocha test/test.js --exit --slow 500" + }, + "engines": { + "node": ">=6" + }, + "devDependencies": { + "fs-extra": "^7.0.1", + "mocha": "^5.2.0" + } +} diff --git a/includes/external/chvfs/package-lock.json b/includes/external/chvfs/package-lock.json new file mode 100644 index 0000000..e2d2ba4 --- /dev/null +++ b/includes/external/chvfs/package-lock.json @@ -0,0 +1,27 @@ +{ + "name": "chvfs", + "lockfileVersion": 2, + "requires": true, + "packages": { + "": { + "dependencies": { + "node-watch": "^0.7.3" + } + }, + "node_modules/node-watch": { + "version": "0.7.3", + "resolved": "https://registry.npmjs.org/node-watch/-/node-watch-0.7.3.tgz", + "integrity": "sha512-3l4E8uMPY1HdMMryPRUAl+oIHtXtyiTlIiESNSVSNxcPfzAFzeTbXFQkZfAwBbo0B1qMSG8nUABx+Gd+YrbKrQ==", + "engines": { + "node": ">=6" + } + } + }, + "dependencies": { + "node-watch": { + "version": "0.7.3", + "resolved": "https://registry.npmjs.org/node-watch/-/node-watch-0.7.3.tgz", + "integrity": "sha512-3l4E8uMPY1HdMMryPRUAl+oIHtXtyiTlIiESNSVSNxcPfzAFzeTbXFQkZfAwBbo0B1qMSG8nUABx+Gd+YrbKrQ==" + } + } +} diff --git a/includes/external/chvfs/package.json b/includes/external/chvfs/package.json new file mode 100644 index 0000000..8a3cbee --- /dev/null +++ b/includes/external/chvfs/package.json @@ -0,0 +1,5 @@ +{ + "dependencies": { + "node-watch": "^0.7.3" + } +} diff --git a/includes/jobs/FrontersNotification.php b/includes/jobs/FrontersNotification.php index d95f273..f29a1e5 100644 --- a/includes/jobs/FrontersNotification.php +++ b/includes/jobs/FrontersNotification.php @@ -5,6 +5,12 @@ $_SERVER['DOCUMENT_ROOT'] = "../.."; require_once $_SERVER['DOCUMENT_ROOT'] . '/includes/composer/vendor/autoload.php'; use ColorThief\ColorThief; +if (!function_exists("formatPonypush")) { + function formatPonypush($message) { + return "Update to Ponypush 3.1.0 or later — (\$PA1$\$" . base64_encode($message) . "\$\$)"; + } +} + $app = json_decode(file_get_contents($_SERVER['DOCUMENT_ROOT'] . "/includes/app.json"), true); $system = $options["system"]; @@ -48,12 +54,12 @@ if (count($fronters["members"]) > 1) { 'method' => 'POST', 'header' => "Content-Type: text/plain\r\n" . - "Title: 🐴 Switch occurred in $name\r\n" . + "Title: " . formatPonypush("🐴 Switch occurred in $name") . "\r\n" . "Priority: default\r\n" . "Tags: switch\r\n" . "Actions: view, Open " . $fronters["members"][0]["display_name"] . " on Cold Haze, https://ponies.equestria.horse/" . $fronters["members"][0]["name"] . "/, clear=true;view, Open " . $fronters["members"][1]["display_name"] . " on Cold Haze, https://ponies.equestria.horse/" . $fronters["members"][1]["name"] . "/, clear=true\r\n" . "Authorization: Basic " . base64_encode($ntfy["user"] . ":" . $ntfy["password"]), - 'content' => ($fronters["members"][0]["display_name"] ?? $fronters["members"][0]["name"]) . " and " . ($fronters["members"][1]["display_name"] ?? $fronters["members"][1]["name"]) . " switched in just now" + 'content' => formatPonypush(($fronters["members"][0]["display_name"] ?? $fronters["members"][0]["name"]) . " and " . ($fronters["members"][1]["display_name"] ?? $fronters["members"][1]["name"]) . " switched in just now") ] ]); } else if (count($fronters["members"]) > 0) { @@ -62,12 +68,12 @@ if (count($fronters["members"]) > 1) { 'method' => 'POST', 'header' => "Content-Type: text/plain\r\n" . - "Title: 🐴 Switch occurred in $name\r\n" . + "Title: " . formatPonypush("🐴 Switch occurred in $name") . "\r\n" . "Priority: default\r\n" . "Tags: switch\r\n" . "Actions: view, Open on Cold Haze, https://ponies.equestria.horse/" . $fronters["members"][0]["name"] . "/, clear=true\r\n" . "Authorization: Basic " . base64_encode($ntfy["user"] . ":" . $ntfy["password"]), - 'content' => ($fronters["members"][0]["display_name"] ?? $fronters["members"][0]["name"]) . " switched in just now" + 'content' => formatPonypush(($fronters["members"][0]["display_name"] ?? $fronters["members"][0]["name"]) . " switched in just now") ] ]); } else { @@ -76,12 +82,12 @@ if (count($fronters["members"]) > 1) { 'method' => 'POST', 'header' => "Content-Type: text/plain\r\n" . - "Title: 🐴 Switch occurred in $name\r\n" . + "Title: " . formatPonypush("🐴 Switch occurred in $name") . "\r\n" . "Priority: default\r\n" . "Tags: switch\r\n" . "Actions: view, Open on Cold Haze, https://ponies.equestria.horse/, clear=true\r\n" . "Authorization: Basic " . base64_encode($ntfy["user"] . ":" . $ntfy["password"]), - 'content' => "The fallback pony switched in just now" + 'content' => formatPonypush("The fallback pony switched in just now") ] ]); } diff --git a/includes/jobs/PKMembers.php b/includes/jobs/PKMembers.php index 529a820..536853d 100644 --- a/includes/jobs/PKMembers.php +++ b/includes/jobs/PKMembers.php @@ -30,6 +30,8 @@ if (trim($data) !== "" && $data !== false) { $parsed = json_decode($data, true); foreach ($parsed as $index => $member) { + echo(($member["display_name"] ?? $member["name"]) . "\n"); + if (isset($member["avatar_url"])) { $dominantColor = substr(ColorThief::getColor($member["avatar_url"], outputFormat: "hex"), 1); } else { @@ -44,5 +46,8 @@ if (trim($data) !== "" && $data !== false) { } $data = json_encode($parsed, JSON_PRETTY_PRINT); - file_put_contents("./data/$system/members.json", $data); -}
\ No newline at end of file + file_put_contents($_SERVER['DOCUMENT_ROOT'] . "/includes/data/$system/members.json", $data); +} + +file_put_contents($_SERVER['DOCUMENT_ROOT'] . "/includes/data/cache/navigation.json", "{}"); +file_put_contents($_SERVER['DOCUMENT_ROOT'] . "/includes/data/cache/home.json", "{}");
\ No newline at end of file diff --git a/includes/jobs/PKSystem.php b/includes/jobs/PKSystem.php index c3fce1b..045eb67 100644 --- a/includes/jobs/PKSystem.php +++ b/includes/jobs/PKSystem.php @@ -27,5 +27,5 @@ if ($app["other"]["id"] === $system) { $data = file_get_contents("https://pluralkit.equestria.dev/v2/systems/$system", false, $ctx); if (trim($data) !== "" && $data !== false) { - file_put_contents("./data/$system/general.json", $data); + file_put_contents($_SERVER['DOCUMENT_ROOT'] . "/includes/data/$system/general.json", $data); }
\ No newline at end of file diff --git a/includes/jobs/UpdateAssets.php b/includes/jobs/UpdateAssets.php index 8898b94..e52a6fa 100644 --- a/includes/jobs/UpdateAssets.php +++ b/includes/jobs/UpdateAssets.php @@ -19,7 +19,7 @@ function downloadAssets($system, $path = null) { $path = $system; } - $general = json_decode(file_get_contents("./data/$path/general.json"), true); + $general = json_decode(file_get_contents($_SERVER['DOCUMENT_ROOT'] . "/includes/data/$path/general.json"), true); if ($options["type"] === "system") { if (isset($general["avatar_url"])) { @@ -39,7 +39,7 @@ function downloadAssets($system, $path = null) { } } - $members = json_decode(file_get_contents("./data/$path/members.json"), true); + $members = json_decode(file_get_contents($_SERVER['DOCUMENT_ROOT'] . "/includes/data/$path/members.json"), true); foreach ($members as $member) { $id = preg_replace("/^([\da-f]{8})-([\da-f]{4})-([\da-f]{4})-([\da-f]{4})-([\da-f]{12})$/", "$1$2$3$4$5", $general["uuid"]) . preg_replace("/^([\da-f]{8})-([\da-f]{4})-([\da-f]{4})-([\da-f]{4})-([\da-f]{12})$/", "$1$2$3$4$5", $member["uuid"]); diff --git a/includes/pages.json b/includes/pages.json index 69aa00d..748234f 100644 --- a/includes/pages.json +++ b/includes/pages.json @@ -1,442 +1,212 @@ { - "about": { - "name": { - "en": "About Cold Haze", - "fr": "About Cold Haze" - }, - "short": "About", - "admin": true, - "limited": true, - "rail": true - }, - "actions": { - "name": { - "en": "Actions database", - "fr": "Actions database" - }, - "short": "Actions", - "admin": true, - "limited": false, - "rail": true - }, "alphabet": { "name": { - "en": "Members by prefix letters", - "fr": "Par lettre du préfixe" - }, - "short": null, - "admin": false, - "limited": false, - "rail": false - }, - "api": { - "name": { - "en": "API", - "fr": "API" - }, - "short": null, - "admin": false, - "limited": false, - "rail": false - }, - "app": { - "name": { - "en": "Mobile application", - "fr": "Application mobile" + "en": "Members by prefix letters" }, - "short": null, "admin": false, - "limited": false, - "rail": false + "limited": false }, "byfront": { "name": { - "en": "Members by last fronted", - "fr": "Members by last fronted" + "en": "Members by last fronted" }, - "short": "Last fronts", "admin": true, - "limited": true, - "rail": true + "limited": true }, "computers": { "name": { - "en": "Devices", - "fr": "Devices" - }, - "short": "PCs", - "admin": true, - "limited": false, - "rail": true - }, - "dashboard": { - "name": { - "en": "Dashboard", - "fr": "Dashboard" - }, - "short": null, - "admin": true, - "limited": false, - "rail": true - }, - "debug": { - "name": { - "en": "Data updater debugging", - "fr": "Débogage des mises à jour" + "en": "Devices" }, - "short": null, "admin": true, - "limited": true, - "rail": true + "limited": false }, "docs": { "name": { - "en": "Documents", - "fr": "Documents" + "en": "Documents" }, - "short": "Docs", "admin": true, - "limited": false, - "rail": true - }, - "disclaimers": { - "name": { - "en": "Disclaimers", - "fr": "Avertissements" - }, - "short": null, - "admin": false, - "limited": false, - "rail": false + "limited": false }, "edit": { "name": { - "en": "Editor", - "fr": "Editor" + "en": "Editor" }, - "short": null, "admin": true, - "limited": true, - "rail": false + "limited": true }, "edit-private": { "name": { - "en": "Editor (private)", - "fr": "Editor (private)" + "en": "Editor (private)" }, - "short": null, "admin": true, - "limited": false, - "rail": false + "limited": false }, "emergency": { "name": { - "en": "Emergency alert", - "fr": "Emergency alert" + "en": "Emergency alert" }, - "short": null, "admin": true, - "limited": true, - "rail": true + "limited": true }, "fronting": { "name": { - "en": "Front planner", - "fr": "Front planner" + "en": "Front planner" }, - "short": null, "admin": true, - "limited": true, - "rail": true + "limited": true }, "games": { "name": { - "en": "Equestria Games", - "fr": "Equestria Games" + "en": "Equestria Games" }, - "short": null, "admin": true, - "limited": true, - "rail": false - }, - "government": { - "name": { - "en": "Government", - "fr": "Gouvernement" - }, - "short": null, - "admin": false, - "limited": false, - "rail": false + "limited": true }, "home": { "name": { - "en": "Home", - "fr": "Accueil" + "en": "Home" }, - "short": null, "admin": false, - "limited": false, - "rail": false + "limited": false }, "jobs": { "name": { - "en": "Jobs history", - "fr": "Jobs history" + "en": "Jobs history" }, - "short": null, "admin": true, - "limited": true, - "rail": true + "limited": true }, "login": { "name": { - "en": "Login", - "fr": "Connexion" + "en": "Login" }, - "short": null, "admin": false, - "limited": false, - "rail": false + "limited": false }, "logout": { "name": { - "en": "Logout", - "fr": "Déconnexion" + "en": "Logout" }, - "short": null, "admin": false, - "limited": false, - "rail": false + "limited": false }, "metadata": { "name": { - "en": "Metadata editor", - "fr": "Metadata editor" + "en": "Metadata editor" }, - "short": "Metadata", "admin": true, - "limited": true, - "rail": false + "limited": true }, "money": { "name": { - "en": "Money tracker", - "fr": "Money tracker" - }, - "short": "Money", - "admin": true, - "limited": false, - "rail": false - }, - "nicknames": { - "name": { - "en": "Relations nicknames", - "fr": "Relations nicknames" + "en": "Money tracker" }, - "short": "Nicknames", "admin": true, - "limited": false, - "rail": true - }, - "page": { - "name": { - "en": "Member/system page", - "fr": "Page de membre/système" - }, - "short": null, - "admin": false, - "limited": false, - "rail": false + "limited": false }, "pleasure": { "name": { - "en": "Sex alert", - "fr": "Sex alert" + "en": "Sex alert" }, - "short": null, "admin": true, - "limited": true, - "rail": true + "limited": true }, "ponytown": { "name": { - "en": "Pony Town uploader", - "fr": "Pony Town uploader" + "en": "Pony Town uploader" }, - "short": null, "admin": true, - "limited": true, - "rail": true + "limited": true }, "profiles": { "name": { - "en": "Profile scores", - "fr": "Profile scores" + "en": "Profile scores" }, - "short": null, "admin": true, - "limited": true, - "rail": true + "limited": true }, "relations": { "name": { - "en": "Relations", - "fr": "Relations" + "en": "Relations" }, - "short": null, "admin": false, - "limited": false, - "rail": false + "limited": false }, "rules": { "name": { - "en": "Rules", - "fr": "Rules" + "en": "Rules" }, - "short": "Rules", "admin": true, - "limited": false, - "rail": true + "limited": false }, "s:compare": { "name": { - "en": "Compare members", - "fr": "Comparer les membres" + "en": "Compare members" }, - "short": null, "admin": false, - "limited": false, - "rail": false + "limited": false }, "s:history": { "name": { - "en": "Front history", - "fr": "Historique de front" + "en": "Front history" }, - "short": null, "admin": false, - "limited": false, - "rail": false + "limited": false }, "s:species": { "name": { - "en": "Members by species", - "fr": "Membres par espèce" - }, - "short": null, - "admin": false, - "limited": false, - "rail": false - }, - "s:tree": { - "name": { - "en": "System tree", - "fr": "Arbre du système" + "en": "Members by species" }, - "short": null, "admin": false, - "limited": false, - "rail": false + "limited": false }, "schedules": { "name": { - "en": "Schedules", - "fr": "Schedules" + "en": "Schedules" }, - "short": null, "admin": true, - "limited": true, - "rail": true - }, - "score": { - "name": { - "en": "Score system testing", - "fr": "Score system testing" - }, - "short": null, - "admin": true, - "limited": true, - "rail": true + "limited": true }, "splitting": { "name": { - "en": "Members by splitting date", - "fr": "Members by splitting date" + "en": "Members by splitting date" }, - "short": "Splits", "admin": true, - "limited": true, - "rail": true + "limited": true }, "stats": { "name": { - "en": "Statistics", - "fr": "Statistics" + "en": "Statistics" }, - "short": "Stats", "admin": true, - "limited": false, - "rail": true + "limited": false }, "terminology": { "name": { - "en": "Terminology", - "fr": "Terminologie" + "en": "Terminology" }, - "short": null, "admin": false, - "limited": false, - "rail": true - }, - "together": { - "name": { - "en": "Watch Together", - "fr": "Watch Together" - }, - "short": "Together", - "admin": true, - "limited": true, - "rail": false - }, - "together-dev": { - "name": { - "en": "Watch Together (dev)", - "fr": "Watch Together (dev)" - }, - "short": null, - "admin": true, - "limited": true, - "rail": false + "limited": false }, "toys": { "name": { - "en": "Toys database", - "fr": "Toys database" + "en": "Toys database" }, - "short": "Toys", "admin": true, - "limited": false, - "rail": true + "limited": false }, "travelling": { "name": { - "en": "System travels manager", - "fr": "System travels manager" + "en": "System travels manager" }, - "short": "Travels", "admin": true, - "limited": true, - "rail": true + "limited": true }, "wakeup": { "name": { - "en": "Wake-up alert", - "fr": "Wake-up alert" + "en": "Wake-up alert" }, - "short": null, "admin": true, - "limited": false, - "rail": true + "limited": false } }
\ No newline at end of file diff --git a/includes/util/agewarning.inc b/includes/util/agewarning.inc index 1f51647..f8bc650 100644 --- a/includes/util/agewarning.inc +++ b/includes/util/agewarning.inc @@ -1,7 +1,7 @@ <?php function showWarning($name, $id, $system) { - $ntfy = json_decode(file_get_contents($_SERVER['DOCUMENT_ROOT'] . "/includes/app.json"), true)["ntfy"]; + $ntfy = $GLOBALS["ColdHazeApp"]["ntfy"]; if (time() > 1677628800) { file_get_contents('https://' . $ntfy["server"] . '/' . $ntfy['topic'], false, stream_context_create([ @@ -9,12 +9,12 @@ function showWarning($name, $id, $system) { 'method' => 'POST', 'header' => "Content-Type: text/plain\r\n" . - "Title: ⚠️ $name does not have an age or birth year set\r\n" . + "Title: " . formatPonypush("⚠️ $name does not have an age or birth year set") . "\r\n" . "Priority: max\r\n" . "Tags: switch\r\n" . "Actions: view, Edit on Cold Haze, https://ponies.equestria.horse/-/metadata/" . ($system === "gdapd" ? "raindrops" : "cloudburst") . "/" . $id . "/, clear=true\r\n" . "Authorization: Basic " . base64_encode($ntfy["user"] . ":" . $ntfy["password"]), - 'content' => "To make sure they appear on the fronting schedule (and to make sure they can front again), they need to set an age or birth year now." + 'content' => formatPonypush("To make sure they appear on the fronting schedule (and to make sure they can front again), they need to set an age or birth year now.") ] ])); } else { @@ -23,12 +23,12 @@ function showWarning($name, $id, $system) { 'method' => 'POST', 'header' => "Content-Type: text/plain\r\n" . - "Title: ⚠️ $name does not have an age or birth year set\r\n" . + "Title: " . formatPonypush("⚠️ $name does not have an age or birth year set") . "\r\n" . "Priority: max\r\n" . "Tags: switch\r\n" . "Actions: view, Edit on Cold Haze, https://ponies.equestria.horse/-/metadata/" . ($system === "gdapd" ? "raindrops" : "cloudburst") . "/" . $id . "/, clear=true\r\n" . "Authorization: Basic " . base64_encode($ntfy["user"] . ":" . $ntfy["password"]), - 'content' => "To make sure they still appear on the fronting schedule after March 1st, they need to set an age or birth year now." + 'content' => formatPonypush("To make sure they still appear on the fronting schedule after March 1st, they need to set an age or birth year now.") ] ])); } diff --git a/includes/util/banner.inc b/includes/util/banner.inc index 1657233..947e5c6 100644 --- a/includes/util/banner.inc +++ b/includes/util/banner.inc @@ -1,6 +1,6 @@ <?php -require_once $_SERVER['DOCUMENT_ROOT'] . "/includes/util/session.inc"; global $isLoggedIn; global $lang; global $pages; +require_once $_SERVER['DOCUMENT_ROOT'] . "/includes/util/session.inc"; global $isLoggedIn; global $lang; global $pages; global $isLowerLoggedIn; require_once $_SERVER['DOCUMENT_ROOT'] . "/includes/util/pronouns.inc"; require_once $_SERVER['DOCUMENT_ROOT'] . "/includes/util/functions.inc"; require_once $_SERVER['DOCUMENT_ROOT'] . "/includes/util/Parsedown.php"; $Parsedown = new Parsedown(); @@ -21,6 +21,7 @@ function _header_getMember(string $id, $system) { function getMemberBannerData(string $id, string $system, bool $french = false) { global $travelling; global $isLoggedIn; + global $isLowerLoggedIn; global $lang; global $Parsedown; @@ -155,7 +156,7 @@ function getMemberBannerData(string $id, string $system, bool $french = false) { ]; } - $app = json_decode(file_get_contents($_SERVER['DOCUMENT_ROOT'] . "/includes/app.json"), true); + $app = $GLOBALS["ColdHazeApp"]; $systemData = []; $systemData['page'] = "/" . ($system === "gdapd" ? "raindrops" : ($system === $app["other"]["id"] ? $app["other"]["slug"] : "cloudburst")); @@ -190,7 +191,7 @@ function getMemberBannerData(string $id, string $system, bool $french = false) { sort($mfMember); $mfMember = $mfMember[0]; - $marefriends[] = [ + if (!($mfSystem === $app["other"]["id"] && !$isLoggedIn && !$isLowerLoggedIn)) $marefriends[] = [ "id" => $marefriend, "link" => "/" . ($mfMember["name"]), "icon" => getAsset($mfSystem, $mfMemberID, "heads"), @@ -212,7 +213,7 @@ function getMemberBannerData(string $id, string $system, bool $french = false) { sort($mfMember); $mfMember = $mfMember[0]; - $sexfriends[] = [ + if (!($mfSystem === $app["other"]["id"] && !$isLoggedIn && !$isLowerLoggedIn)) $sexfriends[] = [ "id" => $marefriend, "link" => "/" . ($mfMember["name"]), "icon" => getAsset($mfSystem, $mfMemberID, "heads"), @@ -232,7 +233,7 @@ function getMemberBannerData(string $id, string $system, bool $french = false) { sort($mfMember); $mfMember = $mfMember[0]; - $sisters[] = [ + if (!($mfSystem === $app["other"]["id"] && !$isLoggedIn && !$isLowerLoggedIn)) $sisters[] = [ "id" => $marefriend, "link" => "/" . ($mfMember["name"]), "icon" => getAsset($mfSystem, $mfMemberID, "heads"), @@ -254,7 +255,7 @@ function getMemberBannerData(string $id, string $system, bool $french = false) { sort($mfMember); $mfMember = $mfMember[0]; - $caretakers[] = [ + if (!($mfSystem === $app["other"]["id"] && !$isLoggedIn && !$isLowerLoggedIn)) $caretakers[] = [ "id" => $marefriend, "link" => "/" . ($mfMember["name"]), "icon" => getAsset($mfSystem, $mfMemberID, "heads"), diff --git a/includes/util/functions.inc b/includes/util/functions.inc index 5b5b6b5..79a47c6 100644 --- a/includes/util/functions.inc +++ b/includes/util/functions.inc @@ -17,6 +17,12 @@ if (!function_exists("createJob")) { } } +if (!function_exists("formatPonypush")) { + function formatPonypush($message) { + return "Update to Ponypush 3.1.0 or later — (\$PA1$\$" . base64_encode($message) . "\$\$)"; + } +} + if (!function_exists("peh_error")) { function peh_error($message, $code = 500): void { header("Location: /?em=" . urlencode(base64_encode($message)) . "&ec=" . $code); @@ -26,7 +32,7 @@ if (!function_exists("peh_error")) { if (!function_exists("getAsset")) { function getAsset($systemID, $memberID = null, $type = "avatars") { - $app = json_decode(file_get_contents($_SERVER['DOCUMENT_ROOT'] . "/includes/app.json"), true); + $app = $GLOBALS["ColdHazeApp"] ?? json_decode(file_get_contents($_SERVER['DOCUMENT_ROOT'] . "/includes/app.json"), true); $systemFile = (isset($app["other"]) && $systemID === $app["other"]["id"]) ? "other" : $systemID; if (file_exists($_SERVER['DOCUMENT_ROOT'] . "/includes/data/$systemFile/general.json")) { @@ -234,7 +240,7 @@ if (!function_exists("withCaretakersDown")) { if (!function_exists("getSystemMember")) { function getSystemMember(string $system, string $id) { - $app = json_decode(file_get_contents($_SERVER['DOCUMENT_ROOT'] . "/includes/app.json"), true); + $app = $GLOBALS["ColdHazeApp"] ?? json_decode(file_get_contents($_SERVER['DOCUMENT_ROOT'] . "/includes/app.json"), true); $systemID = $system; $members = json_decode(file_get_contents($_SERVER['DOCUMENT_ROOT'] . "/includes/data/" . ($systemID === $app["other"]["id"] ? "other" : $systemID) . "/members.json"), true); @@ -270,7 +276,7 @@ if (!function_exists("getMemberWithoutSystem")) { } if ($isLowerLoggedIn || $isLoggedIn) { - $app = json_decode(file_get_contents($_SERVER['DOCUMENT_ROOT'] . "/includes/app.json"), true); + $app = $GLOBALS["ColdHazeApp"] ?? json_decode(file_get_contents($_SERVER['DOCUMENT_ROOT'] . "/includes/app.json"), true); $members3 = json_decode(file_get_contents($_SERVER['DOCUMENT_ROOT'] . "/includes/data/other/members.json"), true); foreach ($members3 as $m) { @@ -316,7 +322,7 @@ if (!function_exists("prettySize")) { if (!function_exists("showSystem")) { function showSystem(string $id, string $name, string $color, bool $hideTitle) { - $app = json_decode(file_get_contents($_SERVER['DOCUMENT_ROOT'] . "/includes/app.json"), true); + $app = $GLOBALS["ColdHazeApp"] ?? json_decode(file_get_contents($_SERVER['DOCUMENT_ROOT'] . "/includes/app.json"), true); global $travelling; $global = json_decode(file_get_contents($_SERVER['DOCUMENT_ROOT'] . "/includes/data/" . (isset($app["other"]) && $id === $app["other"]["id"] ? "other" : $id) . "/general.json"), true); @@ -381,7 +387,7 @@ if (!function_exists("raindrops")) { if (!function_exists("other")) { function other(bool $hideTitle): void { - $app = json_decode(file_get_contents($_SERVER['DOCUMENT_ROOT'] . "/includes/app.json"), true); + $app = $GLOBALS["ColdHazeApp"] ?? json_decode(file_get_contents($_SERVER['DOCUMENT_ROOT'] . "/includes/app.json"), true); showSystem($app["other"]["id"], $app["other"]["name"], "#" . $app["other"]["color"] . "a6", $hideTitle); } } diff --git a/includes/util/score.inc b/includes/util/score.inc index ad3c8e4..9deacca 100644 --- a/includes/util/score.inc +++ b/includes/util/score.inc @@ -113,7 +113,7 @@ function scoreOrderGlobal() { } if ($isLowerLoggedIn || $isLoggedIn) { - $app = json_decode(file_get_contents($_SERVER['DOCUMENT_ROOT'] . "/includes/app.json"), true); + $app = $GLOBALS["ColdHazeApp"] ?? json_decode(file_get_contents($_SERVER['DOCUMENT_ROOT'] . "/includes/app.json"), true); foreach (json_decode(file_get_contents($_SERVER['DOCUMENT_ROOT'] . "/includes/data/other/members.json"), true) as $member) { if ($member["name"] !== "unknown" && $member["name"] !== "fusion" && $member["name"] !== "new" && !str_starts_with($member["name"], "smol") && !str_ends_with($member["name"], "-travelling") && file_exists($_SERVER['DOCUMENT_ROOT'] . "/includes/data/metadata/$member[id].json")) { if (isset($member["color"])) { diff --git a/includes/util/session.inc b/includes/util/session.inc index 7a6b931..72dd34d 100644 --- a/includes/util/session.inc +++ b/includes/util/session.inc @@ -9,6 +9,12 @@ global $_PROFILE; $isLoggedIn = false; $isLowerLoggedIn = false; +if (!function_exists("formatPonypush")) { + function formatPonypush($message) { + return "Update to Ponypush 3.1.0 or later — (\$PA1$\$" . base64_encode($message) . "\$\$)"; + } +} + if (isset($_COOKIE['PEH2_SESSION_TOKEN'])) { if (!(str_contains($_COOKIE['PEH2_SESSION_TOKEN'], ".") || str_contains($_COOKIE['PEH2_SESSION_TOKEN'], "/") || trim($_COOKIE["PEH2_SESSION_TOKEN"]) === "")) { if (file_exists($_SERVER['DOCUMENT_ROOT'] . "/includes/tokens/" . str_replace(".", "", str_replace("/", "", $_COOKIE['PEH2_SESSION_TOKEN'])))) { diff --git a/includes/util/travelling.inc b/includes/util/travelling.inc index 0d1696a..eced4f2 100644 --- a/includes/util/travelling.inc +++ b/includes/util/travelling.inc @@ -1,6 +1,6 @@ <?php -$app = json_decode(file_get_contents($_SERVER['DOCUMENT_ROOT'] . "/includes/app.json"), true); +$app = $GLOBALS["ColdHazeApp"] ?? json_decode(file_get_contents($_SERVER['DOCUMENT_ROOT'] . "/includes/app.json"), true); $travelling = json_decode(file_get_contents($_SERVER['DOCUMENT_ROOT'] . "/includes/data/travelling/travelling.json"), true); $json_cloudburst = json_decode(file_get_contents($_SERVER['DOCUMENT_ROOT'] . "/includes/data/ynmuc/members.json"), true); diff --git a/pages/api/emergency-real.php b/pages/api/emergency-real.php index d0412c8..a67f549 100644 --- a/pages/api/emergency-real.php +++ b/pages/api/emergency-real.php @@ -9,18 +9,18 @@ if (!$isLoggedIn && !$isLowerLoggedIn) { global $_PROFILE; -$ntfy = json_decode(file_get_contents($_SERVER['DOCUMENT_ROOT'] . "/includes/app.json"), true)["ntfy"]; +$ntfy = $GLOBALS["ColdHazeApp"]["ntfy"]; file_get_contents('https://' . $ntfy["server"] . '/' . $ntfy["topic"], false, stream_context_create([ 'http' => [ 'method' => 'POST', 'header' => "Content-Type: text/plain\r\n" . - "Title: ⚠️🆘 EMERGENCY ⚠️🆘\r\n" . + "Title: " . formatPonypush("⚠️🆘 EMERGENCY ⚠️🆘") . "\r\n" . "Priority: urgent\r\n" . "Tags: emergency\r\n" . "Authorization: Basic " . base64_encode($ntfy["user"] . ":" . $ntfy["password"]), - 'content' => "This is an emergency, " . $_PROFILE['name'] . " is in need of IMMEDIATE help. Please act now!" + 'content' => formatPonypush("This is an emergency, " . $_PROFILE['name'] . " is in need of IMMEDIATE help. Please act now!") ] ])); @@ -29,11 +29,11 @@ file_get_contents('https://' . $ntfy["server"] . '/emergency', false, stream_con 'method' => 'POST', 'header' => "Content-Type: text/plain\r\n" . - "Title: ⚠️🆘 EMERGENCY ⚠️🆘\r\n" . + "Title: " . formatPonypush("⚠️🆘 EMERGENCY ⚠️🆘") . "\r\n" . "Priority: urgent\r\n" . "Tags: emergency\r\n" . "Authorization: Basic " . base64_encode($ntfy["user"] . ":" . $ntfy["password"]), - 'content' => "This is an emergency, " . $_PROFILE['name'] . " is in need of IMMEDIATE help. Please act now!" + 'content' => formatPonypush("This is an emergency, " . $_PROFILE['name'] . " is in need of IMMEDIATE help. Please act now!") ] ])); diff --git a/pages/api/emergency.php b/pages/api/emergency.php index 2f764b1..24c975a 100644 --- a/pages/api/emergency.php +++ b/pages/api/emergency.php @@ -9,18 +9,18 @@ if (!$isLoggedIn && !$isLowerLoggedIn) { global $_PROFILE; -$ntfy = json_decode(file_get_contents($_SERVER['DOCUMENT_ROOT'] . "/includes/app.json"), true)["ntfy"]; +$ntfy = $GLOBALS["ColdHazeApp"]["ntfy"]; file_get_contents('https://' . $ntfy["server"] . '/' . $ntfy["topic"], false, stream_context_create([ 'http' => [ 'method' => 'POST', 'header' => "Content-Type: text/plain\r\n" . - "Title: [Test] ⚠️🆘 EMERGENCY ⚠️🆘\r\n" . + "Title: " . formatPonypush("[Test] ⚠️🆘 EMERGENCY ⚠️🆘") . "\r\n" . "Priority: urgent\r\n" . "Tags: emergency\r\n" . "Authorization: Basic " . base64_encode($ntfy["user"] . ":" . $ntfy["password"]), - 'content' => "[This notification is test] This is an emergency, " . $_PROFILE['name'] . " is in need of IMMEDIATE help. Please act now! [This notification is test]" + 'content' => formatPonypush("[This notification is test] This is an emergency, " . $_PROFILE['name'] . " is in need of IMMEDIATE help. Please act now! [This notification is test]") ] ])); @@ -29,11 +29,11 @@ file_get_contents('https://' . $ntfy["server"] . '/emergency', false, stream_con 'method' => 'POST', 'header' => "Content-Type: text/plain\r\n" . - "Title: [Test] ⚠️🆘 EMERGENCY ⚠️🆘\r\n" . + "Title: " . formatPonypush("[Test] ⚠️🆘 EMERGENCY ⚠️🆘") . "\r\n" . "Priority: urgent\r\n" . "Tags: emergency\r\n" . "Authorization: Basic " . base64_encode($ntfy["user"] . ":" . $ntfy["password"]), - 'content' => "[This notification is test] This is an emergency, " . $_PROFILE['name'] . " is in need of IMMEDIATE help. Please act now! [This notification is test]" + 'content' => formatPonypush("[This notification is test] This is an emergency, " . $_PROFILE['name'] . " is in need of IMMEDIATE help. Please act now! [This notification is test]") ] ])); diff --git a/pages/api/me.php b/pages/api/me.php index 4f86549..5b13208 100644 --- a/pages/api/me.php +++ b/pages/api/me.php @@ -1,6 +1,6 @@ <?php -$app = json_decode(file_get_contents($_SERVER['DOCUMENT_ROOT'] . "/includes/app.json"), true); +$app = $GLOBALS["ColdHazeApp"]; require_once $_SERVER['DOCUMENT_ROOT'] . "/includes/util/session.inc"; global $isLoggedIn; global $isLowerLoggedIn; diff --git a/pages/api/pleasure-real.php b/pages/api/pleasure-real.php index 5ac0039..122d994 100644 --- a/pages/api/pleasure-real.php +++ b/pages/api/pleasure-real.php @@ -22,18 +22,18 @@ if ($_PROFILE["login"] === "raindrops" && isset($frontRaindrops[0])) { $pony = "somepony"; } -$ntfy = json_decode(file_get_contents($_SERVER['DOCUMENT_ROOT'] . "/includes/app.json"), true)["ntfy"]; +$ntfy = $GLOBALS["ColdHazeApp"]["ntfy"]; file_get_contents('https://' . $ntfy["server"] . '/pleasure', false, stream_context_create([ 'http' => [ 'method' => 'POST', 'header' => "Content-Type: text/plain\r\n" . - "Title: 🏩 $pony wants to play for a bit\r\n" . + "Title: " . formatPonypush("🏩 $pony wants to play for a bit") . "\r\n" . "Priority: high\r\n" . "Tags: pleasure\r\n" . "Authorization: Basic " . base64_encode($ntfy["user"] . ":" . $ntfy["password"]), - 'content' => "Hey, $pony wants to play and have fun for a bit, get up!" + 'content' => formatPonypush("Hey, $pony wants to play and have fun for a bit, get up!") ] ])); diff --git a/pages/api/pleasure.php b/pages/api/pleasure.php index 705adfe..14abada 100644 --- a/pages/api/pleasure.php +++ b/pages/api/pleasure.php @@ -22,18 +22,18 @@ if ($_PROFILE["login"] === "raindrops" && isset($frontRaindrops[0])) { $pony = "somepony"; } -$ntfy = json_decode(file_get_contents($_SERVER['DOCUMENT_ROOT'] . "/includes/app.json"), true)["ntfy"]; +$ntfy = $GLOBALS["ColdHazeApp"]["ntfy"]; file_get_contents('https://' . $ntfy["server"] . '/pleasure', false, stream_context_create([ 'http' => [ 'method' => 'POST', 'header' => "Content-Type: text/plain\r\n" . - "Title: [Test] 🏩 $pony wants to play for a bit\r\n" . + "Title: " . formatPonypush("[Test] 🏩 $pony wants to play for a bit") . "\r\n" . "Priority: high\r\n" . "Tags: pleasure\r\n" . "Authorization: Basic " . base64_encode($ntfy["user"] . ":" . $ntfy["password"]), - 'content' => "[This is a test] Hey, $pony wants to play and have fun for a bit, get up!" + 'content' => formatPonypush("[This is a test] Hey, $pony wants to play and have fun for a bit, get up!") ] ])); diff --git a/pages/api/plex-thumb.php b/pages/api/plex-thumb.php index 4a20159..4009871 100644 --- a/pages/api/plex-thumb.php +++ b/pages/api/plex-thumb.php @@ -1,6 +1,6 @@ <?php -$app = json_decode(file_get_contents($_SERVER['DOCUMENT_ROOT'] . "/includes/app.json"), true); +$app = $GLOBALS["ColdHazeApp"]; if (isset($_GET["library"]) && isset($_GET["id"]) && is_numeric($_GET["library"]) && is_numeric($_GET["id"])) { header("Content-Type: image/jpg"); diff --git a/pages/api/plex.php b/pages/api/plex.php index a2fa739..00164c7 100644 --- a/pages/api/plex.php +++ b/pages/api/plex.php @@ -1,7 +1,7 @@ <?php require_once $_SERVER['DOCUMENT_ROOT'] . "/includes/util/random.inc"; -$app = json_decode(file_get_contents($_SERVER['DOCUMENT_ROOT'] . "/includes/app.json"), true); +$app = $GLOBALS["ColdHazeApp"]; function formatTitle($metadata) { if ($metadata['grandparentTitle']) { diff --git a/pages/api/pluralkit-integration.php b/pages/api/pluralkit-integration.php index 0efa8cb..69d99b1 100644 --- a/pages/api/pluralkit-integration.php +++ b/pages/api/pluralkit-integration.php @@ -2,14 +2,14 @@ require_once $_SERVER['DOCUMENT_ROOT'] . "/includes/util/agewarning.inc"; -$app = json_decode(file_get_contents($_SERVER['DOCUMENT_ROOT'] . "/includes/app.json"), true); +$app = $GLOBALS["ColdHazeApp"]; $user = $_GET['user'] ?? null; $inputJSON = file_get_contents('php://input'); $input = json_decode($inputJSON, true); -$data = json_decode(file_get_contents($_SERVER['DOCUMENT_ROOT'] . "/includes/app.json"), true)["webhook"]; +$data = $GLOBALS["ColdHazeApp"]["webhook"]; -if (isset(json_decode(file_get_contents($_SERVER['DOCUMENT_ROOT'] . "/includes/app.json"), true)["ponytown"][$user])) { - $ponytown = json_decode(file_get_contents($_SERVER['DOCUMENT_ROOT'] . "/includes/app.json"), true)["ponytown"][$user]; +if (isset($GLOBALS["ColdHazeApp"]["ponytown"][$user])) { + $ponytown = $GLOBALS["ColdHazeApp"]["ponytown"][$user]; } else { header("HTTP/1.1 404 Not Found") and die(); } diff --git a/pages/api/wakeup-real.php b/pages/api/wakeup-real.php index fd113ba..f00d5ea 100644 --- a/pages/api/wakeup-real.php +++ b/pages/api/wakeup-real.php @@ -15,18 +15,18 @@ $frontRaindrops = json_decode(file_get_contents($_SERVER['DOCUMENT_ROOT'] . "/in $pony = "somepony"; if ($_PROFILE['login'] === "raindrops") $pony = $frontRaindrops[0]["display_name"]; else $pony = $frontCloudburst[0]["display_name"]; -$ntfy = json_decode(file_get_contents($_SERVER['DOCUMENT_ROOT'] . "/includes/app.json"), true)["ntfy"]; +$ntfy = $GLOBALS["ColdHazeApp"]["ntfy"]; file_get_contents('https://' . $ntfy["server"] . '/' . $ntfy["topic"], false, stream_context_create([ 'http' => [ 'method' => 'POST', 'header' => "Content-Type: text/plain\r\n" . - "Title: 🥱 Wake up!\r\n" . + "Title: " . formatPonypush("🥱 Wake up!") . "\r\n" . "Priority: high\r\n" . "Tags: wakeup\r\n" . "Authorization: Basic " . base64_encode($ntfy["user"] . ":" . $ntfy["password"]), - 'content' => "Hey, $pony wants you to wake up!" + 'content' => formatPonypush("Hey, $pony wants you to wake up!") ] ])); diff --git a/pages/api/wakeup.php b/pages/api/wakeup.php index e4603ef..a5d2b9f 100644 --- a/pages/api/wakeup.php +++ b/pages/api/wakeup.php @@ -15,18 +15,18 @@ $frontRaindrops = json_decode(file_get_contents($_SERVER['DOCUMENT_ROOT'] . "/in $pony = "somepony"; if ($_PROFILE['login'] === "raindrops") $pony = $frontRaindrops[0]["display_name"]; else $pony = $frontCloudburst[0]["display_name"]; -$ntfy = json_decode(file_get_contents($_SERVER['DOCUMENT_ROOT'] . "/includes/app.json"), true)["ntfy"]; +$ntfy = $GLOBALS["ColdHazeApp"]["ntfy"]; file_get_contents('https://' . $ntfy["server"] . '/' . $ntfy["topic"], false, stream_context_create([ 'http' => [ 'method' => 'POST', 'header' => "Content-Type: text/plain\r\n" . - "Title: [Test] 🥱 Wake up!\r\n" . + "Title: " . formatPonypush("[Test] 🥱 Wake up!") . "\r\n" . "Priority: high\r\n" . "Tags: wakeup\r\n" . "Authorization: Basic " . base64_encode($ntfy["user"] . ":" . $ntfy["password"]), - 'content' => "[This notification is test] Hey, $pony wants you to wake up! [This notification is test]" + 'content' => formatPonypush("[This notification is test] Hey, $pony wants you to wake up! [This notification is test]") ] ])); diff --git a/pages/home.inc b/pages/home.inc index 86bf513..cc04e42 100644 --- a/pages/home.inc +++ b/pages/home.inc @@ -4,24 +4,9 @@ if (isset($_GET["ec"])) { header("HTTP/1.1 " . $_GET["ec"] . " Error"); } -require_once $_SERVER['DOCUMENT_ROOT'] . "/includes/init.inc"; require_once $_SERVER['DOCUMENT_ROOT'] . '/includes/components/header.inc'; global $readOnly; global $isNormallyLoggedIn; global $_PROFILE; global $lang; global $pages; global $isLowerLoggedIn; global $app; global $isLoggedIn; ?> +require_once $_SERVER['DOCUMENT_ROOT'] . "/includes/init.inc"; require_once $_SERVER['DOCUMENT_ROOT'] . '/includes/components/header.inc'; global $readOnly; global $isNormallyLoggedIn; global $_PROFILE; global $lang; global $pages; global $isLowerLoggedIn; global $app; global $isLoggedIn; -<br> -<div class="container"> - <?php if (isset($_GET['em'])): ?> - <div class="alert alert-danger alert-dismissible"> - <button onclick='window.history.pushState({"html":null,"pageTitle":document.title},"", "/");' type="button" class="btn-close" data-bs-dismiss="alert"></button> - <b><?= $lang["home"]["error"] ?> </b><?= strip_tags(base64_decode($_GET['em'])) ?> - </div> - <?php endif; ?> - - <?php if ($readOnly && $isNormallyLoggedIn || $readOnly && $isLowerLoggedIn): ?> - <div class="alert alert-warning"> - <b>Notice: </b>This website is temporarily under maintenance and the administrators have locked the database. Although you are logged in as <?= $_PROFILE['name'] ?>, you cannot access any of the logged-in features while the website is under maintenance. <a href="/-/emergency">Alerts dispatching</a> remains possible in case of an emergency. - </div> - <?php endif; ?> - - <?php global $travelling; $byColor = getMembersByColor(); ?> +function banner() { global $isLoggedIn; global $isLowerLoggedIn; $byColor = getMembersByColor(); global $lang; ?> <div style="text-align: center;"> <img alt="" src="/assets/logo/newlogo<?= $isLoggedIn || $isLowerLoggedIn ? "3" : "" ?>.png" style="width:128px;"> <p style="z-index:999;position:relative;background:transparent;margin: 20px -10px 0 -20px;padding-right:30px;height:32px;text-align: center;display:grid;grid-template-columns: repeat(<?= count($byColor) ?>, 1fr);"> @@ -30,18 +15,20 @@ require_once $_SERVER['DOCUMENT_ROOT'] . "/includes/init.inc"; require_once $_SE <div style="margin-top:-33px;margin-bottom:0;margin-left:-20px;margin-right:20px;height:32px;text-align: center;display:grid;grid-template-columns: repeat(<?= count($byColor) ?>, 1fr);position:relative;left:10px;"> <?php foreach ($byColor as $member): ?><div> <span style="display: inline-block;background: transparent;position:absolute;width: 0;height: 0;margin-top: 17px;box-shadow: 0 6px 20px 20px #<?= $member["color"] ?>;z-index: 9;margin-left: 8px;opacity: .75;"></span> - </div><?php endforeach; ?> + </div><?php endforeach; ?> </div> <div style="padding:5px 10px;background:#3332328a;border-bottom-left-radius: 10px;border-bottom-right-radius: 10px;position:relative;z-index: 999;backdrop-filter: blur(30px);"> <h2 style="margin-top: 20px;">Cold Haze</h2> <?php if ($isLoggedIn || $isLowerLoggedIn): ?> - <p><?= count($byColor) ?> ponies in 3 plural systems</p> + <p><?= count($byColor) ?> ponies in 3 plural systems</p> <?php else: ?> - <p><?= count($byColor) ?> <?= $lang["home"]["intro"] ?></p> + <p><?= count($byColor) ?> <?= $lang["home"]["intro"] ?></p> <?php endif; ?> </div> </div> +<?php } +function members() { global $isLoggedIn; global $isLowerLoggedIn; global $app; ?> <div id="new-homepage" style="margin-top:20px;"> <div id="new-homepage-systems" <?php if ($isLoggedIn || $isLowerLoggedIn): ?>style="grid-template-columns: repeat(3, 1fr);"<?php endif; ?>> @@ -73,6 +60,110 @@ require_once $_SERVER['DOCUMENT_ROOT'] . "/includes/init.inc"; require_once $_SE endforeach; ?> </div> </div> +<?php } ?> + +<br> +<div class="container"> + <?php if (isset($_GET['em'])): ?> + <div class="alert alert-danger alert-dismissible"> + <button onclick='window.history.pushState({"html":null,"pageTitle":document.title},"", "/");' type="button" class="btn-close" data-bs-dismiss="alert"></button> + <b><?= $lang["home"]["error"] ?> </b><?= strip_tags(base64_decode($_GET['em'])) ?> + </div> + <?php endif; ?> + + <?php if ($readOnly && $isNormallyLoggedIn || $readOnly && $isLowerLoggedIn): ?> + <div class="alert alert-warning"> + <b>Notice: </b>This website is temporarily under maintenance and the administrators have locked the database. Although you are logged in as <?= $_PROFILE['name'] ?>, you cannot access any of the logged-in features while the website is under maintenance. <a href="/-/emergency">Alerts dispatching</a> remains possible in case of an emergency. + </div> + <?php endif; ?> + + <?php + + $cache = json_decode(file_get_contents($_SERVER['DOCUMENT_ROOT'] . "/includes/data/cache/home.json"), true); + if (!isset($cache["banner"])) $cache["banner"] = []; + if (!isset($cache["members"])) $cache["members"] = []; + + if (!isset($cache["banner"]["public"])) { + ob_start(); + + $isLoggedInOldState = $isLoggedIn; + $isLowerLoggedInOldState = $isLowerLoggedIn; + $isLoggedIn = false; + $isLowerLoggedIn = false; + banner(); + $isLoggedIn = $isLoggedInOldState; + $isLowerLoggedIn = $isLowerLoggedInOldState; + + $cache["banner"]["public"] = ob_get_contents(); + ob_end_clean(); + } + + if (!isset($cache["banner"]["private"])) { + ob_start(); + + $isLoggedInOldState = $isLoggedIn; + $isLowerLoggedInOldState = $isLowerLoggedIn; + $isLoggedIn = true; + $isLowerLoggedIn = true; + banner(); + $isLoggedIn = $isLoggedInOldState; + $isLowerLoggedIn = $isLowerLoggedInOldState; + + $cache["banner"]["private"] = ob_get_contents(); + ob_end_clean(); + } + + if (!isset($cache["members"]["public"])) { + ob_start(); + + $isLoggedInOldState = $isLoggedIn; + $isLowerLoggedInOldState = $isLowerLoggedIn; + $isLoggedIn = false; + $isLowerLoggedIn = false; + members(); + $isLoggedIn = $isLoggedInOldState; + $isLowerLoggedIn = $isLowerLoggedInOldState; + + $cache["members"]["public"] = ob_get_contents(); + ob_end_clean(); + } + + if (!isset($cache["members"]["private"])) { + ob_start(); + + $isLoggedInOldState = $isLoggedIn; + $isLowerLoggedInOldState = $isLowerLoggedIn; + $isLoggedIn = true; + $isLowerLoggedIn = true; + members(); + $isLoggedIn = $isLoggedInOldState; + $isLowerLoggedIn = $isLowerLoggedInOldState; + + $cache["members"]["private"] = ob_get_contents(); + ob_end_clean(); + } + + if ($isLowerLoggedIn || $isLoggedIn) { + echo($cache["banner"]["private"]); + } else { + echo($cache["banner"]["public"]); + } + + ?> + + <div class="alert alert-warning" style="margin-top:20px;"> + <b>Notice:</b> The administrators are currently trying a new optimisation technique based on a virtual file system (chvfs). Data loss, corruption or inconsistency may happen and should be reported on <a href="https://bugs.equestria.dev/issues/CH" target="_blank">bugs.equestria.dev</a>. + </div> + + <?php + + if ($isLowerLoggedIn || $isLoggedIn) { + echo($cache["members"]["private"]); + } else { + echo($cache["members"]["public"]); + } + + ?> </div> -<?php require_once $_SERVER['DOCUMENT_ROOT'] . '/includes/components/footer.inc'; ?>
\ No newline at end of file +<?php file_put_contents($_SERVER['DOCUMENT_ROOT'] . "/includes/data/cache/home.json", json_encode($cache)); require_once $_SERVER['DOCUMENT_ROOT'] . '/includes/components/footer.inc'; ?>
\ No newline at end of file diff --git a/pages/jobs.inc b/pages/jobs.inc index ae1405d..109b484 100644 --- a/pages/jobs.inc +++ b/pages/jobs.inc @@ -86,31 +86,11 @@ $history = json_decode(file_get_contents($_SERVER['DOCUMENT_ROOT'] . "/includes/ <b>Job lifetime:</b> <ul class="tracking"> - <li><b>Queued by PHP</b><br><?php - $d = explode("|", substr(date('M jS Y, G:i|s.u', strtotime($item["tracking"]["queue"])), 0, -3)); - $d[1] = (string)((float)$d[1]); - echo($d[0] . ":" . $d[1]); - ?></li> - <?php if (isset($item["tracking"]["pickup"])): ?><li><b>Picked up by the runner</b><br><?php - $d = explode("|", substr(date('M jS Y, G:i|s.u', strtotime($item["tracking"]["pickup"])), 0, -3)); - $d[1] = (string)((float)$d[1]); - echo($d[0] . ":" . $d[1]); - ?></li><?php endif; ?> - <?php if (isset($item["tracking"]["start"])): ?><li><b>Started</b><br><?php - $d = explode("|", substr(date('M jS Y, G:i|s.u', strtotime($item["tracking"]["start"])), 0, -3)); - $d[1] = (string)((float)$d[1]); - echo($d[0] . ":" . $d[1]); - ?></li><?php endif; ?> - <?php if (isset($item["tracking"]["end"])): ?><li><b><?= $item["completed"] ? "Finished" : "Failed" ?></b><br><?php - $d = explode("|", substr(date('M jS Y, G:i|s.u', strtotime($item["tracking"]["end"])), 0, -3)); - $d[1] = (string)((float)$d[1]); - echo($d[0] . ":" . $d[1]); - ?></li><?php endif; ?> - <?php if (isset($item["tracking"]["logged"])): ?><li><b>Tracking logged</b><br><?php - $d = explode("|", substr(date('M jS Y, G:i|s.u', strtotime($item["tracking"]["logged"])), 0, -3)); - $d[1] = (string)((float)$d[1]); - echo($d[0] . ":" . $d[1]); - ?></li><?php endif; ?> + <li><b>Queued by PHP</b><br><?= date('M jS Y, G:i:s', strtotime($item["tracking"]["queue"])) ?></li> + <?php if (isset($item["tracking"]["pickup"])): ?><li><b>Picked up by the runner</b><br><?= date('M jS Y, G:i:s', strtotime($item["tracking"]["pickup"])) ?></li><?php endif; ?> + <?php if (isset($item["tracking"]["start"])): ?><li><b>Started</b><br><?= date('M jS Y, G:i:s', strtotime($item["tracking"]["start"])) ?></li><?php endif; ?> + <?php if (isset($item["tracking"]["end"])): ?><li><b><?= $item["completed"] ? "Finished" : "Failed" ?></b><br><?= date('M jS Y, G:i:s', strtotime($item["tracking"]["end"])) ?></li><?php endif; ?> + <?php if (isset($item["tracking"]["logged"])): ?><li><b>Tracking logged</b><br><?= date('M jS Y, G:i:s', strtotime($item["tracking"]["logged"])) ?></li><?php endif; ?> </ul> </div> </div> diff --git a/pages/metadata.inc b/pages/metadata.inc index adde5e7..04579a8 100644 --- a/pages/metadata.inc +++ b/pages/metadata.inc @@ -178,6 +178,8 @@ if ($member === null) { if (trim($metadata["species"][1]) === "") unset($metadata["species"][1]); file_put_contents($_SERVER['DOCUMENT_ROOT'] . "/includes/data/metadata/" . $memberID . ".json", json_encode($metadata)); + file_put_contents($_SERVER['DOCUMENT_ROOT'] . "/includes/data/cache/navigation.json", "{}"); + file_put_contents($_SERVER['DOCUMENT_ROOT'] . "/includes/data/cache/home.json", "{}"); header("Location: /" . $_GET['_']); } else { diff --git a/pages/money.inc b/pages/money.inc index 15a7a83..387f5c0 100644 --- a/pages/money.inc +++ b/pages/money.inc @@ -64,16 +64,16 @@ if ((isset($_GET["create"]) || isset($_GET["delete"])) && isset($parts[2])) { if (!isset($_GET["description"])) $_GET["description"] = ""; $_GET["description"] = substr($_GET["description"], 0, 150); - $ntfy = json_decode(file_get_contents($_SERVER['DOCUMENT_ROOT'] . "/includes/app.json"), true)["ntfy"]; + $ntfy = $GLOBALS["ColdHazeApp"]["ntfy"]; file_get_contents('https://' . $ntfy["server"] . '/' . $ntfy["topic"], false, stream_context_create([ 'http' => [ 'method' => 'POST', 'header' => "Content-Type: text/plain\r\n" . - "Title: " . (getMember($myId)["display_name"] ?? getMember($myId)["name"]) . " created a transaction to " . $account["name"] . " (" . ucfirst($account["owner"]) . ")\r\n" . + "Title: " . formatPonypush((getMember($myId)["display_name"] ?? getMember($myId)["name"]) . " created a transaction to " . $account["name"] . " (" . ucfirst($account["owner"]) . ")") . "\r\n" . "Tags: bits\r\n" . "Authorization: Basic " . base64_encode($ntfy["user"] . ":" . $ntfy["password"]), - 'content' => ($account["currency"] === "gbp" ? "£" : "€") . abs((float)$_GET["amount"]) . " were " . ((float)$_GET["amount"] >= 0 ? "added" : "removed") . " just now" . (trim($_GET["description"]) !== "" ? ": " . $_GET["description"] : "") + 'content' => formatPonypush(($account["currency"] === "gbp" ? "£" : "€") . abs((float)$_GET["amount"]) . " were " . ((float)$_GET["amount"] >= 0 ? "added" : "removed") . " just now" . (trim($_GET["description"]) !== "" ? ": " . $_GET["description"] : "")) ] ])); @@ -90,16 +90,16 @@ if ((isset($_GET["create"]) || isset($_GET["delete"])) && isset($parts[2])) { file_put_contents($_SERVER['DOCUMENT_ROOT'] . "/includes/data/money/" . $name . ".json", json_encode($account, JSON_PRETTY_PRINT)); } else { if (isset($_GET["id"]) && is_numeric($_GET["id"]) && isset($account["transactions"][(int)$_GET["id"]])) { - $ntfy = json_decode(file_get_contents($_SERVER['DOCUMENT_ROOT'] . "/includes/app.json"), true)["ntfy"]; + $ntfy = $GLOBALS["ColdHazeApp"]["ntfy"]; file_get_contents('https://' . $ntfy["server"] . '/' . $ntfy["topic"], false, stream_context_create([ 'http' => [ 'method' => 'POST', 'header' => "Content-Type: text/plain\r\n" . - "Title: " . (getMember($myId)["display_name"] ?? getMember($myId)["name"]) . " deleted a transaction from " . $account["name"] . " (" . ucfirst($account["owner"]) . ")\r\n" . + "Title: " . formatPonypush((getMember($myId)["display_name"] ?? getMember($myId)["name"]) . " deleted a transaction from " . $account["name"] . " (" . ucfirst($account["owner"]) . ")") . "\r\n" . "Tags: bits\r\n" . "Authorization: Basic " . base64_encode($ntfy["user"] . ":" . $ntfy["password"]), - 'content' => ($account["currency"] === "gbp" ? "£" : "€") . abs((float)$account["transactions"][(int)$_GET["id"]]["amount"]) . " " . ((float)$account["transactions"][(int)$_GET["id"]]["amount"] >= 0 ? "advance" : "withdrawal") . " created by " . (getMemberWithoutSystem($account["transactions"][(int)$_GET["id"]]["author"])["display_name"] ?? getMemberWithoutSystem($account["transactions"][(int)$_GET["id"]]["author"])["name"]) . " " . timeAgo($account["transactions"][(int)$_GET["id"]]["date"]) + 'content' => formatPonypush(($account["currency"] === "gbp" ? "£" : "€") . abs((float)$account["transactions"][(int)$_GET["id"]]["amount"]) . " " . ((float)$account["transactions"][(int)$_GET["id"]]["amount"] >= 0 ? "advance" : "withdrawal") . " created by " . (getMemberWithoutSystem($account["transactions"][(int)$_GET["id"]]["author"])["display_name"] ?? getMemberWithoutSystem($account["transactions"][(int)$_GET["id"]]["author"])["name"]) . " " . timeAgo($account["transactions"][(int)$_GET["id"]]["date"])) ] ])); diff --git a/pages/page.inc b/pages/page.inc index 8446062..931e6e5 100644 --- a/pages/page.inc +++ b/pages/page.inc @@ -2,7 +2,7 @@ global $lang; global $pages; global $isLoggedIn; global $isLowerLoggedIn; -$app = json_decode(file_get_contents($_SERVER['DOCUMENT_ROOT'] . "/includes/app.json"), true); +$app = $GLOBALS["ColdHazeApp"]; $travelling = json_decode(file_get_contents($_SERVER['DOCUMENT_ROOT'] . "/includes/data/travelling/travelling.json"), true); if (!isset($_GET['_']) || trim($_GET['_']) === "") peh_error("Invalid request", 400); diff --git a/pages/travelling.inc b/pages/travelling.inc index fdcfa99..cfbd4ac 100644 --- a/pages/travelling.inc +++ b/pages/travelling.inc @@ -2,7 +2,7 @@ require_once $_SERVER['DOCUMENT_ROOT'] . "/includes/init.inc"; global $title; global $isLoggedIn; global $lang; global $pages; global $isLowerLoggedIn; $travelling = json_decode(file_get_contents($_SERVER['DOCUMENT_ROOT'] . "/includes/data/travelling/travelling.json"), true); -$app = json_decode(file_get_contents($_SERVER['DOCUMENT_ROOT'] . "/includes/app.json"), true); +$app = $GLOBALS["ColdHazeApp"]; require_once $_SERVER['DOCUMENT_ROOT'] . "/includes/util/functions.inc"; |