diff options
Diffstat (limited to 'pages')
51 files changed, 1034 insertions, 3884 deletions
diff --git a/pages/actions.inc b/pages/actions.inc deleted file mode 100644 index 630626a..0000000 --- a/pages/actions.inc +++ /dev/null @@ -1,1119 +0,0 @@ -<?php - -return; -require_once $_SERVER['DOCUMENT_ROOT'] . "/includes/init.inc"; global $title; global $isLoggedIn; global $lang; global $pages; - -if (isset($_POST['deleteAction'])) { - $data = json_decode(file_get_contents($_SERVER['DOCUMENT_ROOT'] . "/includes/data/actions/actions.json"), true); - - $selected = null; - $selectedIndex = -1; - $id = $_POST['action']; - - foreach ($data as $index => $item) { - if ($item["id"] === $id) { - $selectedIndex = $index; - $selected = $item; - break; - } - } - - if ($selected === null) { - header("Location: /-/actions"); - die(); - } - - unset($data[$selectedIndex]); - @mkdir($_SERVER['DOCUMENT_ROOT'] . "/includes/data/actions"); - file_put_contents($_SERVER['DOCUMENT_ROOT'] . "/includes/data/actions/" . date('Y-m-d_H-i-s') . ".json", utf8_encode(json_encode($data))); - file_put_contents($_SERVER['DOCUMENT_ROOT'] . "/includes/data/actions/actions.json", utf8_encode(json_encode($data))); - header("Location: /-/actions/?d&id=" . $id); - die(); -} - -if (isset($_POST['updateAction'])) { - $data = json_decode(file_get_contents($_SERVER['DOCUMENT_ROOT'] . "/includes/data/actions/actions.json"), true); - - $selected = null; - $selectedIndex = -1; - $id = $_POST['action']; - - foreach ($data as $index => $item) { - if ($item["id"] === $id) { - $selectedIndex = $index; - $selected = $item; - break; - } - } - - if ($selected === null) { - header("Location: /-/actions"); - die(); - } - - if (isset($_POST["consent"])) { - $selected["consent"] = true; - } else { - $selected["consent"] = false; - } - - if (isset($_POST["name"])) $selected["name"] = strip_tags(trim($_POST["name"])); - if (isset($_POST["example"])) $selected["example"] = strip_tags(trim($_POST["example"])); - if (isset($_POST["irl"])) $selected["irl"] = strip_tags(trim($_POST["irl"])); - if (isset($_POST["keywords"])) $selected["keywords"] = array_map(function ($i) { - return trim($i); - }, explode(",", strip_tags(trim($_POST["keywords"])))); - if (isset($_POST["description"])) $selected["description"] = strip_tags(trim($_POST["description"])); - if (isset($_POST["type"])) $selected["type"] = match ($_POST["type"]) { - "0" => "affectionate", - "1" => "sexual", - "2" => "mixed" - }; - - if (isset($_POST["relations"])) { - $ponies = []; - - foreach ($_POST["relations"] as $relation => $d) { - $ponies[] = [ - "members" => explode("-", $relation), - "deprecated" => isset($d["deprecated"]), - "sexual" => isset($d["sexual"]) - ]; - } - - $selected["ponies"] = $ponies; - } - - global $_PROFILE; - if ($_PROFILE['login'] === "raindrops" && isset($_POST["verified"])) { - $selected["verified"] = true; - } else { - unset($selected["verified"]); - } - - if (isset($_POST["untested"])) { - $selected["untested"] = true; - } else { - unset($selected["untested"]); - } - - $data[$selectedIndex] = $selected; - @mkdir($_SERVER['DOCUMENT_ROOT'] . "/includes/data/actions"); - file_put_contents($_SERVER['DOCUMENT_ROOT'] . "/includes/data/actions/" . date('Y-m-d_H-i-s') . ".json", utf8_encode(json_encode($data))); - file_put_contents($_SERVER['DOCUMENT_ROOT'] . "/includes/data/actions/actions.json", utf8_encode(json_encode($data))); - - header("Location: /-/actions/" . $id); - die(); -} - -if (isset($_POST['createAction'])) { - require_once $_SERVER['DOCUMENT_ROOT'] . "/includes/random.inc"; - $data = json_decode(file_get_contents($_SERVER['DOCUMENT_ROOT'] . "/includes/data/actions/actions.json"), true); - - if (!isset($_POST["name"]) || !isset($_POST["type"])) { - header("Location: /-/actions"); - die(); - } - if (trim($_POST["name"]) === "" || !is_numeric($_POST["type"])) { - header("Location: /-/actions"); - die(); - } - - $type = match ($_POST["type"]) { - "0" => "affectionate", - "1" => "sexual", - "2" => "mixed" - }; - $name = strip_tags(trim($_POST["name"])); - $id = random(); - - $ponies = []; - - if (isset($_POST["relations"])) { - foreach ($_POST["relations"] as $relation => $_) { - $ponies[] = [ - "members" => explode("-", $relation), - "deprecated" => false, - "sexual" => false - ]; - } - } - - if (isset($_POST["consent"])) { - $consent = true; - } else { - $consent = false; - } - - $data[] = [ - "id" => $id, - "name" => $name, - "type" => $type, - "description" => null, - "ponies" => $ponies, - "example" => null, - "irl" => null, - "keywords" => [], - "consent" => $consent - ]; - - @mkdir($_SERVER['DOCUMENT_ROOT'] . "/includes/data/actions"); - file_put_contents($_SERVER['DOCUMENT_ROOT'] . "/includes/data/actions/" . date('Y-m-d_H-i-s') . ".json", utf8_encode(json_encode($data))); - file_put_contents($_SERVER['DOCUMENT_ROOT'] . "/includes/data/actions/actions.json", utf8_encode(json_encode($data))); - header("Location: /-/actions/" . $id); - die(); -} - -global $pagename; -$parts = explode("/", $pagename); -$data = json_decode(file_get_contents($_SERVER['DOCUMENT_ROOT'] . "/includes/data/actions/actions.json"), true); -$toys = json_decode(file_get_contents($_SERVER['DOCUMENT_ROOT'] . "/includes/data/toys/toys.json"), true); - -$selected = null; - -if (isset($parts[1])) { - $id = $parts[1]; - - foreach ($data as $item) { - if ($item["id"] === $id) { - $selected = $item; - break; - } - } - - if ($selected === null) { - header("Location: /-/actions/?nf&id=" . $id); - die(); - } else { - $title = $selected["name"] . " · " . $title; - } -} - -require_once $_SERVER['DOCUMENT_ROOT'] . '/includes/header.inc'; -require_once $_SERVER['DOCUMENT_ROOT'] . '/includes/keywords.inc'; - -if (!file_exists($_SERVER['DOCUMENT_ROOT'] . "/includes/data/actions/actions.json")) file_put_contents($_SERVER['DOCUMENT_ROOT'] . "/includes/data/actions/actions.json", "[]"); - -global $_PROFILE; -global $pagename; -$parts = explode("/", $pagename); - -?> - -<script src="/assets/editor/fuse.js"></script> - -<br> -<div class="container"> - <div id="<?= isset($parts[1]) ? "page-content" : "" ?>"> - <?php if (isset($_GET['nf'])): ?> - <div class="alert alert-danger alert-dismissible"> - <button onclick='window.history.pushState({"html":null,"pageTitle":document.title},"", "/-/actions");' type="button" class="btn-close" data-bs-dismiss="alert" style="filter: none !important;"></button> - <b>Error: </b> The requested action (<code><?= strip_tags($_GET['id'] ?? "-") ?></code>) was not found, it may have been deleted or has never existed. - </div> - <?php endif; ?> - - <?php if (isset($_GET['d'])): ?> - <div class="alert alert-success alert-dismissible"> - <button onclick='window.history.pushState({"html":null,"pageTitle":document.title},"", "/-/actions");' type="button" class="btn-close" data-bs-dismiss="alert" style="filter: none !important;"></button> - <b>Success: </b> The action with ID <code><?= strip_tags($_GET['id'] ?? "-") ?></code> has been successfully deleted. - </div> - <?php endif; ?> - - <?php if (isset($parts[1])): ?> - - <h2> - <span style="vertical-align: middle;"><?= $selected["name"] ?></span> - <a href="/-/actions" class="small btn btn-outline-light" style="float:right;margin-top:5px;vertical-align:middle;opacity:1 !important; color:white;">Back</a> - </h2> - <p> - <a onclick="event.target.blur();" data-bs-toggle="modal" data-bs-target="#editor" href="#">Edit</a> · - <?php if ($selected["type"] === "affectionate"): ?> - <span style="" class="badge rounded-pill bg-primary">Affectionate</span> - <?php endif; ?> - <?php if ($selected["type"] === "sexual"): ?> - <span style="" class="badge rounded-pill bg-danger">Sexual</span> - <?php endif; ?> - <?php if ($selected["type"] === "mixed"): ?> - <span style="" class="badge rounded-pill bg-primary">Affectionate</span> <span style="" class="badge rounded-pill bg-danger">Sexual</span> - <?php endif; ?> - <?php if (!isset($item["verified"])): ?><span class="badge bg-warning rounded-pill text-black">Unverified</span><?php endif; ?> - <?php if (isset($item["untested"])): ?><span class="badge bg-info rounded-pill">Untested</span><?php endif; ?> - </p> - - <hr> - <?php if ($selected["consent"] && $selected["type"] !== "affectionate"): ?> - <div class="alert alert-danger"> - <b>This action requires consent.</b> Since this action constitues a sexual act, verbal consent from both parties is absolutely required. Both parties must be in a mental state where they are able to consent. Furthermore, if one of the parties involved wishes to stop, the request must be immediately honoured. - </div> - <?php elseif ($selected["consent"]): ?> - <div class="alert alert-warning"> - <b>This action is better with consent.</b> This action is extremely personal to all parties involved, and it is best to ask if they wish to do this. If they ask to stop the action, you must stop immediately and reverse any potential effects. - </div> - <?php endif; ?> - - <?php if (isset($selected["description"]) && trim($selected["description"]) !== ""): ?> - <?= replaceKeyWords(str_replace("\n", "<br>", strip_tags($selected["description"]))); ?> - <?php else: ?> - <p><i>No description provided for this action. Enter edit mode to add a description to this action.</i></p> - <?php endif; ?> - - <?php if (isset($selected["toys"]) && $selected["toys"]): ?> - <hr> - <p><b>Available toys:</b></p> - <div id="toys-list"> - <div class="toys-list-inner"> - <?php - - $init = []; - foreach ($toys as $value) { - $init[$value["name"]] = $value; - } - - ksort($init); - - $sorted = array_values($init); - uasort($sorted, function ($a, $b) { - $uniquePonies1 = []; - - foreach ($a["ponies"] as $ponies) { - foreach ($ponies["members"] as $member) { - $uniquePonies1[$member] = true; - } - } - - $uniquePonies2 = []; - - foreach ($b["ponies"] as $ponies) { - foreach ($ponies["members"] as $member) { - $uniquePonies2[$member] = true; - } - } - - return count($uniquePonies2) - count($uniquePonies1); - }); - - foreach ($sorted as $item): ?> - <a href="/-/toys/<?= $item["id"] ?>" id="action-<?= $item["id"] ?>" style="color:white !important;"> - <div> - <span><?= $item["name"] ?></span> - </div> - </a> - <?php endforeach; ?> - </div> - </div> - <?php endif; ?> - - <!--<hr> - <b>Can be done by:</b> - <?php - - $hasMultipleTypes = false; - $seenType = ""; - - foreach ($selected["ponies"] as $relation) { - if (isset($relation["sexual"]) && $relation["sexual"]) { - $type = "sexual"; - } else { - $type = "affectionate"; - } - - if ($type !== $seenType && $seenType !== "") { - $hasMultipleTypes = true; - } - - if (trim($seenType) === "") { - $seenType = $type; - } - } - - ?> - <?php if ($hasMultipleTypes): ?> - <ul> - <li> - Affectionately: - <ul> - <?php foreach ($selected["ponies"] as $relation): if (!$relation["deprecated"] && (!isset($relation["sexual"]) || !$relation["sexual"])): - - $member1 = getMemberWithoutSystem($relation["members"][0]); - $member2 = getMemberWithoutSystem($relation["members"][1]); - - ?> - <li> - <img style="vertical-align: middle;width:24px;height:24px;" src="<?= getAsset($systemID, $member1["id"], "heads") ?>"> - <img style="vertical-align: middle;width:24px;height:24px;" src="<?= getAsset($systemID, $member2["id"], "heads") ?>"> - - <span style="vertical-align: middle;"><?= getMiniName($member1["display_name"] ?? $member1["name"]) ?> and <?= getMiniName($member2["display_name"] ?? $member2["name"]) ?></span> - </li> - <?php endif; endforeach; ?> - <?php foreach ($selected["ponies"] as $relation): if ($relation["deprecated"] && (!isset($relation["sexual"]) || !$relation["sexual"])): - - $member1 = getMemberWithoutSystem($relation["members"][0]); - $member2 = getMemberWithoutSystem($relation["members"][1]); - - ?> - <li> - <span style="opacity:.5;"> - <img style="vertical-align: middle;width:24px;height:24px;" src="<?= getAsset($systemID, $member1["id"], "heads") ?>"> - <img style="vertical-align: middle;width:24px;height:24px;" src="<?= getAsset($systemID, $member2["id"], "heads") ?>"> - - <span style="vertical-align: middle;"><?= getMiniName($member1["display_name"] ?? $member1["name"]) ?> and <?= getMiniName($member2["display_name"] ?? $member2["name"]) ?></span> - </span> - <span class="badge bg-danger rounded-pill">Deprecated</span> - </li> - <?php endif; endforeach; ?> - </ul> - </li> - <li> - Sexually: - <ul> - <?php foreach ($selected["ponies"] as $relation): if (!$relation["deprecated"] && (isset($relation["sexual"]) && $relation["sexual"])): - - $member1 = getMemberWithoutSystem($relation["members"][0]); - $member2 = getMemberWithoutSystem($relation["members"][1]); - - ?> - <li> - <img style="vertical-align: middle;width:24px;height:24px;" src="<?= getAsset($member1["system"], $member1["id"], "heads") ?>"> - <img style="vertical-align: middle;width:24px;height:24px;" src="<?= getAsset($member2["system"], $member2["id"], "heads") ?>"> - - <span style="vertical-align: middle;"><?= getMiniName($member1["display_name"] ?? $member1["name"]) ?> and <?= getMiniName($member2["display_name"] ?? $member2["name"]) ?></span> - </li> - <?php endif; endforeach; ?> - <?php foreach ($selected["ponies"] as $relation): if ($relation["deprecated"] && (isset($relation["sexual"]) && $relation["sexual"])): - - $member1 = getMemberWithoutSystem($relation["members"][0]); - $member2 = getMemberWithoutSystem($relation["members"][1]); - - ?> - <li> - <span style="opacity:.5;"> - <img style="vertical-align: middle;width:24px;height:24px;" src="<?= getAsset($member1["system"], $member1["id"], "heads") ?>"> - <img style="vertical-align: middle;width:24px;height:24px;" src="<?= getAsset($member2["system"], $member2["id"], "heads") ?>"> - - <span style="vertical-align: middle;"><?= getMiniName($member1["display_name"] ?? $member1["name"]) ?> and <?= getMiniName($member2["display_name"] ?? $member2["name"]) ?></span> - </span> - <span class="badge bg-danger rounded-pill">Deprecated</span> - </li> - <?php endif; endforeach; ?> - </ul> - </li> - </ul> - <?php else: ?> - <ul> - <?php foreach ($selected["ponies"] as $relation): if (!$relation["deprecated"]): - - $member1 = getMemberWithoutSystem($relation["members"][0]); - $member2 = getMemberWithoutSystem($relation["members"][1]); - - ?> - <li> - <img style="vertical-align: middle;width:24px;height:24px;" src="<?= getAsset($member1["system"], $member1["id"], "heads") ?>"> - <img style="vertical-align: middle;width:24px;height:24px;" src="<?= getAsset($member2["system"], $member2["id"], "heads") ?>"> - - <span style="vertical-align: middle;"><?= getMiniName($member1["display_name"] ?? $member1["name"]) ?> and <?= getMiniName($member2["display_name"] ?? $member2["name"]) ?></span> - </li> - <?php endif; endforeach; ?> - <?php foreach ($selected["ponies"] as $relation): if ($relation["deprecated"]): - - $member1 = getMemberWithoutSystem($relation["members"][0]); - $member2 = getMemberWithoutSystem($relation["members"][1]); - - ?> - <li> - <span style="opacity:.5;"> - <img style="vertical-align: middle;width:24px;height:24px;" src="<?= getAsset($member1["system"], $member1["id"], "heads") ?>"> - <img style="vertical-align: middle;width:24px;height:24px;" src="<?= getAsset($member2["system"], $member2["id"], "heads") ?>"> - - <span style="vertical-align: middle;"><?= getMiniName($member1["display_name"] ?? $member1["name"]) ?> and <?= getMiniName($member2["display_name"] ?? $member2["name"]) ?></span> - </span> - <span class="badge bg-danger rounded-pill">Deprecated</span> - </li> - <?php endif; endforeach; ?> - </ul> - <?php endif; ?>--> - - <div style="margin-top:10px;"></div> - - <?php $multipleExamples = count(explode(",", strip_tags($selected["example"]))) > 1; ?> - <b>Example<?= $multipleExamples ? "s" : "" ?>:</b><br> - <?php if (isset($selected["example"]) && trim($selected["example"]) !== ""): ?> - <?php if ($multipleExamples): ?> - <ul> - <?php foreach (explode(",", strip_tags($selected["example"])) as $example): ?> - <li><?= replaceKeyWords(trim($example)) ?></li> - <?php endforeach; ?> - </ul> - <?php else: ?> - <?= replaceKeyWords(strip_tags($selected["example"])) ?> - <?php endif; ?> - <?php else: ?> - <p><i>No example provided for this action. Enter edit mode to add an example to this action.</i></p> - <?php endif; ?> - - <div style="margin-top:10px;"></div> - - <b>Steps to reproduce in real life:</b><br> - <?php if (isset($selected["irl"]) && trim($selected["irl"]) !== ""): ?> - <?= replaceKeyWords(strip_tags($selected["irl"])) ?> - <?php else: ?> - <p><i>This action is not reproducible in real life.</i></p> - <?php endif; ?> - - <hr> - - <h4>Similar actions</h4> - <div class="row"> - <?php - - $names = []; - $currentName = $selected["name"]; - $namesByDistance = []; - - foreach ($data as $action) { - if ($action["name"] !== $currentName) $names[$action["name"]] = [ - "id" => $action["id"], - "type" => $action["type"], - "ponies" => $action["ponies"] - ]; - } - - foreach ($names as $name => $data) { - if ($data["type"] === $selected["type"] || $selected["type"] !== "affectionate") { - $namesByDistance[] = [ - "name" => $name, - "distance" => levenshtein($currentName, $name) + ((int)($data["type"] !== $selected["type"]) * 2), - "id" => $data["id"], - "type" => $data["type"], - "ponies" => $data["ponies"] - ]; - } - } - - uasort($namesByDistance, function ($a, $b) use ($selected) { - return $a["distance"] - $b["distance"]; - }); - - foreach ($namesByDistance as $item) { - echo("<!-- " . $currentName . " <-> " . $item["name"] . " => " . $item["distance"] . " (artif: " . ((int)($item["type"] !== $selected["type"]) * 10) . ") -->"); - } - - $index = 0; - foreach ($namesByDistance as $item): if ($index < 3): - ?> - <div class="col-md-4" style="margin-bottom:20px;"> - <a class="linked-card" href="/-/actions/<?= $item["id"] ?>"><div class="card"> - <div class="card-body"> - <h4 class="card-title"><?= $item["name"] ?></h4> - <p class="card-text"> - <!--<?php - - $uniquePonies = []; - - foreach ($item["ponies"] as $ponies) { - foreach ($ponies["members"] as $member) { - if (isset($uniquePonies[$member]) && !$uniquePonies[$member]) { - $uniquePonies[$member] = false; - } else { - $uniquePonies[$member] = $ponies["deprecated"]; - } - } - } - - foreach ($uniquePonies as $name => $deprecated): if (!$deprecated): ?> - <span data-bs-toggle="tooltip" title="<?= getMemberWithoutSystem($name)["display_name"] ?? getMemberWithoutSystem($name)["display_name"] ?>" style="display: inline-block;"> - <img src="<?= getAsset(getMemberWithoutSystem($name)["system"], getMemberWithoutSystem($name)["id"], "heads") ?>" style="width:32px;"> - </span> - <?php endif; endforeach; ?> - <?php foreach ($uniquePonies as $name => $deprecated): if ($deprecated): ?> - <span data-bs-toggle="tooltip" data-bs-html="true" title="<i><?= strip_tags(getMemberWithoutSystem($name)["display_name"] ?? getMemberWithoutSystem($name)["name"]) ?></i>" style="opacity:.5;display: inline-block;"> - <img src="<?= getAsset(getMemberWithoutSystem($name)["system"], getMemberWithoutSystem($name)["id"], "heads") ?>" style="width:32px;"> - </span> - <?php endif; endforeach; ?>--> - - - </p> - <?php if ($item["type"] === "affectionate"): ?> - <span style="" class="badge rounded-pill bg-primary">Affectionate</span> - <?php endif; ?> - <?php if ($item["type"] === "sexual"): ?> - <span style="" class="badge rounded-pill bg-danger">Sexual</span> - <?php endif; ?> - <?php if ($item["type"] === "mixed"): ?> - <span style="" class="badge rounded-pill bg-primary">Affectionate</span> <span style="" class="badge rounded-pill bg-danger">Sexual</span> - <?php endif; ?> - </div> - </div></a> - </div> - <?php $index++; endif; endforeach; ?> - </div> - - <div class="modal fade" id="editor"> - <div class="modal-dialog"> - <div class="modal-content"> - <div class="modal-header"> - <h4 class="modal-title">Edit action</h4> - <button type="button" class="btn-close" data-bs-dismiss="modal"></button> - </div> - - <div class="modal-body"> - <form method="post" style="display:inline;"> - <input type="text" placeholder="Action title" name="name" class="form-control" style="color:white;background:#111;border-color:#222;margin-bottom:10px;" value="<?= str_replace('"', '"', $selected["name"]) ?>"> - <select name="type" id="editor-type" class="form-select" style='color:white;background-color:#111;border-color:#222;background-image:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3e%3cpath fill='none' stroke='%23ffffff' stroke-linecap='round' stroke-linejoin='round' stroke-width='2' d='M2 5l6 6 6-6'/%3e%3c/svg%3e");margin-bottom:10px;' onchange="changeMixed();"> - <option value="0" <?= $selected["type"] === "affectionate" ? "selected" : "" ?>>Affectionate</option> - <option value="1" <?= $selected["type"] === "sexual" ? "selected" : "" ?>>Sexual</option> - <option value="2" <?= $selected["type"] === "mixed" ? "selected" : "" ?>>Mixed</option> - </select> - - <label style="margin-left:5px;"> - <input <?= ($selected["consent"] ?? false) ? "checked" : "" ?> type="checkbox" name="consent"> - Requires consent - </label><br> - - <label style="margin-left:5px;"> - <input <?= ($selected["verified"] ?? false) ? "checked" : "" ?> <?= $_PROFILE['login'] !== "raindrops" ? "disabled" : "" ?> type="checkbox" name="verified"> - Mark as verified - </label><br> - - <label style="margin-left:5px;"> - <input <?= ($selected["untested"] ?? false) ? "checked" : "" ?> type="checkbox" name="untested"> - Mark as untested - </label> - - <hr> - - <textarea name="description" class="form-control" style="resize: none;color:white;background:#111;border-color:#222;" placeholder="Description"><?= strip_tags($selected["description"] ?? "") ?></textarea> - - <hr> - - <input type="text" placeholder="Keywords (comma-separated)" name="keywords" class="form-control" style="color:white;background:#111;border-color:#222;margin-bottom:10px;" value="<?= str_replace('"', '"', implode(",", $selected["keywords"] ?? [])) ?>"> - <input type="text" placeholder="Action example" name="example" class="form-control" style="color:white;background:#111;border-color:#222;margin-bottom:10px;" value="<?= str_replace('"', '"', $selected["example"] ?? "") ?>"> - <input type="text" placeholder="IRL steps" name="irl" class="form-control" style="color:white;background:#111;border-color:#222;" value="<?= str_replace('"', '"', $selected["irl"] ?? "") ?>"> - - <div style="display: none;"> - <hr> - - <p>Select the groups of ponies who can do this action:</p> - <?php - - $members = scoreOrderGlobal(); - $relations = []; - - foreach ($members as $member) { - foreach ([ - ...array_map(function ($i) { - $r = [ - "name" => $i - ]; - $r["type"] = "marefriends"; - return $r; - }, $member["_metadata"]["marefriends"] ?? []), - ...array_map(function ($i) { - $r = [ - "name" => $i - ]; - $r["type"] = "sisters"; - return $r; - }, $member["_metadata"]["sisters"] ?? []), - ...array_map(function ($i) { - $r = [ - "name" => $i - ]; - $r["type"] = "caretaking"; - return $r; - }, $member["_metadata"]["caretakers"] ?? []) - ] as $rel) { - $id = $rel["name"]; - $otherMember = getSystemMember(explode("/", $id)[0], explode("/", $id)[1]); - - $parts = [ - $member["id"], - $otherMember["id"] - ]; - - asort($parts); - - $relations[implode("-", $parts)] = [ - "name" => getMiniName($member["display_name"] ?? $member["name"]) . " and " . getMiniName($otherMember["display_name"] ?? $otherMember["name"]), - "type" => $rel["type"], - "images" => [ - file_exists($_SERVER['DOCUMENT_ROOT'] . "/assets/uploads/pt-$member[name].png") ? "/assets/uploads/pt-$member[name].png" : "/assets/uploads/pt.png", - file_exists($_SERVER['DOCUMENT_ROOT'] . "/assets/uploads/pt-$otherMember[name].png") ? "/assets/uploads/pt-$otherMember[name].png" : "/assets/uploads/pt.png", - ] - ]; - } - } - - $inFileRelations = []; - $inFileDeprecations = []; - $inFileSexual = []; - - foreach ($selected["ponies"] as $ponies) { - $inFileRelations[] = $ponies["members"][0] . "-" . $ponies["members"][1]; - - if (isset($ponies["deprecated"]) && $ponies["deprecated"]) $inFileDeprecations[] = $ponies["members"][0] . "-" . $ponies["members"][1]; - if (isset($ponies["sexual"]) && $ponies["sexual"]) $inFileSexual[] = $ponies["members"][0] . "-" . $ponies["members"][1]; - } - - foreach ($relations as $id => $relation): - ?> - <label style="display:block;" class="creator-relation <?= $selected["type"] === "mixed" ? "mixed" : "" ?> <?= in_array($id, $inFileRelations) ? "checked" : "" ?>"> - <input <?= in_array($id, $inFileRelations) ? "checked" : "" ?> name="relations[<?= $id ?>][member]" style="display:none;" type="checkbox" class="checkbox-input"> - - <img style="vertical-align: middle;width:24px;height:24px;" src="<?= $relation["images"][0] ?>"> - <img style="vertical-align: middle;width:24px;height:24px;" src="<?= $relation["images"][1] ?>"> - <span style="vertical-align: middle;"><?= $relation["name"] ?></span> - - <span style="float:right;margin-top:3px;" class="badge rounded-pill bg-<?= match ($relation["type"]) { - "marefriends" => "danger", - "sisters" => "success", - "caretaking" => "primary" - } ?>"><?= match ($relation["type"]) { - "marefriends" => "Marefriends", - "sisters" => "Sisters", - "caretaking" => "Caretaker" - } ?></span> - - <label class="deprecated" style="display:none;margin-left: 20px;margin-top: 5px;"> - <input <?= in_array($id, $inFileDeprecations) ? "checked" : "" ?> name="relations[<?= $id ?>][deprecated]" type="checkbox"> - Mark as deprecated - </label> - <label class="sexual" style="display:none;margin-left: 20px;margin-top: 5px;"> - <input <?= in_array($id, $inFileSexual) ? "checked" : "" ?> name="relations[<?= $id ?>][sexual]" type="checkbox"> - Mark as sexual - </label> - </label> - <?php endforeach; ?> - </div> - - <br> - <input type="hidden" name="updateAction"> - <input type="hidden" name="action" value="<?= $selected["id"] ?>"> - <input type="submit" class="btn btn-primary" value="Save"> - </form> - <form method="post" style="display:inline;"> - <input type="hidden" name="deleteAction"> - <input type="hidden" name="action" value="<?= $selected["id"] ?>"> - <input type="submit" class="btn btn-danger" value="Delete"> - </form> - </div> - </div> - </div> - </div> - - <?php else: ?> - - <h2>Actions database</h2> - <p><?= count($data) ?> actions (<?= count(array_filter($data, function ($i) { - return $i["type"] === "affectionate" || $i["type"] === "mixed"; - })) ?> affectionate, <?= count(array_filter($data, function ($i) { - return $i["type"] === "sexual" || $i["type"] === "mixed"; - })) ?> sexual, <?= count(array_filter($data, function ($i) { - return isset($i["untested"]) && $i["untested"]; - })) ?> untested, <?= count(array_filter($data, function ($i) { - return (isset($i["description"]) && trim($i["description"]) === "") || !isset($i["description"]); - })) ?> incomplete)</p> - - <p>TODO: fill everything and add keywords</p> - - <input type="text" placeholder="Search for an action..." class="form-control" style="margin-bottom:15px;color:white;background:#111;border-color:#222;" onchange="search();" onkeydown="search();" onkeyup="search();" id="search"> - - <div id="list"> - <div class="list-group"> - <?php - - $init = []; - foreach ($data as $value) { - $init[$value["name"]] = $value; - } - - ksort($init); - - $sorted = array_values($init); - - foreach ($sorted as $item): ?> - <a href="/-/actions/<?= $item["id"] ?>" id="action-<?= $item["id"] ?>" style="display:grid;grid-template-columns: 1fr 0.2fr;" class="list-group-item list-group-item-action action-listing"> - <div> - <span class="<?= trim($item["description"]) === "" ? "text-danger" : "" ?>"><?= $item["name"] ?></span> - <?php if (!isset($item["verified"])): ?><span class="badge bg-warning rounded-pill text-black">Unverified</span><?php endif; ?> - <?php if (isset($item["untested"])): ?><span class="badge bg-info rounded-pill">Untested</span><?php endif; ?> - </div> - <!-- - <div> - <?php - - $uniquePonies = []; - $longPonyList = false; - - foreach ($item["ponies"] as $ponies) { - foreach ($ponies["members"] as $member) { - if (isset($uniquePonies[$member]) && !$uniquePonies[$member]) { - $uniquePonies[$member] = false; - } else { - $uniquePonies[$member] = $ponies["deprecated"]; - } - } - } - - if (count($uniquePonies) > 6) { - $longPonyList = true; - } - - $index = 1; - foreach ($uniquePonies as $name => $deprecated): if (!$deprecated): ?> - <span title="<?= getMemberWithoutSystem($name)["display_name"] ?? getMemberWithoutSystem($name)["display_name"] ?>" style="display: inline-block;<?= $longPonyList && $index % 2 === 0 ? "position:absolute;margin-left:-12px;z-index:" . (999 - $index) . ";" : "position:relative;z-index:" . (999 - $index) . ";" ?>"> - <img src="/assets/uploads/pt-<?= getMemberWithoutSystem($name)["name"] ?>.png" style="width:24px;"> - </span> - <?php $index++; endif; endforeach; ?> - <?php foreach ($uniquePonies as $name => $deprecated): if ($deprecated): ?> - <span title="<?= strip_tags(getMemberWithoutSystem($name)["display_name"] ?? getMemberWithoutSystem($name)["name"]) ?> (deprecated)" style="opacity:.5;display: inline-block;<?= $longPonyList && $index % 2 === 0 ? "position:absolute;margin-left:-12px;z-index:" . (999 - $index) . ";" : "position:relative;z-index:" . (999 - $index) . ";" ?>"> - <img src="/assets/uploads/pt-<?= getMemberWithoutSystem($name)["name"] ?>.png" style="width:24px;"> - </span> - <?php $index++; endif; endforeach; ?> - </div> - --> - <div style="text-align: right;"> - <?php if ($item["type"] === "affectionate"): ?> - <span style="" class="badge rounded-pill bg-primary">Affectionate</span> - <?php endif; ?> - <?php if ($item["type"] === "sexual"): ?> - <span style="" class="badge rounded-pill bg-danger">Sexual</span> - <?php endif; ?> - <?php if ($item["type"] === "mixed"): ?> - <span style="" class="badge rounded-pill bg-success">Mixed</span> - <?php endif; ?> - </div> - </a> - <?php endforeach; ?> - </div> - </div> - - <div id="search-results" class="list-group"></div> - - <div id="page-content"> - <hr> - <p>Not finding what you are looking for? <a onclick="event.target.blur(); document.getElementById('creator-title').focus();" href="#" data-bs-toggle="modal" data-bs-target="#creator">Create an action.</a></p> - </div> - - <script> - window.actions = JSON.parse(atob(`<?= base64_encode(json_encode(array_values(json_decode(file_get_contents($_SERVER['DOCUMENT_ROOT'] . "/includes/data/actions/actions.json"), true)))) ?>`)); - </script> - - <div class="modal fade" id="creator"> - <div class="modal-dialog"> - <div class="modal-content"> - <div class="modal-header"> - <h4 class="modal-title">Create a new action</h4> - <button type="button" class="btn-close" data-bs-dismiss="modal"></button> - </div> - - <div class="modal-body"> - <form method="post"> - <input id="creator-title" type="text" placeholder="Action title" name="name" class="form-control" style="color:white;background:#111;border-color:#222;margin-bottom:10px;"> - <select name="type" class="form-select" style='color:white;background-color:#111;border-color:#222;background-image:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3e%3cpath fill='none' stroke='%23ffffff' stroke-linecap='round' stroke-linejoin='round' stroke-width='2' d='M2 5l6 6 6-6'/%3e%3c/svg%3e");margin-bottom:10px;'> - <option value="0" selected>Affectionate</option> - <option value="1">Sexual</option> - <option value="2">Mixed</option> - </select> - - <div class="alert alert-secondary" style="display:none;"> - <p>The following actions might be the same as the one you are trying to add:</p> - <ul> - <li>Action 1</li> - <li>Action 2</li> - <li>Action 3</li> - </ul> - </div> - - <label style="margin-left:5px;"> - <input type="checkbox" name="consent"> - Requires consent - </label> - - <div style="display: none;"> - <hr> - - <p>Select the groups of ponies who can do this action:</p> - <?php - - $members = scoreOrderGlobal(); - $relations = []; - - foreach ($members as $member) { - foreach ([ - ...array_map(function ($i) { - $r = [ - "name" => $i - ]; - $r["type"] = "marefriends"; - return $r; - }, $member["_metadata"]["marefriends"] ?? []), - ...array_map(function ($i) { - $r = [ - "name" => $i - ]; - $r["type"] = "sisters"; - return $r; - }, $member["_metadata"]["sisters"] ?? []), - ...array_map(function ($i) { - $r = [ - "name" => $i - ]; - $r["type"] = "caretaking"; - return $r; - }, $member["_metadata"]["caretakers"] ?? []) - ] as $rel) { - $id = $rel["name"]; - $otherMember = getSystemMember(explode("/", $id)[0], explode("/", $id)[1]); - - $parts = [ - $member["id"], - $otherMember["id"] - ]; - - asort($parts); - - $relations[implode("-", $parts)] = [ - "name" => getMiniName($member["display_name"] ?? $member["name"]) . " and " . getMiniName($otherMember["display_name"] ?? $otherMember["name"]), - "type" => $rel["type"], - "images" => [ - file_exists($_SERVER['DOCUMENT_ROOT'] . "/assets/uploads/pt-$member[name].png") ? "/assets/uploads/pt-$member[name].png" : "/assets/uploads/pt.png", - file_exists($_SERVER['DOCUMENT_ROOT'] . "/assets/uploads/pt-$otherMember[name].png") ? "/assets/uploads/pt-$otherMember[name].png" : "/assets/uploads/pt.png", - ] - ]; - } - } - - foreach ($relations as $id => $relation): - ?> - <label style="display:block;" class="creator-relation"> - <input name="relations[<?= $id ?>]" style="display:none;" type="checkbox" class="checkbox-input"> - - <img style="vertical-align: middle;width:24px;height:24px;" src="<?= $relation["images"][0] ?>"> - <img style="vertical-align: middle;width:24px;height:24px;" src="<?= $relation["images"][1] ?>"> - <span style="vertical-align: middle;"><?= $relation["name"] ?></span> - - <span style="float:right;margin-top:3px;" class="badge rounded-pill bg-<?= match ($relation["type"]) { - "marefriends" => "danger", - "sisters" => "success", - "caretaking" => "primary" - } ?>"><?= match ($relation["type"]) { - "marefriends" => "Marefriends", - "sisters" => "Sisters", - "caretaking" => "Caretaker" - } ?></span> - </label> - <?php endforeach; ?></div> - - <p style="margin-top:10px;">You can add additional data (description, example, how to do the action IRL) after creating the action.</p> - <input type="hidden" name="createAction"> - <input type="submit" class="btn btn-primary" value="Create"> - </form> - </div> - </div> - </div> - </div> - - <?php endif; ?> - </div> -</div> - -<!--suppress JSUnresolvedFunction --> -<script> - Array.from(document.getElementsByClassName("checkbox-input")).forEach((el) => { - el.onchange = () => { - let parent = el.parentElement; - - if (el.checked) { - parent.classList.add("checked"); - } else { - parent.classList.remove("checked"); - } - } - }); - - const fuse = new Fuse(window.actions, { - includeScore: true, - keys: [ - { - name: 'name', - weight: 1 - }, - { - name: 'description', - weight: 1 - }, - { - name: 'example', - weight: 0.7 - }, - { - name: 'irl', - weight: 0.5 - } - ] - }) - - function search() { - let query = document.getElementById("search").value; - let results = fuse.search(query).map((i) => { - return { - id: i.item.id, - score: i.score - }; - }); - - let unfiltered = results; - - results = results.filter((i) => { - return i.score < 0.7; - }); - - console.log("Before:", unfiltered, "After:", results); - - document.getElementById("list").style.display = "none"; - document.getElementById("search-results").style.display = "block"; - document.getElementById("search-results").innerHTML = ""; - - for (let result of results) { - document.getElementById("search-results").innerHTML += document.getElementById("action-" + result.id).outerHTML; - } - - console.log(results); - - if (query.trim() === "") { - document.getElementById("list").style.display = "block"; - document.getElementById("search-results").style.display = "none"; - } - } - - function changeMixed() { - let value = document.getElementById("editor-type").value; - console.log(value); - - if (value === "2") { - Array.from(document.getElementsByClassName("creator-relation")).forEach((el) => { - el.classList.add("mixed"); - }); - } else { - Array.from(document.getElementsByClassName("creator-relation")).forEach((el) => { - el.classList.remove("mixed"); - }); - } - } -</script> - -<style> - .modal-header { - border-bottom: 1px solid #353738; - } - - .modal-content { - border: 1px solid rgba(255, 255, 255, .2); - background-color: #111; - } - - .btn-close { - filter: invert(1); - } - - .creator-relation { - border-radius: 10px; - padding: 5px 10px; - opacity: .5; - } - - .creator-relation.checked { - background-color: rgba(255, 255, 255, .1); - opacity: 1; - } - - .creator-relation:hover { - background-color: rgba(255, 255, 255, .1); - } - - .creator-relation.checked:hover { - background-color: rgba(255, 255, 255, .25) !important; - } - - .creator-relation.checked .deprecated { - display: block !important; - } - - .creator-relation.mixed.checked .sexual { - display: block !important; - } - - .list-group-item { - color: #fff; - background-color: #222; - border: 1px solid rgba(255, 255, 255, .125); - } - - .list-group-item.disabled { - color: #fff; - background-color: #222; - border-color: rgba(255, 255, 255, .125); - opacity: .75; - } - - .list-group-item:hover { - background-color: #252525; - color: #ddd; - } - - .list-group-item:active, .list-group-item:focus { - background-color: #272727; - color: #bbb; - } - - @media (max-width: 991px) { - .action-listing { - grid-template-columns: 1fr !important; - text-align: center !important; - } - - .action-listing > * { - margin-bottom: 10px; - text-align: center !important; - } - - .action-listing > *:nth-last-child(1) { - margin-bottom: 0 !important; - } - - .action-listing img { - width: 32px !important; - } - } - - .toys-list-inner { - display: grid; - grid-template-columns: repeat(4, 1fr); - background-color: #111111; - box-sizing: border-box; - grid-gap: 1px; - } - - .toys-list-inner > * { - text-decoration: none !important; - box-shadow: 0 0 0 1px #2f2f2f; - padding: 5px 10px; - } - - .toys-list-inner > *:nth-child(1) { - border-top-left-radius: 5px; - } - - .toys-list-inner > *:nth-child(4) { - border-top-right-radius: 5px; - } - - .toys-list-inner > *:nth-last-child(4) { - border-bottom-left-radius: 5px; - } - - .toys-list-inner > *:nth-last-child(1) { - border-bottom-right-radius: 5px; - } -</style> - -<?php require_once $_SERVER['DOCUMENT_ROOT'] . '/includes/footer.inc'; ?> diff --git a/pages/api.inc b/pages/api.inc index 1d83985..f71ac10 100644 --- a/pages/api.inc +++ b/pages/api.inc @@ -8,8 +8,8 @@ if (str_ends_with($_GET['_'], "/")) { $toplevel = explode("/", $pagename)[1]; -if (file_exists($_SERVER['DOCUMENT_ROOT'] . "/api/" . $toplevel . ".php")) { - require_once $_SERVER['DOCUMENT_ROOT'] . "/api/" . $toplevel . ".php"; +if (file_exists($_SERVER['DOCUMENT_ROOT'] . "/pages/api/" . $toplevel . ".php")) { + require_once $_SERVER['DOCUMENT_ROOT'] . "/pages/api/" . $toplevel . ".php"; } else { header("HTTP/1.1 500 Internal Server Error"); echo("Endpoint not found"); diff --git a/pages/api/cloudburst-img-round.php b/pages/api/cloudburst-img-round.php new file mode 100644 index 0000000..6400499 --- /dev/null +++ b/pages/api/cloudburst-img-round.php @@ -0,0 +1,94 @@ +<?php + +$fronters = json_decode(file_get_contents($_SERVER['DOCUMENT_ROOT'] . "/includes/data/ynmuc/fronters.json"), true); + +$url = isset($fronters['members'][0]) ? ($fronters['members'][0]["avatar_url"] ?? "/assets/uploads/raindrops.png") : "/assets/uploads/raindrops.png"; +file_put_contents("/tmp/temp", file_get_contents($url)); + +function imageCreateCorners($sourceImageFile, $radius) { + # test source image + if (file_exists($sourceImageFile)) { + $res = is_array($info = getimagesize($sourceImageFile)); + } + else $res = false; + + # open image + if ($res) { + $w = $info[0]; + $h = $info[1]; + switch ($info['mime']) { + case 'image/jpeg': $src = imagecreatefromjpeg($sourceImageFile); + break; + case 'image/gif': $src = imagecreatefromgif($sourceImageFile); + break; + case 'image/png': $src = imagecreatefrompng($sourceImageFile); + break; + default: + $res = false; + } + } + + # create corners + if ($res) { + + $q = 10; # change this if you want + $radius *= $q; + + # find unique color + do { + $r = rand(0, 255); + $g = rand(0, 255); + $b = rand(0, 255); + } + while (imagecolorexact($src, $r, $g, $b) < 0); + + $nw = $w*$q; + $nh = $h*$q; + + $img = imagecreatetruecolor($nw, $nh); + $alphacolor = imagecolorallocatealpha($img, $r, $g, $b, 127); + imagealphablending($img, false); + imagesavealpha($img, true); + imagefilledrectangle($img, 0, 0, $nw, $nh, $alphacolor); + + imagefill($img, 0, 0, $alphacolor); + imagecopyresampled($img, $src, 0, 0, 0, 0, $nw, $nh, $w, $h); + + imagearc($img, $radius-1, $radius-1, $radius*2, $radius*2, 180, 270, $alphacolor); + imagefilltoborder($img, 0, 0, $alphacolor, $alphacolor); + imagearc($img, $nw-$radius, $radius-1, $radius*2, $radius*2, 270, 0, $alphacolor); + imagefilltoborder($img, $nw-1, 0, $alphacolor, $alphacolor); + imagearc($img, $radius-1, $nh-$radius, $radius*2, $radius*2, 90, 180, $alphacolor); + imagefilltoborder($img, 0, $nh-1, $alphacolor, $alphacolor); + imagearc($img, $nw-$radius, $nh-$radius, $radius*2, $radius*2, 0, 90, $alphacolor); + imagefilltoborder($img, $nw-1, $nh-1, $alphacolor, $alphacolor); + imagealphablending($img, true); + imagecolortransparent($img, $alphacolor); + + # resize image down + $dest = imagecreatetruecolor($w, $h); + imagealphablending($dest, false); + imagesavealpha($dest, true); + imagefilledrectangle($dest, 0, 0, $w, $h, $alphacolor); + imagecopyresampled($dest, $img, 0, 0, 0, 0, $w, $h, $nw, $nh); + + # output image + $res = $dest; + imagedestroy($src); + imagedestroy($img); + } + + return $res; +} + +header("Content-Type: image/png"); + +$id = bin2hex(random_bytes(8)); +exec('convert -size 128x128 xc:none -draw "roundrectangle 0,0,128,128,128,128" /tmp/' . $id . '-mask.png', $out); + +exec('convert -resize 128x128 "/tmp/temp" /tmp/' . $id . '-source.png'); +exec('convert /tmp/' . $id . '-source.png -matte /tmp/' . $id . '-mask.png -compose DstIn -composite /tmp/' . $id . '.png', $out2); + +unlink("/tmp/temp"); + +echo(file_get_contents('/tmp/' . $id . '.png'));
\ No newline at end of file diff --git a/pages/api/cloudburst-img.php b/pages/api/cloudburst-img.php new file mode 100644 index 0000000..1967a90 --- /dev/null +++ b/pages/api/cloudburst-img.php @@ -0,0 +1,11 @@ +<?php + +require_once $_SERVER['DOCUMENT_ROOT'] . "/includes/functions.inc"; +$fronters = json_decode(file_get_contents($_SERVER['DOCUMENT_ROOT'] . "/includes/data/ynmuc/fronters.json"), true); + +$url = isset($fronters['members'][0]) ? ($fronters['members'][0]["avatar_url"] ? $_SERVER['DOCUMENT_ROOT'] . getAsset("ynmuc", $fronters['members'][0]["id"]) : $_SERVER['DOCUMENT_ROOT'] . "/uploads/raindrops.png") : $_SERVER['DOCUMENT_ROOT'] . "/uploads/raindrops.png"; +file_put_contents("/tmp/temp", file_get_contents($url)); +header("Content-Type: " . mime_content_type("/tmp/temp")); +unlink("/tmp/temp"); + +echo(file_get_contents($url));
\ No newline at end of file diff --git a/pages/api/cloudburst-img2-round.php b/pages/api/cloudburst-img2-round.php new file mode 100644 index 0000000..4ca772f --- /dev/null +++ b/pages/api/cloudburst-img2-round.php @@ -0,0 +1,94 @@ +<?php + +$fronters = json_decode(file_get_contents($_SERVER['DOCUMENT_ROOT'] . "/includes/data/ynmuc/fronters.json"), true); + +$url = isset($fronters['members'][1]) ? ($fronters['members'][1]["avatar_url"] ?? "/assets/uploads/raindrops.png") : "/assets/uploads/raindrops.png"; +file_put_contents("/tmp/temp", file_get_contents($url)); + +function imageCreateCorners($sourceImageFile, $radius) { + # test source image + if (file_exists($sourceImageFile)) { + $res = is_array($info = getimagesize($sourceImageFile)); + } + else $res = false; + + # open image + if ($res) { + $w = $info[0]; + $h = $info[1]; + switch ($info['mime']) { + case 'image/jpeg': $src = imagecreatefromjpeg($sourceImageFile); + break; + case 'image/gif': $src = imagecreatefromgif($sourceImageFile); + break; + case 'image/png': $src = imagecreatefrompng($sourceImageFile); + break; + default: + $res = false; + } + } + + # create corners + if ($res) { + + $q = 10; # change this if you want + $radius *= $q; + + # find unique color + do { + $r = rand(0, 255); + $g = rand(0, 255); + $b = rand(0, 255); + } + while (imagecolorexact($src, $r, $g, $b) < 0); + + $nw = $w*$q; + $nh = $h*$q; + + $img = imagecreatetruecolor($nw, $nh); + $alphacolor = imagecolorallocatealpha($img, $r, $g, $b, 127); + imagealphablending($img, false); + imagesavealpha($img, true); + imagefilledrectangle($img, 0, 0, $nw, $nh, $alphacolor); + + imagefill($img, 0, 0, $alphacolor); + imagecopyresampled($img, $src, 0, 0, 0, 0, $nw, $nh, $w, $h); + + imagearc($img, $radius-1, $radius-1, $radius*2, $radius*2, 180, 270, $alphacolor); + imagefilltoborder($img, 0, 0, $alphacolor, $alphacolor); + imagearc($img, $nw-$radius, $radius-1, $radius*2, $radius*2, 270, 0, $alphacolor); + imagefilltoborder($img, $nw-1, 0, $alphacolor, $alphacolor); + imagearc($img, $radius-1, $nh-$radius, $radius*2, $radius*2, 90, 180, $alphacolor); + imagefilltoborder($img, 0, $nh-1, $alphacolor, $alphacolor); + imagearc($img, $nw-$radius, $nh-$radius, $radius*2, $radius*2, 0, 90, $alphacolor); + imagefilltoborder($img, $nw-1, $nh-1, $alphacolor, $alphacolor); + imagealphablending($img, true); + imagecolortransparent($img, $alphacolor); + + # resize image down + $dest = imagecreatetruecolor($w, $h); + imagealphablending($dest, false); + imagesavealpha($dest, true); + imagefilledrectangle($dest, 0, 0, $w, $h, $alphacolor); + imagecopyresampled($dest, $img, 0, 0, 0, 0, $w, $h, $nw, $nh); + + # output image + $res = $dest; + imagedestroy($src); + imagedestroy($img); + } + + return $res; +} + +header("Content-Type: image/png"); + +$id = bin2hex(random_bytes(8)); +exec('convert -size 128x128 xc:none -draw "roundrectangle 0,0,128,128,128,128" /tmp/' . $id . '-mask.png', $out); + +exec('convert -resize 128x128 "/tmp/temp" /tmp/' . $id . '-source.png'); +exec('convert /tmp/' . $id . '-source.png -matte /tmp/' . $id . '-mask.png -compose DstIn -composite /tmp/' . $id . '.png', $out2); + +unlink("/tmp/temp"); + +echo(file_get_contents('/tmp/' . $id . '.png'));
\ No newline at end of file diff --git a/pages/api/cloudburst-two.php b/pages/api/cloudburst-two.php new file mode 100644 index 0000000..8272d81 --- /dev/null +++ b/pages/api/cloudburst-two.php @@ -0,0 +1,8 @@ +<?php + +header("Content-Type: text/plain"); + +$fronters = json_decode(file_get_contents($_SERVER['DOCUMENT_ROOT'] . "/includes/data/ynmuc/fronters.json"), true); +echo(json_encode([ + "multiple" => count($fronters["members"]) > 1 +]));
\ No newline at end of file diff --git a/pages/api/cloudburst.php b/pages/api/cloudburst.php new file mode 100644 index 0000000..2750a98 --- /dev/null +++ b/pages/api/cloudburst.php @@ -0,0 +1,6 @@ +<?php + +header("Content-Type: text/plain"); + +$fronters = json_decode(file_get_contents($_SERVER['DOCUMENT_ROOT'] . "/includes/data/ynmuc/fronters.json"), true); +echo($fronters['members'][0]['display_name'] ?? $fronters['members'][0]['name']);
\ No newline at end of file diff --git a/pages/api/computer.php b/pages/api/computer.php new file mode 100644 index 0000000..cd065e7 --- /dev/null +++ b/pages/api/computer.php @@ -0,0 +1,50 @@ +<?php + +require_once $_SERVER['DOCUMENT_ROOT'] . "/includes/session.inc"; global $isLoggedIn; global $_PROFILE; +if (!$isLoggedIn) header("Location: /-/login") and die(); + +$request_raw = file_get_contents('php://input'); +$json_object = json_decode($request_raw, true); + +$host = md5($json_object['host']); + +switch ($_GET['type']) { + case "heartbeat": + if (file_exists($_SERVER['DOCUMENT_ROOT'] . "/includes/data/computers/metadata/" . $_PROFILE['login'] . "-" . $host . ".json")) { + $data = json_decode(file_get_contents($_SERVER['DOCUMENT_ROOT'] . "/includes/data/computers/metadata/" . $_PROFILE['login'] . "-" . $host . ".json"), true); + $data["date"] = date('c'); + file_put_contents($_SERVER['DOCUMENT_ROOT'] . "/includes/data/computers/metadata/" . $_PROFILE['login'] . "-" . $host . ".json", json_encode($data)); + } + break; + + case "screenshot": + $id = $json_object['id']; + $data = base64_decode($json_object['data']); + + if (!file_exists($_SERVER['DOCUMENT_ROOT'] . "/includes/data/computers/screens")) mkdir($_SERVER['DOCUMENT_ROOT'] . "/includes/data/computers/screens"); + file_put_contents($_SERVER['DOCUMENT_ROOT'] . "/includes/data/computers/screens/" . $_PROFILE['login'] . "-" . $host . "-" . $id . ".jpg", $data); + break; + + case "window": + $id = sha1($json_object['id']); + $data = base64_decode($json_object['data']); + + if (!file_exists($_SERVER['DOCUMENT_ROOT'] . "/includes/data/computers/windows")) mkdir($_SERVER['DOCUMENT_ROOT'] . "/includes/data/computers/windows"); + file_put_contents($_SERVER['DOCUMENT_ROOT'] . "/includes/data/computers/windows/" . $_PROFILE['login'] . "-" . $host . "-" . $id . ".jpg", $data); + + if (isset($json_object['icon'])) { + $data2 = base64_decode($json_object['icon']); + file_put_contents($_SERVER['DOCUMENT_ROOT'] . "/includes/data/computers/windows/" . $_PROFILE['login'] . "-" . $host . "-" . $id . ".png", $data2); + } else { + file_put_contents($_SERVER['DOCUMENT_ROOT'] . "/includes/data/computers/windows/" . $_PROFILE['login'] . "-" . $host . "-" . $id . ".png", ""); + } + + break; + + case "data": + if (!file_exists($_SERVER['DOCUMENT_ROOT'] . "/includes/data/computers/metadata")) mkdir($_SERVER['DOCUMENT_ROOT'] . "/includes/data/computers/metadata"); + file_put_contents($_SERVER['DOCUMENT_ROOT'] . "/includes/data/computers/metadata/" . $_PROFILE['login'] . "-" . $host . ".json", json_encode($json_object)); + break; +} + +die("OK");
\ No newline at end of file diff --git a/pages/api/data.php b/pages/api/data.php new file mode 100644 index 0000000..0a1b01b --- /dev/null +++ b/pages/api/data.php @@ -0,0 +1,12 @@ +<?php + +require_once $_SERVER['DOCUMENT_ROOT'] . "/includes/session.inc"; global $isLoggedIn; +require_once $_SERVER['DOCUMENT_ROOT'] . "/includes/bitset.inc"; +if (!$isLoggedIn) header("Location: /-/login") and die(); + +if (!isset($_GET['f']) || !file_exists($_SERVER['DOCUMENT_ROOT'] . "/includes/data/" . $_GET['f'])) { + die(); +} else { + header("Content-Type: " . mime_content_type($_SERVER['DOCUMENT_ROOT'] . "/includes/data/" . $_GET['f'])); + die(file_get_contents($_SERVER['DOCUMENT_ROOT'] . "/includes/data/" . $_GET['f'])); +}
\ No newline at end of file diff --git a/pages/api/docs.php b/pages/api/docs.php new file mode 100644 index 0000000..89e9216 --- /dev/null +++ b/pages/api/docs.php @@ -0,0 +1,29 @@ +<?php + +require_once $_SERVER['DOCUMENT_ROOT'] . "/includes/session.inc"; global $isLoggedIn; global $_PROFILE; +if (!$isLoggedIn) header("Location: /-/login") and die(); + +$request_raw = file_get_contents('php://input'); +$json_object = json_decode($request_raw, true); + +$select = $_GET['id'] ?? null; + +if (isset($select)) { + if (ctype_alnum($select) && file_exists($_SERVER['DOCUMENT_ROOT'] . "/includes/data/docs/" . $select . ".json")) { + $id = $select; + $data = json_decode(file_get_contents($_SERVER['DOCUMENT_ROOT'] . "/includes/data/docs/" . $select . ".json"), true); + } else { + die("Not found"); + } +} else { + die("Not set"); +} + +if ($json_object["content"]) $data["contents"] = $json_object["content"]; +if ($json_object["name"]) $data["name"] = $json_object["name"]; +if ($json_object["category"]) $data["category"] = trim($json_object["category"]) !== "" && trim($json_object["category"]) !== "Unsorted" && trim($json_object["category"]) !== "unsorted" && trim($json_object["category"]) !== "/no" && trim($json_object["category"]) !== "Unsort" && trim($json_object["category"]) !== "unsort" ? $json_object["category"] : null; + +$data["last"]["date"] = time(); +$data["last"]["author"] = $_PROFILE['login']; + +file_put_contents($_SERVER['DOCUMENT_ROOT'] . "/includes/data/docs/" . $select . ".json", utf8_encode(json_encode($data)));
\ No newline at end of file diff --git a/pages/api/emergency-real.php b/pages/api/emergency-real.php new file mode 100644 index 0000000..2dd7172 --- /dev/null +++ b/pages/api/emergency-real.php @@ -0,0 +1,22 @@ +<?php + +require_once $_SERVER['DOCUMENT_ROOT'] . "/includes/session.inc"; global $isLoggedIn; +if (!$isLoggedIn) header("Location: /-/login") and die(); +global $_PROFILE; + +$ntfy = json_decode(file_get_contents($_SERVER['DOCUMENT_ROOT'] . "/includes/app.json"), true)["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" . + "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!" + ] +])); + +die();
\ No newline at end of file diff --git a/pages/api/emergency.php b/pages/api/emergency.php new file mode 100644 index 0000000..e0726e7 --- /dev/null +++ b/pages/api/emergency.php @@ -0,0 +1,22 @@ +<?php + +require_once $_SERVER['DOCUMENT_ROOT'] . "/includes/session.inc"; global $isLoggedIn; +if (!$isLoggedIn) header("Location: /-/login") and die(); +global $_PROFILE; + +$ntfy = json_decode(file_get_contents($_SERVER['DOCUMENT_ROOT'] . "/includes/app.json"), true)["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" . + "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]" + ] +])); + +die();
\ No newline at end of file diff --git a/pages/api/fronter.php b/pages/api/fronter.php new file mode 100644 index 0000000..51ee4ee --- /dev/null +++ b/pages/api/fronter.php @@ -0,0 +1,113 @@ +<?php + +require_once $_SERVER['DOCUMENT_ROOT'] . "/includes/session.inc"; global $isLoggedIn; global $isLowerLoggedIn; +if (!$isLoggedIn || $isLowerLoggedIn) { + header("Location: /-/login"); + die(); +} + +$system = $_GET['s'] ?? null; +$member = $_GET['m'] ?? null; +$index = (int)$_GET['i'] ?? null; +$type = $_GET['t'] ?? null; +$date = $_GET['d'] ?? null; + +if (!isset($system) || trim($system) === "" || strlen($system) !== 5 || !preg_match("/[a-z]/i", $system) || ($system !== "gdapd" && $system !== "ynmuc")) + peh_error("System not found", 404); + +if (!isset($type) || trim($type) === "") + peh_error("Type not found", 404); + +if (!isset($date) || trim($date) === "" || strlen($date) !== 10 || !preg_match("/[\d-]/i", $date)) + peh_error("Date not found", 404); + +$list = json_decode(file_get_contents($_SERVER['DOCUMENT_ROOT'] . "/includes/data/planner/$system.json"), true); + +function moveElement(&$array, $a, $b) { + $out = array_splice($array, $a, 1); + array_splice($array, $b, 0, $out); +} + +switch ($type) { + case "add": + if (!isset($member) || trim($member) === "" || strlen($member) !== 5 || !preg_match("/[a-z]/i", $member)) + if ($member !== null && $member !== "null") peh_error("System member not found", 404); + + if (!isset($list[$date])) $list[$date] = []; + $list[$date][] = [$member, null]; + break; + + case "cofront": + if (!isset($index) || trim($index) === "" || is_integer($index)) + if ($index !== null && $index !== "null") peh_error("Invalid index", 400); + + $day = $list[$date]; + + if (!isset($day[$index])) + if ($index !== null && $index !== "null") peh_error("Index not found", 404); + + if (!isset($member) || trim($member) === "" || strlen($member) !== 5 || !preg_match("/[a-z]/i", $member)) + if ($member !== null && $member !== "null") peh_error("System member not found", 404); + + $list[$date][$index][1] = $member; + break; + + case "delete": + if (!isset($index) || trim($index) === "" || is_integer($index)) + if ($index !== null && $index !== "null") peh_error("Invalid index", 400); + + $day = $list[$date]; + + if (!isset($day[$index])) + if ($index !== null && $index !== "null") peh_error("Index not found", 404); + + unset($day[$index]); + $list[$date] = array_values($day); + + break; + + case "codelete": + if (!isset($index) || trim($index) === "" || is_integer($index)) + if ($index !== null && $index !== "null") peh_error("Invalid index", 400); + + $day = $list[$date]; + + if (!isset($day[$index])) + if ($index !== null && $index !== "null") peh_error("Index not found", 404); + + $list[$date][$index][1] = null; + + break; + + case "down": + if (!isset($index) || trim($index) === "" || is_integer($index)) + if ($index !== null && $index !== "null") peh_error("Invalid index", 400); + + if (!isset($day[$index])) + if ($index !== null && $index !== "null") peh_error("Index not found", 404); + + $day = $list[$date]; + moveElement($list[$date], $index, $index + 1 < count($list[$date]) ? $index + 1 : $index); + + break; + + case "up": + if (!isset($index) || trim($index) === "" || is_integer($index)) + if ($index !== null && $index !== "null") peh_error("Invalid index", 400); + + if (!isset($day[$index])) + if ($index !== null && $index !== "null") peh_error("Index not found", 404); + + $day = $list[$date]; + moveElement($list[$date], $index, $index - 1 > -1 ? $index - 1 : $index); + + break; + + default: + peh_error("Invalid type name", 400); + break; +} + +file_put_contents($_SERVER['DOCUMENT_ROOT'] . "/includes/data/planner/$system.json", json_encode($list)); + +die();
\ No newline at end of file diff --git a/pages/api/pluralkit-integration.php b/pages/api/pluralkit-integration.php new file mode 100644 index 0000000..0793873 --- /dev/null +++ b/pages/api/pluralkit-integration.php @@ -0,0 +1,176 @@ +<?php + +require_once $_SERVER['DOCUMENT_ROOT'] . "/includes/agewarning.inc"; + +$app = json_decode(file_get_contents($_SERVER['DOCUMENT_ROOT'] . "/includes/app.json"), true); +$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"]; + +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]; +} else { + header("HTTP/1.1 404 Not Found") and die(); +} + +if ($user === null) { + header("HTTP/1.1 500 Internal Server Error") and die(); +} + +if (!in_array($user, array_keys($data))) { + header("HTTP/1.1 404 Not Found") and die(); +} + +if ($input["signing_token"] !== $data[$user]) { + header("HTTP/1.1 401 Unauthorized") and die(); +} + +if ($input['system_id'] === "7d9f543e-f742-40f6-9d07-86c3f2983124") { + $system = "gdapd"; + $name = "Raindrops System"; +} elseif ($input['system_id'] === "ade46823-206b-4b0c-ad3c-caae934a5f3b") { + $system = "ynmuc"; + $name = "Cloudburst System"; +} elseif (isset($app["other"]) && $input["system_id"] === $app["other"]["uuid"]) { + $system = $app["other"]["id"]; + $name = $app["other"]["name"]; +} else { + die(); +} + +$lastFronter = json_decode(@file_get_contents($_SERVER['DOCUMENT_ROOT'] . "/includes/data/$system/last.json"), true) ?? ""; + +if ($input["type"] === "CREATE_SWITCH" || $input["type"] === "UPDATE_SWITCH" || $input["type"] === "DELETE_SWITCH") { + if ($system === $app["other"]["id"]) { + file_put_contents($_SERVER['DOCUMENT_ROOT'] . "/includes/data/$system/fronters.json", file_get_contents("https://pluralkit.equestria.dev/v2/systems/$input[system_id]/fronters"), false, stream_context_create([ + 'http' => [ + 'method' => 'GET', + 'header' => + "Authorization: " . $app["other"]["token"] . "\r\n" + ] + ])); + file_put_contents($_SERVER['DOCUMENT_ROOT'] . "/includes/data/$system/switches.json", file_get_contents("https://pluralkit.equestria.dev/v2/systems/$input[system_id]/switches"), false, stream_context_create([ + 'http' => [ + 'method' => 'GET', + 'header' => + "Authorization: " . $app["other"]["token"] . "\r\n" + ] + ])); + } else { + file_put_contents($_SERVER['DOCUMENT_ROOT'] . "/includes/data/$system/fronters.json", file_get_contents("https://pluralkit.equestria.dev/v2/systems/$input[system_id]/fronters")); + file_put_contents($_SERVER['DOCUMENT_ROOT'] . "/includes/data/$system/switches.json", file_get_contents("https://pluralkit.equestria.dev/v2/systems/$input[system_id]/switches")); + } + + $fronters = json_decode(file_get_contents($_SERVER['DOCUMENT_ROOT'] . "/includes/data/$system/fronters.json"), true); + $currentFronter = $fronters["members"][0]["id"]; + file_put_contents($_SERVER['DOCUMENT_ROOT'] . "/includes/data/$system/last.json", json_encode($currentFronter)); + + $ntfy = json_decode(file_get_contents($_SERVER['DOCUMENT_ROOT'] . "/includes/app.json"), true)["ntfy"]; + + if (count($fronters["members"]) > 0 && ($system !== $app["other"]["id"] || !isset($app["other"]))) { + foreach ($fronters["members"] as $member) { + if (file_exists($_SERVER['DOCUMENT_ROOT'] . "/includes/data/metadata/" . $member["id"] . ".json")) { + $metadata = json_decode(file_get_contents($_SERVER['DOCUMENT_ROOT'] . "/includes/data/metadata/" . $member["id"] . ".json"), true); + + if (!isset($metadata["birth"])) { + showWarning($member["display_name"] ?? $member["name"], $member["name"], $system); + } else if (isset($metadata['birth']["age"]) && $metadata["birth"]["age"] === 0 && (!isset($metadata['birth']["year"]) || $metadata["birth"]["year"] < 1900)) { + showWarning($member["display_name"] ?? $member["name"], $member["name"], $system); + } else if (isset($metadata['birth']["year"]) && $metadata["birth"]["year"] < 1900) { + showWarning($member["display_name"] ?? $member["name"], $member["name"], $system); + } else if (!isset($metadata['birth']["year"]) && !isset($metadata['birth']["age"])) { + showWarning($member["display_name"] ?? $member["name"], $member["name"], $system); + } + } + } + } + + if ($system !== $app["other"]["id"] || !isset($app["other"])) { + if (count($fronters["members"]) > 1) { + $context = stream_context_create([ + 'http' => [ + 'method' => 'POST', + 'header' => + "Content-Type: text/plain\r\n" . + "Title: 🐴 Switch occurred in the $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" + ] + ]); + } else if (count($fronters["members"]) > 0) { + $context = stream_context_create([ + 'http' => [ + 'method' => 'POST', + 'header' => + "Content-Type: text/plain\r\n" . + "Title: 🐴 Switch occurred in the $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" + ] + ]); + } else { + $context = stream_context_create([ + 'http' => [ + 'method' => 'POST', + 'header' => + "Content-Type: text/plain\r\n" . + "Title: 🐴 Switch occurred in the $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" + ] + ]); + } + + file_get_contents('https://' . $ntfy["server"] . '/public-switches', false, $context); + } + + if ($system === "gdapd") { + $topic = "public-switches-raindrops"; + + if (count($fronters["members"]) > 0) { + file_get_contents('https://' . $ntfy["server"] . '/public-switches-fr', false, stream_context_create([ + 'http' => [ + 'method' => 'POST', + 'header' => + "Content-Type: text/plain\r\n" . + "Title: 🐴 $name vient de switch\r\n" . + "Priority: default\r\n" . + "Tags: switch\r\n" . + "Actions: view, Voir sur Cold Haze, https://fr.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"]) . " est désormais au front" + ] + ])); + } else { + file_get_contents('https://' . $ntfy["server"] . '/public-switches-fr', false, stream_context_create([ + 'http' => [ + 'method' => 'POST', + 'header' => + "Content-Type: text/plain\r\n" . + "Title: 🐴 $name vient de switch\r\n" . + "Priority: default\r\n" . + "Tags: switch\r\n" . + "Actions: view, Voir sur Cold Haze, https://fr.equestria.horse/, clear=true\r\n" . + "Authorization: Basic " . base64_encode($ntfy["user"] . ":" . $ntfy["password"]), + 'content' => "Le poney de trait est désormais au front" + ] + ])); + } + } else if ($system === "ynmuc") { + $topic = "public-switches-cloudburst"; + } else { + $topic = "main"; + } + + file_get_contents('https://' . $ntfy["server"] . '/' . $topic, false, $context); +}
\ No newline at end of file diff --git a/pages/api/raindrops-img-round.php b/pages/api/raindrops-img-round.php new file mode 100644 index 0000000..f733cc8 --- /dev/null +++ b/pages/api/raindrops-img-round.php @@ -0,0 +1,94 @@ +<?php + +$fronters = json_decode(file_get_contents($_SERVER['DOCUMENT_ROOT'] . "/includes/data/gdapd/fronters.json"), true); + +$url = isset($fronters['members'][0]) ? ($fronters['members'][0]["avatar_url"] ?? "/assets/uploads/raindrops.png") : "/assets/uploads/raindrops.png"; +file_put_contents("/tmp/temp", file_get_contents($url)); + +function imageCreateCorners($sourceImageFile, $radius) { + # test source image + if (file_exists($sourceImageFile)) { + $res = is_array($info = getimagesize($sourceImageFile)); + } + else $res = false; + + # open image + if ($res) { + $w = $info[0]; + $h = $info[1]; + switch ($info['mime']) { + case 'image/jpeg': $src = imagecreatefromjpeg($sourceImageFile); + break; + case 'image/gif': $src = imagecreatefromgif($sourceImageFile); + break; + case 'image/png': $src = imagecreatefrompng($sourceImageFile); + break; + default: + $res = false; + } + } + + # create corners + if ($res) { + + $q = 10; # change this if you want + $radius *= $q; + + # find unique color + do { + $r = rand(0, 255); + $g = rand(0, 255); + $b = rand(0, 255); + } + while (imagecolorexact($src, $r, $g, $b) < 0); + + $nw = $w*$q; + $nh = $h*$q; + + $img = imagecreatetruecolor($nw, $nh); + $alphacolor = imagecolorallocatealpha($img, $r, $g, $b, 127); + imagealphablending($img, false); + imagesavealpha($img, true); + imagefilledrectangle($img, 0, 0, $nw, $nh, $alphacolor); + + imagefill($img, 0, 0, $alphacolor); + imagecopyresampled($img, $src, 0, 0, 0, 0, $nw, $nh, $w, $h); + + imagearc($img, $radius-1, $radius-1, $radius*2, $radius*2, 180, 270, $alphacolor); + imagefilltoborder($img, 0, 0, $alphacolor, $alphacolor); + imagearc($img, $nw-$radius, $radius-1, $radius*2, $radius*2, 270, 0, $alphacolor); + imagefilltoborder($img, $nw-1, 0, $alphacolor, $alphacolor); + imagearc($img, $radius-1, $nh-$radius, $radius*2, $radius*2, 90, 180, $alphacolor); + imagefilltoborder($img, 0, $nh-1, $alphacolor, $alphacolor); + imagearc($img, $nw-$radius, $nh-$radius, $radius*2, $radius*2, 0, 90, $alphacolor); + imagefilltoborder($img, $nw-1, $nh-1, $alphacolor, $alphacolor); + imagealphablending($img, true); + imagecolortransparent($img, $alphacolor); + + # resize image down + $dest = imagecreatetruecolor($w, $h); + imagealphablending($dest, false); + imagesavealpha($dest, true); + imagefilledrectangle($dest, 0, 0, $w, $h, $alphacolor); + imagecopyresampled($dest, $img, 0, 0, 0, 0, $w, $h, $nw, $nh); + + # output image + $res = $dest; + imagedestroy($src); + imagedestroy($img); + } + + return $res; +} + +header("Content-Type: image/png"); + +$id = bin2hex(random_bytes(8)); +exec('convert -size 128x128 xc:none -draw "roundrectangle 0,0,128,128,128,128" /tmp/' . $id . '-mask.png', $out); + +exec('convert -resize 128x128 "/tmp/temp" /tmp/' . $id . '-source.png'); +exec('convert /tmp/' . $id . '-source.png -matte /tmp/' . $id . '-mask.png -compose DstIn -composite /tmp/' . $id . '.png', $out2); + +unlink("/tmp/temp"); + +echo(file_get_contents('/tmp/' . $id . '.png'));
\ No newline at end of file diff --git a/pages/api/raindrops-img.php b/pages/api/raindrops-img.php new file mode 100644 index 0000000..4cbac6b --- /dev/null +++ b/pages/api/raindrops-img.php @@ -0,0 +1,11 @@ +<?php + +require_once $_SERVER['DOCUMENT_ROOT'] . "/includes/functions.inc"; +$fronters = json_decode(file_get_contents($_SERVER['DOCUMENT_ROOT'] . "/includes/data/gdapd/fronters.json"), true); + +$url = isset($fronters['members'][0]) ? ($fronters['members'][0]["avatar_url"] ? $_SERVER['DOCUMENT_ROOT'] . getAsset("gdapd", $fronters['members'][0]["id"]) : $_SERVER['DOCUMENT_ROOT'] . "/uploads/raindrops.png") : $_SERVER['DOCUMENT_ROOT'] . "/uploads/raindrops.png"; +file_put_contents("/tmp/temp", file_get_contents($url)); +header("Content-Type: " . mime_content_type("/tmp/temp")); +unlink("/tmp/temp"); + +echo(file_get_contents($url));
\ No newline at end of file diff --git a/pages/api/raindrops-img2-round.php b/pages/api/raindrops-img2-round.php new file mode 100644 index 0000000..8ca6c81 --- /dev/null +++ b/pages/api/raindrops-img2-round.php @@ -0,0 +1,94 @@ +<?php + +$fronters = json_decode(file_get_contents($_SERVER['DOCUMENT_ROOT'] . "/includes/data/gdapd/fronters.json"), true); + +$url = isset($fronters['members'][1]) ? ($fronters['members'][1]["avatar_url"] ?? "/assets/uploads/raindrops.png") : "/assets/uploads/raindrops.png"; +file_put_contents("/tmp/temp", file_get_contents($url)); + +function imageCreateCorners($sourceImageFile, $radius) { + # test source image + if (file_exists($sourceImageFile)) { + $res = is_array($info = getimagesize($sourceImageFile)); + } + else $res = false; + + # open image + if ($res) { + $w = $info[0]; + $h = $info[1]; + switch ($info['mime']) { + case 'image/jpeg': $src = imagecreatefromjpeg($sourceImageFile); + break; + case 'image/gif': $src = imagecreatefromgif($sourceImageFile); + break; + case 'image/png': $src = imagecreatefrompng($sourceImageFile); + break; + default: + $res = false; + } + } + + # create corners + if ($res) { + + $q = 10; # change this if you want + $radius *= $q; + + # find unique color + do { + $r = rand(0, 255); + $g = rand(0, 255); + $b = rand(0, 255); + } + while (imagecolorexact($src, $r, $g, $b) < 0); + + $nw = $w*$q; + $nh = $h*$q; + + $img = imagecreatetruecolor($nw, $nh); + $alphacolor = imagecolorallocatealpha($img, $r, $g, $b, 127); + imagealphablending($img, false); + imagesavealpha($img, true); + imagefilledrectangle($img, 0, 0, $nw, $nh, $alphacolor); + + imagefill($img, 0, 0, $alphacolor); + imagecopyresampled($img, $src, 0, 0, 0, 0, $nw, $nh, $w, $h); + + imagearc($img, $radius-1, $radius-1, $radius*2, $radius*2, 180, 270, $alphacolor); + imagefilltoborder($img, 0, 0, $alphacolor, $alphacolor); + imagearc($img, $nw-$radius, $radius-1, $radius*2, $radius*2, 270, 0, $alphacolor); + imagefilltoborder($img, $nw-1, 0, $alphacolor, $alphacolor); + imagearc($img, $radius-1, $nh-$radius, $radius*2, $radius*2, 90, 180, $alphacolor); + imagefilltoborder($img, 0, $nh-1, $alphacolor, $alphacolor); + imagearc($img, $nw-$radius, $nh-$radius, $radius*2, $radius*2, 0, 90, $alphacolor); + imagefilltoborder($img, $nw-1, $nh-1, $alphacolor, $alphacolor); + imagealphablending($img, true); + imagecolortransparent($img, $alphacolor); + + # resize image down + $dest = imagecreatetruecolor($w, $h); + imagealphablending($dest, false); + imagesavealpha($dest, true); + imagefilledrectangle($dest, 0, 0, $w, $h, $alphacolor); + imagecopyresampled($dest, $img, 0, 0, 0, 0, $w, $h, $nw, $nh); + + # output image + $res = $dest; + imagedestroy($src); + imagedestroy($img); + } + + return $res; +} + +header("Content-Type: image/png"); + +$id = bin2hex(random_bytes(8)); +exec('convert -size 128x128 xc:none -draw "roundrectangle 0,0,128,128,128,128" /tmp/' . $id . '-mask.png', $out); + +exec('convert -resize 128x128 "/tmp/temp" /tmp/' . $id . '-source.png'); +exec('convert /tmp/' . $id . '-source.png -matte /tmp/' . $id . '-mask.png -compose DstIn -composite /tmp/' . $id . '.png', $out2); + +unlink("/tmp/temp"); + +echo(file_get_contents('/tmp/' . $id . '.png'));
\ No newline at end of file diff --git a/pages/api/raindrops-two.php b/pages/api/raindrops-two.php new file mode 100644 index 0000000..2fa09f2 --- /dev/null +++ b/pages/api/raindrops-two.php @@ -0,0 +1,8 @@ +<?php + +header("Content-Type: text/plain"); + +$fronters = json_decode(file_get_contents($_SERVER['DOCUMENT_ROOT'] . "/includes/data/gdapd/fronters.json"), true); +echo(json_encode([ + "multiple" => count($fronters["members"]) > 1 +]));
\ No newline at end of file diff --git a/pages/api/raindrops.php b/pages/api/raindrops.php new file mode 100644 index 0000000..c44faa6 --- /dev/null +++ b/pages/api/raindrops.php @@ -0,0 +1,6 @@ +<?php + +header("Content-Type: text/plain"); + +$fronters = json_decode(file_get_contents($_SERVER['DOCUMENT_ROOT'] . "/includes/data/gdapd/fronters.json"), true); +echo($fronters['members'][0]['display_name'] ?? $fronters['members'][0]['name']);
\ No newline at end of file diff --git a/pages/api/save-private.php b/pages/api/save-private.php new file mode 100644 index 0000000..de7d505 --- /dev/null +++ b/pages/api/save-private.php @@ -0,0 +1,35 @@ +<?php + +require_once $_SERVER['DOCUMENT_ROOT'] . "/includes/session.inc"; global $isLoggedIn; +if (!$isLoggedIn) header("Location: /-/login") and die(); + +$request_raw = file_get_contents('php://input'); +$json_object = json_decode($request_raw, true); + +$system = $_GET['system'] ?? null; +$member = $_GET['member'] ?? null; +$content = $json_object['content'] ?? null; + +if (!isset($system) || trim($system) === "" || strlen($system) !== 5 || !preg_match("/[a-z]/i", $system)) + peh_error("System not found", 404); + +if (!isset($member) || trim($member) === "" || strlen($member) !== 5 || !preg_match("/[a-z]/i", $member)) + if ($member !== null && $member !== "null") peh_error("System member not found", 404); + +if (!isset($content)) + peh_error("No content", 400); + +if ($member !== null && $member !== "null") { + $file = $_SERVER['DOCUMENT_ROOT'] . "/includes/data/content/" . $member . "-private.html"; +} else { + $file = $_SERVER['DOCUMENT_ROOT'] . "/includes/data/content/" . $system . ".html"; +} + +if (trim($content) === "") { + if (file_exists($file)) { + unlink($file); + } + die(); +} + +file_put_contents($file, $content);
\ No newline at end of file diff --git a/pages/api/save.php b/pages/api/save.php new file mode 100644 index 0000000..2ea3663 --- /dev/null +++ b/pages/api/save.php @@ -0,0 +1,37 @@ +<?php + +require_once $_SERVER['DOCUMENT_ROOT'] . "/includes/session.inc"; global $isLoggedIn; global $isLowerLoggedIn; global $app; +if (!$isLoggedIn && !$isLowerLoggedIn) header("Location: /-/login") and die(); + +$request_raw = file_get_contents('php://input'); +$json_object = json_decode($request_raw, true); + +$system = $_GET['system'] ?? null; +$member = $_GET['member'] ?? null; +$content = $json_object['content'] ?? null; + +if (!isset($system) || trim($system) === "" || strlen($system) !== 5 || !preg_match("/[a-z]/i", $system)) + peh_error("System not found", 404); + +if (!isset($member) || trim($member) === "" || strlen($member) !== 5 || !preg_match("/[a-z]/i", $member)) + if ($member !== null && $member !== "null") peh_error("System member not found", 404); + +if ($isLowerLoggedIn && $system !== $app["other"]["id"]) die(); + +if (!isset($content)) + peh_error("No content", 400); + +if ($member !== null && $member !== "null") { + $file = $_SERVER['DOCUMENT_ROOT'] . "/includes/data/content/" . $member . ".html"; +} else { + $file = $_SERVER['DOCUMENT_ROOT'] . "/includes/data/" . $system . "/content.html"; +} + +if (trim($content) === "") { + if (file_exists($file)) { + unlink($file); + } + die(); +} + +file_put_contents($file, $content);
\ No newline at end of file diff --git a/pages/api/token.php b/pages/api/token.php new file mode 100644 index 0000000..99b9158 --- /dev/null +++ b/pages/api/token.php @@ -0,0 +1,7 @@ +<?php + +require_once $_SERVER['DOCUMENT_ROOT'] . "/includes/session.inc"; global $isLoggedIn; +if (!$isLoggedIn) header("Location: /-/login") and die(); + +header("Content-Type: text/plain"); +die($_COOKIE['PEH2_SESSION_TOKEN']);
\ No newline at end of file diff --git a/pages/api/wakeup-real.php b/pages/api/wakeup-real.php new file mode 100644 index 0000000..2267a4e --- /dev/null +++ b/pages/api/wakeup-real.php @@ -0,0 +1,28 @@ +<?php + +require_once $_SERVER['DOCUMENT_ROOT'] . "/includes/session.inc"; global $isLoggedIn; +if (!$isLoggedIn) header("Location: /-/login") and die(); +global $_PROFILE; + +$frontCloudburst = json_decode(file_get_contents($_SERVER['DOCUMENT_ROOT'] . "/includes/data/ynmuc/fronters.json"), true)["members"]; +$frontRaindrops = json_decode(file_get_contents($_SERVER['DOCUMENT_ROOT'] . "/includes/data/gdapd/fronters.json"), true)["members"]; + +$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"]; + +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" . + "Priority: high\r\n" . + "Tags: wakeup\r\n" . + "Authorization: Basic " . base64_encode($ntfy["user"] . ":" . $ntfy["password"]), + 'content' => "Hey, $pony wants you to wake up!" + ] +])); + +die();
\ No newline at end of file diff --git a/pages/api/wakeup.php b/pages/api/wakeup.php new file mode 100644 index 0000000..69b0a68 --- /dev/null +++ b/pages/api/wakeup.php @@ -0,0 +1,28 @@ +<?php + +require_once $_SERVER['DOCUMENT_ROOT'] . "/includes/session.inc"; global $isLoggedIn; +if (!$isLoggedIn) header("Location: /-/login") and die(); +global $_PROFILE; + +$frontCloudburst = json_decode(file_get_contents($_SERVER['DOCUMENT_ROOT'] . "/includes/data/ynmuc/fronters.json"), true)["members"]; +$frontRaindrops = json_decode(file_get_contents($_SERVER['DOCUMENT_ROOT'] . "/includes/data/gdapd/fronters.json"), true)["members"]; + +$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"]; + +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" . + "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]" + ] +])); + +die();
\ No newline at end of file diff --git a/pages/app.inc b/pages/app.inc deleted file mode 100644 index ceed71e..0000000 --- a/pages/app.inc +++ /dev/null @@ -1,3 +0,0 @@ -<?php - -header("Location: /app/") and die();
\ No newline at end of file diff --git a/pages/byfront.inc b/pages/byfront.inc index 00000b6..bcdc1e8 100644 --- a/pages/byfront.inc +++ b/pages/byfront.inc @@ -130,7 +130,7 @@ $travelling = json_decode(file_get_contents($_SERVER['DOCUMENT_ROOT'] . "/includ <?php if ($travelling[$member['id']]["travelling"]): ?> <span class="badge text-white bg-secondary rounded-pill">Travelling</span> <?php endif; ?> - <?php if ($member["_lastFronted"] < time() - (86400 * 30)): ?> + <?php if ($member["_lastFronted"] < time() - (86400 * 30) && !$member["_metadata"]["not_fronting"]): ?> <span class="badge text-white bg-danger rounded-pill">Must front</span> <?php endif; ?> </span> diff --git a/pages/dashboard.inc b/pages/dashboard.inc deleted file mode 100644 index 08e063b..0000000 --- a/pages/dashboard.inc +++ /dev/null @@ -1,231 +0,0 @@ -<?php - -require_once $_SERVER['DOCUMENT_ROOT'] . "/includes/init.inc"; global $title; global $isLoggedIn; global $lang; global $pages; global $pages; -require_once $_SERVER['DOCUMENT_ROOT'] . '/includes/header.inc'; global $_PROFILE; -use om\IcalParser; - -$poniesHavingSex = []; - -$actions = json_decode(file_get_contents($_SERVER['DOCUMENT_ROOT'] . "/includes/data/actions/actions.json"), true); - -foreach ($actions as $action) { - if ($action["type"] !== "sexual") continue; - - foreach ($action["ponies"] as $ponies) { - $id = implode("", $ponies["members"]); - - $member = getMemberWithoutSystem($ponies["members"][0]); - $otherMember = getMemberWithoutSystem($ponies["members"][1]); - - $parts = [ - $member["id"], - $otherMember["id"] - ]; - - asort($parts); - $poniesHavingSex[] = $parts[0]; - $poniesHavingSex[] = $parts[1]; - } -} - -$fronter = array_map(function ($i) { - return $i["id"]; -}, ($_PROFILE["login"] === "raindrops" ? json_decode(file_get_contents($_SERVER['DOCUMENT_ROOT'] . "/includes/data/gdapd/fronters.json"), true) : json_decode(file_get_contents($_SERVER['DOCUMENT_ROOT'] . "/includes/data/ynmuc/fronters.json"), true))["members"])[0] ?? null; - -$viewingPonyHasSex = in_array($fronter, $poniesHavingSex) || isset($_GET['toys']); - -?> - -<br> -<div class="container"> - <div id="page-content"> - <h3 id="date" style="text-align: center;margin-bottom:20px;">Date</h3> - <script> - function _Date() { - let d = new Date(); - let m = d.getMonth(); - let w = d.getDay(); - - switch (m) { - case 0: m = "Jan"; break; - case 1: m = "Feb"; break; - case 2: m = "Mar"; break; - case 3: m = "Apr"; break; - case 4: m = "May"; break; - case 5: m = "Jun"; break; - case 6: m = "Jul"; break; - case 7: m = "Aug"; break; - case 8: m = "Sep"; break; - case 9: m = "Oct"; break; - case 10: m = "Nov"; break; - case 11: m = "Dec"; break; - } - - switch (w) { - case 0: w = "Sun"; break; - case 1: w = "Mon"; break; - case 2: w = "Tue"; break; - case 3: w = "Wed"; break; - case 4: w = "Thu"; break; - case 5: w = "Fri"; break; - case 6: w = "Sat"; break; - } - - function fixed(number) { - if (number < 10) { - return "0" + number; - } else { - return number.toString(); - } - } - - document.getElementById("date").innerText = `${w} ${d.getDate()} ${m} ${d.getHours()}:${fixed(d.getMinutes())}`; - } - - setInterval(_Date); - </script> - - <hr> - <h4>Next fronters <span class="small"><a href="/-/fronting">(edit)</a></span></h4> - <?php - - $scheduleCloudburstToday = json_decode(file_get_contents($_SERVER['DOCUMENT_ROOT'] . "/includes/data/planner/ynmuc.json"), true)[date('Y-m-d')] ?? []; - $scheduleRaindropsToday = json_decode(file_get_contents($_SERVER['DOCUMENT_ROOT'] . "/includes/data/planner/gdapd.json"), true)[date('Y-m-d')] ?? []; - - $scheduleCloudburstTomorrow = json_decode(file_get_contents($_SERVER['DOCUMENT_ROOT'] . "/includes/data/planner/ynmuc.json"), true)[date('Y-m-d', time() + 86400)] ?? []; - $scheduleRaindropsTomorrow = json_decode(file_get_contents($_SERVER['DOCUMENT_ROOT'] . "/includes/data/planner/gdapd.json"), true)[date('Y-m-d', time() + 86400)] ?? []; - - $scheduleCloudburstNextday = json_decode(file_get_contents($_SERVER['DOCUMENT_ROOT'] . "/includes/data/planner/ynmuc.json"), true)[date('Y-m-d', time() + 172800)] ?? []; - $scheduleRaindropsNextday = json_decode(file_get_contents($_SERVER['DOCUMENT_ROOT'] . "/includes/data/planner/gdapd.json"), true)[date('Y-m-d', time() + 172800)] ?? []; - - $today1 = $_PROFILE["login"] === "raindrops" ? $scheduleRaindropsToday : $scheduleCloudburstToday; - $today2 = $_PROFILE["login"] === "raindrops" ? $scheduleCloudburstToday : $scheduleRaindropsToday; - $tomorrow1 = $_PROFILE["login"] === "raindrops" ? $scheduleRaindropsTomorrow : $scheduleCloudburstTomorrow; - $tomorrow2 = $_PROFILE["login"] === "raindrops" ? $scheduleCloudburstTomorrow : $scheduleRaindropsTomorrow; - $nextday1 = $_PROFILE["login"] === "raindrops" ? $scheduleRaindropsNextday : $scheduleCloudburstNextday; - $nextday2 = $_PROFILE["login"] === "raindrops" ? $scheduleCloudburstNextday : $scheduleRaindropsNextday; - - ?> - - <h5>Fronters today</h5> - <ul> - <?php foreach ($today1 as $index => $id): $member = getMemberWithoutSystem($id[0]); ?> - <li> - <?php if ($member["name"] === "fusion"): ?> - <img alt="" src="/assets/logo/logo.png" style="height: 24px; vertical-align: middle;"> <span style="vertical-align: middle;">Merged members</span> - <?php else: ?> - <img alt="" src="<?= getAsset($member['system'], $member["id"], "heads") ?>" style="height: 24px; vertical-align: middle;"> <b style="vertical-align: middle;"><?= getMiniName($member["display_name"] ?? $member["name"]) ?></b> - <?php endif; ?> - <?php if (isset($id[1])): $member2 = getMemberWithoutSystem($id[1]); ?> - <b style="vertical-align: middle;">and <img alt="" src="<?= getAsset($member['system'], $member2["id"], "heads") ?>" style="height: 24px; vertical-align: middle;"> <?= getMiniName($member2["display_name"] ?? $member2["name"]) ?></b> - <?php endif; ?> - <?php if (isset($today2[$index])): $member2 = getSystemMember($_PROFILE["login"] === "raindrops" ? "ynmuc" : "gdapd", $today2[$index][0]); ?><span style="vertical-align: middle;">with</span> <img alt="" src="<?= getAsset($member2['system'], $member2["id"], "heads") ?>" style="height: 24px; vertical-align: middle;"> <span style="vertical-align: middle;"><?= getMiniName($member2["display_name"] ?? $member2["name"]) ?><?php if (isset($today2[$index][1])): $member2 = getSystemMember($_PROFILE["login"] === "raindrops" ? "ynmuc" : "gdapd", $today2[$index][1]); ?> - and <img alt="" src="<?= getAsset($member['system'], $member2["id"], "heads") ?>" style="height: 24px; vertical-align: middle;"> <?= getMiniName($member2["display_name"] ?? $member2["name"]) ?> - <?php endif; ?></span><?php endif; ?> - </li> - <?php endforeach; ?> - </ul> - - <h5>Fronters tomorrow</h5> - <ul> - <?php foreach ($tomorrow1 as $index => $id): $member = getSystemMember($_PROFILE["login"] === "raindrops" ? "gdapd" : "ynmuc", $id[0]); ?> - <li> - <?php if ($member["name"] === "fusion"): ?> - <img alt="" src="/assets/logo/logo.png" style="height: 24px; vertical-align: middle;"> <span style="vertical-align: middle;">Merged members</span> - <?php else: ?> - <img alt="" src="<?= getAsset($member['system'], $member["id"], "heads") ?>" style="height: 24px; vertical-align: middle;"> <b style="vertical-align: middle;"><?= getMiniName($member["display_name"] ?? $member["name"]) ?></b> - <?php endif; ?> - <?php if (isset($id[1])): $member2 = getMemberWithoutSystem($id[1]); ?> - <b style="vertical-align: middle;">and <img alt="" src="<?= getAsset($member['system'], $member2["id"], "heads") ?>" style="height: 24px; vertical-align: middle;"> <?= getMiniName($member2["display_name"] ?? $member2["name"]) ?></b> - <?php endif; ?> - <?php if (isset($tomorrow2[$index])): $member2 = getSystemMember($_PROFILE["login"] === "raindrops" ? "ynmuc" : "gdapd", $tomorrow2[$index][0]); ?><span style="vertical-align: middle;">with</span> <img alt="" src="<?= getAsset($member2['system'], $member2["id"], "heads") ?>" style="height: 24px; vertical-align: middle;"> <span style="vertical-align: middle;"><?= getMiniName($member2["display_name"] ?? $member2["name"]) ?><?php if (isset($tomorrow2[$index][1])): $member2 = getSystemMember($_PROFILE["login"] === "raindrops" ? "ynmuc" : "gdapd", $tomorrow2[$index][1]); ?> - and <img alt="" src="<?= getAsset($member2['system'], $member2["id"], "heads") ?>" style="height: 24px; vertical-align: middle;"> <?= getMiniName($member2["display_name"] ?? $member2["name"]) ?> - <?php endif; ?></span><?php endif; ?> - </li> - <?php endforeach; ?> - </ul> - - <h5>Fronters on <?= date('l', time() + 172800) ?></h5> - <ul> - <?php foreach ($nextday1 as $index => $id): $member = getSystemMember($_PROFILE["login"] === "raindrops" ? "gdapd" : "ynmuc", $id[0]); ?> - <li> - <?php if ($member["name"] === "fusion"): ?> - <img alt="" src="/assets/logo/logo.png" style="height: 24px; vertical-align: middle;"> <span style="vertical-align: middle;">Merged members</span> - <?php else: ?> - <img alt="" src="<?= getAsset($member['system'], $member["id"], "heads") ?>" style="height: 24px; vertical-align: middle;"> <b style="vertical-align: middle;"><?= getMiniName($member["display_name"] ?? $member["name"]) ?></b> - <?php endif; ?> - <?php if (isset($id[1])): $member2 = getMemberWithoutSystem($id[1]); ?> - <b style="vertical-align: middle;">and <img alt="" src="<?= getAsset($member['system'], $member2["id"], "heads") ?>" style="height: 24px; vertical-align: middle;"> <?= getMiniName($member2["display_name"] ?? $member2["name"]) ?></b> - <?php endif; ?> - <?php if (isset($nextday2[$index])): $member2 = getSystemMember($_PROFILE["login"] === "raindrops" ? "ynmuc" : "gdapd", $nextday2[$index][0]); ?><span style="vertical-align: middle;">with</span> <img alt="" src="<?= getAsset($member2['system'], $member2["id"], "heads") ?>" style="height: 24px; vertical-align: middle;"> <span style="vertical-align: middle;"><?= getMiniName($member2["display_name"] ?? $member2["name"]) ?><?php if (isset($nextday2[$index][1])): $member2 = getSystemMember($_PROFILE["login"] === "raindrops" ? "ynmuc" : "gdapd", $nextday2[$index][1]); ?> - and <img alt="" src="<?= getAsset($member2['system'], $member2["id"], "heads") ?>" style="height: 24px; vertical-align: middle;"> <?= getMiniName($member2["display_name"] ?? $member2["name"]) ?> - <?php endif; ?></span><?php endif; ?> - </li> - <?php endforeach; ?> - </ul> - - <hr> - <h4>Next events</h4> - <?php - - $cal = new IcalParser(); - $results = $cal->parseFile($_SERVER['DOCUMENT_ROOT'] . "/includes/data/calendar/calendar.ics"); - $events = []; - - foreach ($cal->getEvents()->sorted() as $event) { - $events[] = [ - "id" => $event['UID'], - "date" => [ - "created" => $event['CREATED']->format('c'), - "modified" => $event['LAST-MODIFIED']->format('c'), - "start" => $event['DTSTART']->format('c'), - "end" => $event['DTEND']->format('c'), - "duration" => strtotime($event['DTEND']->format('c')) - strtotime($event['DTSTART']->format('c')), - "full_day" => strtotime($event['DTEND']->format('c')) - strtotime($event['DTSTART']->format('c')) >= 86400, - "days" => ( - strtotime($event['DTEND']->format('c')) - strtotime($event['DTSTART']->format('c')) >= 86400 ? - round((strtotime($event['DTEND']->format('c')) - strtotime($event['DTSTART']->format('c'))) / 86400) : - null - ) - ], - "name" => $event['SUMMARY'], - "description" => $event['DESCRIPTION'] ?? "", - ]; - } - - $events = array_values(array_filter($events, function ($i) { - return ( - strtotime($i["date"]["end"]) > time() && - strtotime($i["date"]["start"]) < time() + 2629800 - ); - })); - - ?> - <ul> - <?php foreach ($events as $event): ?> - <li> - <?php if ($event["date"]["full_day"]): ?> - <b> - <?php if (strtotime($event["date"]["start"]) < time()): ?> - Started <?= timeAgo($event["date"]["start"]) ?>, ends <?= timeIn($event["date"]["end"]) ?> - <?php else: ?> - <?= ucfirst(relativeDate($event["date"]["start"], false)) ?> - <?php endif; ?> - · - </b> - <?php else: ?> - <b> - <?= ucfirst(relativeDate($event["date"]["start"])) ?> - · - </b> - <?php endif; ?> - for <?= duration($event["date"]["duration"]) ?> - · - <?= $event["name"] ?> - </li> - <?php endforeach; ?> - </ul> - </div> -</div> - -<?php require_once $_SERVER['DOCUMENT_ROOT'] . '/includes/footer.inc'; ?> diff --git a/pages/demo.inc b/pages/demo.inc deleted file mode 100644 index 47e0775..0000000 --- a/pages/demo.inc +++ /dev/null @@ -1,4 +0,0 @@ -<?php - -header("Location: /"); -die();
\ No newline at end of file diff --git a/pages/disclaimers.inc b/pages/disclaimers.inc deleted file mode 100644 index 7f15bcc..0000000 --- a/pages/disclaimers.inc +++ /dev/null @@ -1,15 +0,0 @@ -<?php - -require_once $_SERVER['DOCUMENT_ROOT'] . "/includes/init.inc"; global $title; global $isLoggedIn; global $lang; global $pages; -require_once $_SERVER['DOCUMENT_ROOT'] . '/includes/header.inc'; - -?> - -<br> -<div class="container"> - <div id="page-content"> - <?= file_exists($_SERVER['DOCUMENT_ROOT'] . "/content/disclaimers.$lang[_name].html") ? file_get_contents($_SERVER['DOCUMENT_ROOT'] . "/content/disclaimers.$lang[_name].html") : file_get_contents($_SERVER['DOCUMENT_ROOT'] . "/content/disclaimers.html") ?> - </div> -</div> - -<?php require_once $_SERVER['DOCUMENT_ROOT'] . '/includes/footer.inc'; ?> diff --git a/pages/docs.inc b/pages/docs.inc index 5e0ac65..3b212df 100644 --- a/pages/docs.inc +++ b/pages/docs.inc @@ -11,7 +11,7 @@ if ($select === "add") { file_put_contents($_SERVER['DOCUMENT_ROOT'] . "/includes/data/docs/" . $id . ".json", json_encode([ "name" => "Untitled document ($id)", "category" => null, - "contents" => "<div class='alert alert-primary'>This is a new document you just created.</div>", + "contents" => "This is a new document you just created.", "last" => [ "author" => $_PROFILE["login"], "date" => time() diff --git a/pages/edit-private.inc b/pages/edit-private.inc index 9564f7a..4d89b5c 100644 --- a/pages/edit-private.inc +++ b/pages/edit-private.inc @@ -1,21 +1,8 @@ <?php -function getSubsystemByID(string $id) { - global $subsystems; - $subsystem = null; - - foreach ($subsystems as $ss) { - if ($ss["source"] === $id) { - $subsystem = $ss; - } - } - - return $subsystem; -} - require_once $_SERVER['DOCUMENT_ROOT'] . "/includes/init.inc"; global $title; global $isLoggedIn; global $lang; global $pages; -if (!isset($_GET['_']) || trim($_GET['_']) === "") header("Location: /?error=Invalid request") and die(); +if (!isset($_GET['_']) || trim($_GET['_']) === "") peh_error("Invalid request", 400); $parts = explode("/", $_GET['_']); array_shift($parts); @@ -23,16 +10,13 @@ array_shift($parts); $system = $parts[0]; $member = ($parts[1] ?? null) === "" ? null : $parts[1]; -if ($system !== "cloudburst" && $system !== "raindrops") header("Location: /?error=Invalid system name: " . $system) and die(); +if ($system !== "cloudburst" && $system !== "raindrops") peh_error("Invalid system name: " . $system, 400); $systemCommonName = $system === "cloudburst" ? "Cloudburst System" : "Raindrops System"; $systemID = $system === "cloudburst" ? "ynmuc" : "gdapd"; -$subsystems = json_decode(file_get_contents($_SERVER['DOCUMENT_ROOT'] . "/includes/data/subsystems/$systemID.json"), true) ?? []; - if ($member === null) { - header("Location: /?error=Unsupported target: system") and die(); + peh_error("Unsupported target: system", 500); } else { - $isSubsystem = false; $members = json_decode(file_get_contents($_SERVER['DOCUMENT_ROOT'] . "/includes/data/" . $systemID . "/members.json"), true); $memberData = null; $memberCommonName = null; @@ -47,19 +31,7 @@ if ($member === null) { } if ($memberData === null) { - if (in_array($member, array_map(function ($i) { - return $i["source"]; - }, $subsystems))) { - $isSubsystem = true; - $subsystemID = $member; - $subsystem = getSubsystemByID($subsystemID); - $subsystemData = json_decode(file_get_contents($_SERVER['DOCUMENT_ROOT'] . "/includes/data/subsystems/$systemID-$subsystem[source].json"), true); - $subsystemCommonName = $subsystemData["name"] ?? $subsystemID; - - require_once $_SERVER['DOCUMENT_ROOT'] . '/includes/subsysedit.inc'; - } else { - header("Location: /?error=System member or subsystem not found") and die(); - } + peh_error("System member not found", 404); } require_once $_SERVER['DOCUMENT_ROOT'] . '/includes/edit-private.inc'; diff --git a/pages/edit.inc b/pages/edit.inc index afaddd3..e074087 100644 --- a/pages/edit.inc +++ b/pages/edit.inc @@ -1,21 +1,8 @@ <?php -function getSubsystemByID(string $id) { - global $subsystems; - $subsystem = null; - - foreach ($subsystems as $ss) { - if ($ss["source"] === $id) { - $subsystem = $ss; - } - } - - return $subsystem; -} - require_once $_SERVER['DOCUMENT_ROOT'] . "/includes/init.inc"; global $isLowerLoggedIn; global $title; global $isLoggedIn; global $lang; global $pages; global $app; -if (!isset($_GET['_']) || trim($_GET['_']) === "") header("Location: /?error=Invalid request") and die(); +if (!isset($_GET['_']) || trim($_GET['_']) === "") peh_error("Invalid request", 400); $parts = explode("/", $_GET['_']); array_shift($parts); @@ -23,12 +10,10 @@ array_shift($parts); $system = $parts[0]; $member = !isset($parts[1]) || $parts[1] === "" ? null : $parts[1]; -if ($system !== "cloudburst" && $system !== "raindrops" && $system !== $app["other"]["slug"]) header("Location: /?error=Invalid system name: " . $system) and die(); +if ($system !== "cloudburst" && $system !== "raindrops" && $system !== $app["other"]["slug"]) peh_error("Invalid system name: " . $system, 400); $systemCommonName = $system === "cloudburst" ? "Cloudburst System" : ($system === "raindrops" ? "Raindrops System" : $app["other"]["name"]); $systemID = $system === "cloudburst" ? "ynmuc" : ($system === "raindrops" ? "gdapd" : $app["other"]["id"]); -$subsystems = json_decode(file_get_contents($_SERVER['DOCUMENT_ROOT'] . "/includes/data/subsystems/$systemID.json"), true) ?? []; - if ($isLowerLoggedIn && $systemID !== $app["other"]["id"]) { header("Location: /") and die(); } @@ -36,7 +21,6 @@ if ($isLowerLoggedIn && $systemID !== $app["other"]["id"]) { if ($member === null) { require_once $_SERVER['DOCUMENT_ROOT'] . '/includes/sysedit.inc'; } else { - $isSubsystem = false; $members = json_decode(file_get_contents($_SERVER['DOCUMENT_ROOT'] . "/includes/data/" . $systemID . "/members.json"), true); $memberData = null; $memberCommonName = null; @@ -51,19 +35,7 @@ if ($member === null) { } if ($memberData === null) { - if (in_array($member, array_map(function ($i) { - return $i["source"]; - }, $subsystems))) { - $isSubsystem = true; - $subsystemID = $member; - $subsystem = getSubsystemByID($subsystemID); - $subsystemData = json_decode(file_get_contents($_SERVER['DOCUMENT_ROOT'] . "/includes/data/subsystems/$systemID-$subsystem[source].json"), true); - $subsystemCommonName = $subsystemData["name"] ?? $subsystemID; - - require_once $_SERVER['DOCUMENT_ROOT'] . '/includes/subsysedit.inc'; - } else { - header("Location: /?error=System member or subsystem not found") and die(); - } + peh_error("System member not found", 404); } require_once $_SERVER['DOCUMENT_ROOT'] . '/includes/edit.inc'; diff --git a/pages/front.inc b/pages/front.inc index cd4f952..73f193c 100644 --- a/pages/front.inc +++ b/pages/front.inc @@ -8,7 +8,7 @@ if (isset($parts[2])) { } elseif ($parts[2] === "raindrops") { $fronters = json_decode(file_get_contents($_SERVER['DOCUMENT_ROOT'] . "/includes/data/gdapd/fronters.json"), true); } else { - header("Location: /?error=Invalid argument; got " . $parts[2]); + peh_error("Invalid argument; got " . strip_tags($parts[2]), 400); die(); } @@ -23,6 +23,6 @@ if (isset($parts[2])) { } } } else { - header("Location: /?error=Missing operand"); + peh_error("Missing operand", 400); die(); }
\ No newline at end of file diff --git a/pages/government.inc b/pages/government.inc deleted file mode 100644 index 08fb63c..0000000 --- a/pages/government.inc +++ /dev/null @@ -1,142 +0,0 @@ -<?php - -require_once $_SERVER['DOCUMENT_ROOT'] . "/includes/init.inc"; global $title; global $isLoggedIn; global $lang; global $pages; -require_once $_SERVER['DOCUMENT_ROOT'] . '/includes/header.inc'; - -?> - -<br> -<div class="container"> - <div> - <h2><?= $pages["government"]["name"][$lang["_name"]] ?></h2> - <?php - - $members = scoreOrderGlobal(); - $zzise = getMemberWithoutSystem("zzise"); - $auvwc = getMemberWithoutSystem("auvwc"); - $qbzxm = getMemberWithoutSystem("qbzxm"); - $vncoa = getMemberWithoutSystem("vncoa"); - $qraku = getMemberWithoutSystem("qraku"); - $ghrby = getMemberWithoutSystem("ghrby"); - - ?> - - <div title="<b><?= $lang["government"]["council"][0] ?></b><br><?= $lang["government"]["council"][1] ?>" data-bs-toggle="tooltip" data-bs-html="true" style="text-align: center;border-radius:10px;background:#222; padding: 10px; margin-top: 15px;"> - <b><?= $lang["government"]["council"][0] ?></b> - <div style="margin-top: 10px; display: flex; justify-content: center;"> - <a class="gov-link" href="/<?= $ghrby["name"] ?>" style="color: white !important; text-decoration: none;"><div style="margin-right: 10px;"> - <img style="width:48px; height: 48px; border-radius: 999px; background-color: #333;" src="<?= getAsset("ynmuc", "ghrby") ?>"><br> - <?= $ghrby["display_name"] ?> - </div></a> - <a class="gov-link" href="/<?= $auvwc["name"] ?>" style="color: white !important; text-decoration: none;"><div style=" margin-right: auto;"> - <img style="width:48px; height: 48px; border-radius: 999px; background-color: #333;" src="<?= getAsset("gdapd", "auvwc") ?>"><br> - <?= $auvwc["display_name"] ?> - </div></a> - </div> - </div> - <div style="display: grid; grid-template-columns: 1fr 1px 1fr; grid-column-gap: 15px; margin-top: 15px;"> - <div> - <p style="text-align: center;"> - <img style="width: 24px; vertical-align: middle;" src="/assets/uploads/cloudburst.png"> - <b style="vertical-align: middle;">Cloudburst System</b> - </p> - <div style="display: grid; grid-template-columns: 1.5fr 1fr; grid-column-gap: 15px;"> - <div title="<b><?= $lang["government"]["head"][1] ?></b><br><?= $lang["government"]["head"][2] ?>" data-bs-toggle="tooltip" data-bs-html="true" style="text-align: center;border-radius:10px;background:#023100; padding: 10px;"> - <b><span class="list-separator-mobile"><?= $lang["government"]["head"][0] ?></span><span class="list-separator-desktop"><?= $lang["government"]["head"][1] ?></span></b> - <div style="margin-top: 10px; display: flex; justify-content: center;"> - <a class="gov-link" href="/<?= $ghrby["name"] ?>" style="color: white !important; text-decoration: none;"><div> - <img style="width:48px; height: 48px; border-radius: 999px; background-color: #333;" src="<?= getAsset("ynmuc", "ghrby") ?>"> - <span class="list-separator-desktop"><br><?= $ghrby["display_name"] ?></span> - </div></a> - </div> - </div> - <div title="<b><?= $lang["government"]["protector1"][1] ?></b><br><?= $lang["government"]["protector1"][2] ?>" data-bs-toggle="tooltip" data-bs-html="true" style="text-align: center;border-radius:10px;background:#002d31; padding: 10px;"> - <b><span class="list-separator-mobile"><?= $lang["government"]["protector1"][0] ?></span><span class="list-separator-desktop"><?= $lang["government"]["protector1"][1] ?></span></b> - <div style="margin-top: 10px; display: flex; justify-content: center;"> - <a class="gov-link" href="/<?= $zzise["name"] ?>" style="color: white !important; text-decoration: none;"><div> - <img style="width:48px; height: 48px; border-radius: 999px; background-color: #333;" src="<?= getAsset("ynmuc", "zzise") ?>"> - <span class="list-separator-desktop"><br><?= $zzise["display_name"] ?></span> - </div></a> - </div> - </div> - </div> - </div> - <div style="background:rgba(255, 255, 255, .2);"></div> - <div> - <p style="text-align: center;"> - <img style="width: 24px; vertical-align: middle;" src="/assets/uploads/raindrops.png"> - <b style="vertical-align: middle;">Raindrops System</b> - </p> - <div style="display: grid; grid-template-columns: 1.5fr 1fr; grid-column-gap: 15px;"> - <div title="<b><?= $lang["government"]["head"][1] ?></b><br><?= $lang["government"]["head"][2] ?>" data-bs-toggle="tooltip" data-bs-html="true" style="text-align: center;border-radius:10px;background:#023100; padding: 10px;"> - <b><span class="list-separator-mobile"><?= $lang["government"]["head"][0] ?></span><span class="list-separator-desktop"><?= $lang["government"]["head"][1] ?></span></b> - <div style="margin-top: 10px; display: flex; justify-content: center;"> - <a class="gov-link" href="/<?= $auvwc["name"] ?>" style="color: white !important; text-decoration: none;"><div> - <img style="width:48px; height: 48px; border-radius: 999px; background-color: #333;" src="<?= getAsset("gdapd", "auvwc") ?>"> - <span class="list-separator-desktop"><br><?= $auvwc["display_name"] ?></span> - </div></a> - </div> - </div> - <div title="<b><?= $lang["government"]["protector1"][1] ?></b><br><?= $lang["government"]["protector1"][2] ?>" data-bs-toggle="tooltip" data-bs-html="true" style="text-align: center;border-radius:10px;background:#002d31; padding: 10px;"> - <b><span class="list-separator-mobile"><?= $lang["government"]["protector1"][0] ?></span><span class="list-separator-desktop"><?= $lang["government"]["protector1"][1] ?></span></b> - <div style="margin-top: 10px; display: flex; justify-content: center;"> - <a class="gov-link" href="/<?= $qbzxm["name"] ?>" style="color: white !important; text-decoration: none;"><div> - <img style="width:48px; height: 48px; border-radius: 999px; background-color: #333;" src="<?= getAsset("gdapd", "qbzxm") ?>"> - <span class="list-separator-desktop"><br><?= $qbzxm["display_name"] ?></span> - </div></a> - </div> - </div> - </div> - </div> - </div> - <div style="display: grid; grid-template-columns: 1fr 1px 1fr; grid-column-gap: 15px;"> - <div title="<b><?= $lang["government"]["protectors"][0] ?></b><br><?= $lang["government"]["protectors"][1] ?>" data-bs-toggle="tooltip" data-bs-html="true" style="margin-top: 15px;"> - <div style="text-align: center;border-radius:10px;background:#311a00; padding: 10px;"> - <b><?= $lang["government"]["protectors"][0] ?></b> - <div style="margin-top: 10px; display: flex; justify-content: center;"> - <a class="gov-link" href="/<?= $zzise["name"] ?>" style="color: white !important; text-decoration: none;"><div style="margin-right: 20px;"> - <img style="width:48px; height: 48px; border-radius: 999px; background-color: #333;" src="<?= getAsset("ynmuc", "zzise") ?>"> - <span class="list-separator-desktop"><br><?= $zzise["display_name"] ?></span> - </div></a> - <a class="gov-link" href="/<?= $vncoa["name"] ?>" style="color: white !important; text-decoration: none;"><div style="margin-right: 20px;"> - <img style="width:48px; height: 48px; border-radius: 999px; background-color: #333;" src="<?= getAsset("ynmuc", "vncoa") ?>"> - <span class="list-separator-desktop"><br><?= $vncoa["display_name"] ?></span> - </div></a> - </div> - </div> - </div> - <div style="background:rgba(255, 255, 255, .2);"></div> - <div title="<b><?= $lang["government"]["protectors"][0] ?></b><br><?= $lang["government"]["protectors"][1] ?>" data-bs-toggle="tooltip" data-bs-html="true" style="margin-top: 15px;"> - <div style="text-align: center;border-radius:10px;background:#311a00; padding: 10px;"> - <b><?= $lang["government"]["protectors"][0] ?></b> - <div style="margin-top: 10px; display: flex; justify-content: center;"> - <a class="gov-link" href="/<?= $qbzxm["name"] ?>" style="color: white !important; text-decoration: none;"><div style="margin-right: 20px;"> - <img style="width:48px; height: 48px; border-radius: 999px; background-color: #333;" src="<?= getAsset("gdapd", "qbzxm") ?>"> - <span class="list-separator-desktop"><br><?= $qbzxm["display_name"] ?></span> - </div></a> - <a class="gov-link" href="/<?= $qraku["name"] ?>" style="color: white !important; text-decoration: none;"><div style="margin-right: 20px;"> - <img style="width:48px; height: 48px; border-radius: 999px; background-color: #333;" src="<?= getAsset("gdapd", "qraku") ?>"> - <span class="list-separator-desktop"><br><?= $qraku["display_name"] ?></span> - </div></a> - </div> - </div> - </div> - </div> - </div> -</div> - -<style> - .gov-link:hover { - opacity: .75; - } - - .gov-link:active { - opacity: .5; - } - - .gov-link:focus { - opacity: .5; - } -</style> - -<?php require_once $_SERVER['DOCUMENT_ROOT'] . '/includes/footer.inc'; ?> diff --git a/pages/home.inc b/pages/home.inc index 4dd838e..d206100 100644 --- a/pages/home.inc +++ b/pages/home.inc @@ -1,11 +1,17 @@ -<?php if (isset($_GET['error'])) header("HTTP/1.1 404 Not Found"); require_once $_SERVER['DOCUMENT_ROOT'] . '/includes/header.inc'; global $readOnly; global $isNormallyLoggedIn; global $_PROFILE; global $lang; global $pages; global $isLowerLoggedIn; global $app; global $isLoggedIn; ?> +<?php + +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/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['error'])): ?> + <?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($_GET['error']) ?> + <b><?= $lang["home"]["error"] ?> </b><?= strip_tags(base64_decode($_GET['em'])) ?> </div> <?php endif; ?> @@ -17,16 +23,16 @@ <?php global $travelling; $byColor = getMembersByColor($_SERVER['HTTP_HOST'] === "fr.equestria.horse"); ?> <div style="text-align: center;"> - <img alt="" src="/assets/logo/newlogo<?php if ($_SERVER['HTTP_HOST'] === "fr.equestria.horse"): ?>2<?php endif; ?>.png" style="width:128px;"> - <p style="z-index:999;position:relative;background:black;margin: 20px -10px 0 -20px;padding-right:30px;height:32px;text-align: center;display:grid;grid-template-columns: repeat(<?= count($byColor) ?>, 1fr);"> + <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);"> <?php foreach ($byColor as $member): ?><a data-bs-html="true" class="rainbow-item tooltip-nohelp" title="<b><?= $member["display_name"] ?? $member["name"] ?></b><br><?= ($travelling[$member['id']]["travelling"] ? $member["_system"] === "ynmuc" : $member["_system"] === "gdapd") ? "Raindrops System" : ($member["_system"] === "ynmuc" ? "Cloudburst System" : $app["other"]["name"]) ?>" data-bs-toggle="tooltip" style="overflow: hidden;" href="/<?= $member["name"] ?>"><img src="<?= getAsset($member["_system"], $member["id"], "heads") ?>" style="height:32px;position:absolute;z-index:99;"></a><?php endforeach; ?> </p> <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);"> <?php foreach ($byColor as $member): ?><div> - <span style="display: inline-block;background: transparent;position:absolute;width: 20px;height: 15px;margin-top: 17px;box-shadow: 0 6px 20px 7px #<?= $member["color"] ?>;z-index: 9;margin-left: 8px;opacity: .75;"></span> + <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> - <div style="padding:5px 10px;background:#222;border-bottom-left-radius: 10px;border-bottom-right-radius: 10px;"> + <div style="padding:5px 10px;background:#3332328a;border-bottom-left-radius: 10px;border-bottom-right-radius: 10px;position:relative;z-index: 99999;backdrop-filter: blur(30px);"> <h2 style="margin-top: 20px;">Cold Haze</h2> <?php if ($_SERVER['HTTP_HOST'] === "fr.equestria.horse"): ?> <p><?= count($byColor) ?> poneys dans une tête</p> @@ -55,7 +61,7 @@ <div id="homepage-desktop" style="margin-top:10px;"> - <?php if ($_SERVER['HTTP_HOST'] !== "fr.equestria.horse") cloudburst(false); ?> + <?php cloudburst(false); ?> <?php raindrops(false); ?> <?php if ($isLoggedIn || $isLowerLoggedIn) other(false); ?> diff --git a/pages/login.inc b/pages/login.inc index cfe363c..8d71574 100644 --- a/pages/login.inc +++ b/pages/login.inc @@ -16,7 +16,7 @@ require_once $_SERVER['DOCUMENT_ROOT'] . '/includes/header.inc'; global $readOnl <?php else: ?> <?php global $isLoggedIn; if ($isLoggedIn): ?> <div class="alert alert-warning"> - <b>You are already logged in.</b> If you want to login to a different account or using a different authentication method, you may do so now. + <b>You are already logged in.</b> If you want to log into a different account or using a different authentication method, you may do so now. </div> <?php else: ?> <p><?= $lang["login"]["select"] ?> Cold Haze.</p> @@ -24,10 +24,9 @@ require_once $_SERVER['DOCUMENT_ROOT'] . '/includes/header.inc'; global $readOnl <div class="col-md-6"> <div class="card" style="margin-bottom:10px;text-align: center;"> <div class="card-body"> - <!--<img src="https://git.equestria.dev/equestria.dev/design/raw/branch/mane/logo/dark/banner.svg" style="height:48px;" alt="">--> <h4 class="card-title" style="margin-top:15px;"><?= $lang["login"]["private"][0] ?></h4> <p><?= $lang["login"]["private"][1] ?></p> - <a href="/Authentication/Start" class="btn btn-primary"><?= $lang["login"]["private"][2] ?></a> + <a href="/auth/init" class="btn btn-primary"><?= $lang["login"]["private"][2] ?></a> </div> </div> </div> diff --git a/pages/metadata.inc b/pages/metadata.inc index 0a987f3..db5589d 100644 --- a/pages/metadata.inc +++ b/pages/metadata.inc @@ -1,23 +1,10 @@ <?php -function getSubsystemByID(string $id) { - global $subsystems; - $subsystem = null; - - foreach ($subsystems as $ss) { - if ($ss["source"] === $id) { - $subsystem = $ss; - } - } - - return $subsystem; -} - require_once $_SERVER['DOCUMENT_ROOT'] . "/includes/init.inc"; global $title; global $isLowerLoggedIn; global $isLoggedIn; global $lang; global $pages; global $app; require_once $_SERVER['DOCUMENT_ROOT'] . "/includes/functions.inc"; require_once $_SERVER['DOCUMENT_ROOT'] . "/includes/bitset.inc"; -if (!isset($_GET['_']) || trim($_GET['_']) === "") header("Location: /?error=Invalid request") and die(); +if (!isset($_GET['_']) || trim($_GET['_']) === "") peh_error("Invalid request", 400); $parts = explode("/", $_GET['_']); array_shift($parts); @@ -25,12 +12,10 @@ array_shift($parts); $system = $parts[0]; $member = !isset($parts[1]) || $parts[1] === "" ? null : $parts[1]; -if ($system !== "cloudburst" && $system !== "raindrops" && $system !== $app["other"]["slug"]) header("Location: /?error=Invalid system name: " . $system) and die(); +if ($system !== "cloudburst" && $system !== "raindrops" && $system !== $app["other"]["slug"]) peh_error("Invalid system name: " . $system, 400); $systemCommonName = $system === "cloudburst" ? "Cloudburst System" : ($system === $app["other"]["slug"] ? $app["other"]["name"] : "Raindrops System"); $systemID = $system === "cloudburst" ? "ynmuc" : ($system === $app["other"]["slug"] ? $app["other"]["id"] : "gdapd"); -$subsystems = json_decode(file_get_contents($_SERVER['DOCUMENT_ROOT'] . "/includes/data/subsystems/$systemID.json"), true) ?? []; - if ($isLowerLoggedIn && $systemID !== $app["other"]["id"]) { header("Location: /"); die(); @@ -40,7 +25,6 @@ if ($member === null) { header("Location: /"); die(); } else { - $isSubsystem = false; $members = json_decode(file_get_contents($_SERVER['DOCUMENT_ROOT'] . "/includes/data/" . $systemID . "/members.json"), true); $memberData = null; $memberCommonName = null; @@ -55,7 +39,7 @@ if ($member === null) { } if ($memberData === null) { - header("Location: /?error=Not found") and die(); + peh_error("Not found", 404); } if (isset($_GET["submit"])) { @@ -111,27 +95,29 @@ if ($member === null) { $toUpdate["interest"] = strip_tags($_GET["interest"]); } + $regex = "/^(ynmuc|gdapd|" . $app["other"]["id"] . ")\/[a-z]{5}$/m"; + if (isset($_GET["marefriends"])) { - $toUpdate["marefriends"] = array_values(array_filter(array_map(function ($i) { return trim($i); }, explode(",", $_GET["marefriends"])), function ($i) { - return !!preg_match("/^(ynmuc|gdapd)\/[a-z]{5}$/m", $i); + $toUpdate["marefriends"] = array_values(array_filter(array_map(function ($i) { return trim($i); }, explode(",", $_GET["marefriends"])), function ($i) use ($regex) { + return !!preg_match($regex, $i); })); } if (isset($_GET["sexfriends"])) { - $toUpdate["sexfriends"] = array_values(array_filter(array_map(function ($i) { return trim($i); }, explode(",", $_GET["sexfriends"])), function ($i) { - return !!preg_match("/^(ynmuc|gdapd)\/[a-z]{5}$/m", $i); + $toUpdate["sexfriends"] = array_values(array_filter(array_map(function ($i) { return trim($i); }, explode(",", $_GET["sexfriends"])), function ($i) use ($regex) { + return !!preg_match($regex, $i); })); } if (isset($_GET["sisters"])) { - $toUpdate["sisters"] = array_values(array_filter(array_map(function ($i) { return trim($i); }, explode(",", $_GET["sisters"])), function ($i) { - return !!preg_match("/^(ynmuc|gdapd)\/[a-z]{5}$/m", $i); + $toUpdate["sisters"] = array_values(array_filter(array_map(function ($i) { return trim($i); }, explode(",", $_GET["sisters"])), function ($i) use ($regex) { + return !!preg_match($regex, $i); })); } if (isset($_GET["caretakers"])) { - $toUpdate["caretakers"] = array_values(array_filter(array_map(function ($i) { return trim($i); }, explode(",", $_GET["caretakers"])), function ($i) { - return !!preg_match("/^(ynmuc|gdapd)\/[a-z]{5}$/m", $i); + $toUpdate["caretakers"] = array_values(array_filter(array_map(function ($i) { return trim($i); }, explode(",", $_GET["caretakers"])), function ($i) use ($regex) { + return !!preg_match($regex, $i); })); } diff --git a/pages/nicknames.inc b/pages/nicknames.inc deleted file mode 100644 index 2799703..0000000 --- a/pages/nicknames.inc +++ /dev/null @@ -1,115 +0,0 @@ -<?php - -require_once $_SERVER['DOCUMENT_ROOT'] . "/includes/init.inc"; global $title; global $isLoggedIn; global $lang; global $pages; -require_once $_SERVER['DOCUMENT_ROOT'] . '/includes/header.inc'; - -$members = scoreOrderGlobal(); -$relations = []; - -foreach ($members as $member) { - foreach ([ - ...array_map(function ($i) { - $r = [ - "name" => $i - ]; - $r["type"] = "marefriends"; - return $r; - }, $member["_metadata"]["marefriends"] ?? []), - ...array_map(function ($i) { - $r = [ - "name" => $i - ]; - $r["type"] = "sisters"; - return $r; - }, $member["_metadata"]["sisters"] ?? []), - ...array_map(function ($i) { - $r = [ - "name" => $i - ]; - $r["type"] = "caretaking"; - return $r; - }, $member["_metadata"]["caretakers"] ?? []) - ] as $rel) { - $id = $rel["name"]; - $otherMember = getSystemMember(explode("/", $id)[0], explode("/", $id)[1]); - - $parts = [ - $member["id"], - $otherMember["id"] - ]; - - asort($parts); - - $relations[implode("-", $parts)] = [ - "id" => implode("", $parts), - "name" => getMiniName($member["display_name"] ?? $member["name"]) . " and " . getMiniName($otherMember["display_name"] ?? $otherMember["name"]), - "type" => $rel["type"], - "images" => [ - getAsset($member['system'], $member["id"], "heads"), - getAsset($otherMember['system'], $otherMember["id"], "heads") - ] - ]; - } -} - -$nicknames = json_decode(file_get_contents($_SERVER['DOCUMENT_ROOT'] . "/includes/data/nicknames/nicknames.json"), true); - -?> - -<br> -<div class="container"> - <div id="page-content"> - <h2>Relations nicknames</h2> - <?php foreach ($relations as $relation): ?> - <div class="relation" style="background-color:rgba(255, 255, 255, .1);margin-bottom:10px;padding:10px;border-radius:10px;display:grid;grid-template-columns: 1fr 3fr;"> - <a class="relation-intro" title="<?= $relation["id"] ?>" data-bs-toggle="tooltip" style="background-color:rgba(255, 255, 255, .05);border-right:1px solid rgba(255, 255, 255, .1);margin:-10px;padding:10px;border-top-left-radius:10px;border-bottom-left-radius:10px;color: white;text-decoration: none;"> - <span style="vertical-align: middle;"><img src="<?= $relation["images"][0] ?>" style="width:24px;"><img src="<?= $relation["images"][1] ?>" style="width:24px;"></span> <span style="vertical-align: middle;"><?= $relation["name"] ?></span> - </a> - <div class="relation-item relation-item-marefriends" style="text-align:left;margin-left:10px;padding:0 20px;"> - <?php if (isset($nicknames[$relation["id"]])): ?> - "<?= implode('", "', $nicknames[$relation["id"]]) ?>" - <?php else: ?> - <span class="text-muted">No nickname for this relation</span> - <?php endif; ?> - </div> - </div> - <?php endforeach; ?> - </div> -</div> - -<style> - .relation-intro { - opacity: 1 !important; - } - - @media (max-width: 991px) { - .relation { - grid-template-columns: 1fr !important; - } - - .relation-intro { - text-align: center; - border-bottom-left-radius: 0 !important; - border-top-right-radius: 10px; - border-right: none !important; - border-bottom: 1px solid rgba(255, 255, 255, .1); - } - - .relation-item-marefriends { - margin-top: 20px !important; - text-align: center !important; - } - - .relation-item { - margin-top: 10px; - margin-left: 0 !important; - padding: 10px 0 !important; - } - } - - .relation-item { - text-align: center; - } -</style> - -<?php require_once $_SERVER['DOCUMENT_ROOT'] . '/includes/footer.inc'; ?> diff --git a/pages/page.inc b/pages/page.inc index 3bdeb2e..7fe039c 100644 --- a/pages/page.inc +++ b/pages/page.inc @@ -5,7 +5,7 @@ global $lang; global $pages; global $isLoggedIn; global $isLowerLoggedIn; $app = 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); -if (!isset($_GET['_']) || trim($_GET['_']) === "") header("Location: /?error=Invalid request") and die(); +if (!isset($_GET['_']) || trim($_GET['_']) === "") peh_error("Invalid request", 400); $parts = explode("/", $_GET['_']); @@ -42,7 +42,7 @@ if (($parts[0] !== "cloudburst" && $parts[0] !== "raindrops" && $parts[0] !== $a $system = $parts[0]; $member = (isset($parts[1]) ? $parts[1] : null) === "" ? null : (isset($parts[1]) ? $parts[1] : null); -if ($system !== "cloudburst" && $system !== "raindrops" && ($system !== $app["other"]["slug"] && !$isLowerLoggedIn && !$isLoggedIn)) header("Location: /?error=" . $lang["page"]["system"]) and die(); +if ($system !== "cloudburst" && $system !== "raindrops" && ($system !== $app["other"]["slug"] && !$isLowerLoggedIn && !$isLoggedIn)) peh_error("System not found", 404); $systemCommonName = $system === "cloudburst" ? "Cloudburst System" : ($system === $app["other"]["slug"] && ($isLoggedIn || $isLowerLoggedIn) ? $app["other"]["name"] : "Raindrops System"); $systemID = $system === "cloudburst" ? "ynmuc" : ($system === $app["other"]["slug"] && ($isLoggedIn || $isLowerLoggedIn) ? $app["other"]["id"] : "gdapd"); @@ -58,7 +58,7 @@ if ($member === null) { $pageFile = $_SERVER['DOCUMENT_ROOT'] . '/includes/system/' . $parts[2] . '.inc'; require_once $_SERVER['DOCUMENT_ROOT'] . '/includes/system/' . $parts[2] . '.inc'; } else { - header("Location: /?error=" . $lang["page"]["system"] . " " . $parts[2]) and die(); + peh_error("System page not found: " . strip_tags($parts[2]), 404); } } else { $memberFoundInAnotherSystem = false; @@ -105,7 +105,7 @@ if ($member === null) { $pageFile = $_SERVER['DOCUMENT_ROOT'] . '/includes/member/' . $parts[3] . '.inc'; require_once $_SERVER['DOCUMENT_ROOT'] . '/includes/member/' . $parts[3] . '.inc'; } else { - header("Location: /?error=" . $lang["page"]["system"] . " " . $parts[3]) and die(); + peh_error("Member page not found: " . strip_tags($parts[3]), 404); } die(); } diff --git a/pages/parser.inc b/pages/parser.inc deleted file mode 100644 index 47e0775..0000000 --- a/pages/parser.inc +++ /dev/null @@ -1,4 +0,0 @@ -<?php - -header("Location: /"); -die();
\ No newline at end of file diff --git a/pages/pleasure.inc b/pages/pleasure.inc deleted file mode 100644 index ac59cfd..0000000 --- a/pages/pleasure.inc +++ /dev/null @@ -1,16 +0,0 @@ -<?php - -return; -require_once $_SERVER['DOCUMENT_ROOT'] . "/includes/init.inc"; global $title; global $isLoggedIn; global $lang; global $pages; -$emergencyHeader = true; require_once $_SERVER['DOCUMENT_ROOT'] . '/includes/header.inc'; - -?> - -<br> -<div class="container"> - <div id="page-content"> - <?php require_once $_SERVER['DOCUMENT_ROOT'] . "/includes/pleasure.inc"; ?> - </div> -</div> - -<?php require_once $_SERVER['DOCUMENT_ROOT'] . '/includes/footer.inc'; ?> diff --git a/pages/prefix.inc b/pages/prefix.inc deleted file mode 100644 index 47e0775..0000000 --- a/pages/prefix.inc +++ /dev/null @@ -1,4 +0,0 @@ -<?php - -header("Location: /"); -die();
\ No newline at end of file diff --git a/pages/relations.inc b/pages/relations.inc index 8d14fe7..b66ab25 100644 --- a/pages/relations.inc +++ b/pages/relations.inc @@ -9,13 +9,7 @@ require_once $_SERVER['DOCUMENT_ROOT'] . '/includes/header.inc'; <div class="container"> <div id="page-content"> <h2><?= $pages["relations"]["name"][$lang["_name"]] ?></h2> - <?php foreach (withCaretakersDown(array_filter(scoreOrderGlobal(), function ($i) { - if ($_SERVER['HTTP_HOST'] === "fr.equestria.horse" && $i["_system"] !== "gdapd") { - return false; - } else { - return true; - } - })) as $member): ?> + <?php foreach (withCaretakersDown(scoreOrderGlobal()) as $member): ?> <div class="relation" style="background-color:rgba(255, 255, 255, .1);margin-bottom:10px;padding:10px;border-radius:10px;display:grid;grid-template-columns: 1.5fr 2fr 2fr 2fr;"> <a class="relation-intro" style="background-color:rgba(255, 255, 255, .05);border-right:1px solid rgba(255, 255, 255, .1);margin:-10px;padding:10px;border-top-left-radius:10px;border-bottom-left-radius:10px;color: white;text-decoration: none;" href="/<?= $member["name"] ?>"> <img src="<?= getAsset($member["system"], $member["id"], "heads") ?>" style="width:24px;"> <?= $member["display_name"] ?? $member["name"] ?> diff --git a/pages/rules-old.inc b/pages/rules-old.inc deleted file mode 100644 index a567bc5..0000000 --- a/pages/rules-old.inc +++ /dev/null @@ -1,4 +0,0 @@ -<?php - -header("Location: /-/rules"); -die();
\ No newline at end of file diff --git a/pages/score.inc b/pages/score.inc deleted file mode 100644 index 97e666c..0000000 --- a/pages/score.inc +++ /dev/null @@ -1,208 +0,0 @@ -<?php - -require_once $_SERVER['DOCUMENT_ROOT'] . "/includes/init.inc"; global $title; global $isLoggedIn; global $lang; global $pages; -require_once $_SERVER['DOCUMENT_ROOT'] . '/includes/header.inc'; - -?> - -<br> -<div class="container"> - <div id="page-content"> - <h2>Score system testing</h2> - - <h4>Raindrops System (<code><?php - - $scores = []; - foreach (json_decode(file_get_contents($_SERVER['DOCUMENT_ROOT'] . "/includes/data/gdapd/members.json"), true) as $member) { - if ($member["name"] !== "unknown" && $member["name"] !== "fusion" && $member["name"] !== "new" && !str_ends_with($member["name"], "-travelling")) { - require_once $_SERVER['DOCUMENT_ROOT'] . "/includes/score.inc"; - $metadata = parseMetadata(json_decode(file_get_contents($_SERVER['DOCUMENT_ROOT'] . "/includes/data/metadata/$member[id].json"), true)); - $score = calculateScore($metadata, $member["display_name"] ?? $member["name"]); - - $scores[] = $score["total"]; - } - } - - $total = array_reduce($scores, function($a, $b) { - return $a + $b; - }); - - echo round($total / (count(json_decode(file_get_contents($_SERVER['DOCUMENT_ROOT'] . "/includes/data/gdapd/members.json"), true)) - 1)); - - ?></code>)</h4> - <ul> - <?php - - $scores = []; - foreach (json_decode(file_get_contents($_SERVER['DOCUMENT_ROOT'] . "/includes/data/gdapd/members.json"), true) as $member) { - if ($member["name"] !== "unknown" && $member["name"] !== "fusion" && $member["name"] !== "new" && !str_ends_with($member["name"], "-travelling")) { - $name = $member["display_name"] ?? $member["name"]; - require_once $_SERVER['DOCUMENT_ROOT'] . "/includes/score.inc"; - $metadata = parseMetadata(json_decode(file_get_contents($_SERVER['DOCUMENT_ROOT'] . "/includes/data/metadata/$member[id].json"), true)); - $score = calculateScore($metadata, $member["display_name"] ?? $member["name"]); - - $scores[] = [ - "name" => $name, - "page" => "/" . $member["name"], - "score" => $score["total"], - "details" => $score - ]; - } - } - - uasort($scores, function($a, $b) { - return $b["score"] - $a["score"]; - }); - - ?> - - <?php foreach ($scores as $score): ?> - <li> - <details> - <summary><a href="<?= $score["page"] ?>"><?= $score["name"] ?></a> (<code><?= $score["score"] ?></code>)</summary> - <pre><?= json_encode($score["details"], JSON_PRETTY_PRINT) ?></pre> - </details> - </li> - <?php endforeach; ?> - </ul> - - - <h4>Cloudburst System (<code><?php - - $scores = []; - foreach (json_decode(file_get_contents($_SERVER['DOCUMENT_ROOT'] . "/includes/data/ynmuc/members.json"), true) as $member) { - if ($member["name"] !== "unknown" && $member["name"] !== "fusion" && $member["name"] !== "new" && !str_ends_with($member["name"], "-travelling")) { - require_once $_SERVER['DOCUMENT_ROOT'] . "/includes/score.inc"; - $metadata = parseMetadata(json_decode(file_get_contents($_SERVER['DOCUMENT_ROOT'] . "/includes/data/metadata/$member[id].json"), true)); - $score = calculateScore($metadata, $member["display_name"] ?? $member["name"]); - - $scores[] = $score["total"]; - } - } - - $total = array_reduce($scores, function($a, $b) { - return $a + $b; - }); - - echo round($total / (count(json_decode(file_get_contents($_SERVER['DOCUMENT_ROOT'] . "/includes/data/ynmuc/members.json"), true)) - 1)); - - ?></code>)</h4> - <ul> - <?php - - $scores = []; - foreach (json_decode(file_get_contents($_SERVER['DOCUMENT_ROOT'] . "/includes/data/ynmuc/members.json"), true) as $member) { - if ($member["name"] !== "unknown" && $member["name"] !== "fusion" && $member["name"] !== "new" && !str_ends_with($member["name"], "-travelling")) { - $name = $member["display_name"] ?? $member["name"]; - require_once $_SERVER['DOCUMENT_ROOT'] . "/includes/score.inc"; - $metadata = parseMetadata(json_decode(file_get_contents($_SERVER['DOCUMENT_ROOT'] . "/includes/data/metadata/$member[id].json"), true)); - $score = calculateScore($metadata, $member["display_name"] ?? $member["name"]); - - $scores[] = [ - "name" => $name, - "page" => "/" . $member["name"], - "score" => $score["total"], - "details" => $score - ]; - } - } - - uasort($scores, function($a, $b) { - return $b["score"] - $a["score"]; - }); - - ?> - - <?php foreach ($scores as $score): ?> - <li> - <details> - <summary><a href="<?= $score["page"] ?>"><?= $score["name"] ?></a> (<code><?= $score["score"] ?></code>)</summary> - <pre><?= json_encode($score["details"], JSON_PRETTY_PRINT) ?></pre> - </details> - </li> - <?php endforeach; ?> - </ul> - - <h4>Global (<code><?php - - $scores = []; - foreach (json_decode(file_get_contents($_SERVER['DOCUMENT_ROOT'] . "/includes/data/gdapd/members.json"), true) as $member) { - if ($member["name"] !== "unknown" && $member["name"] !== "fusion" && $member["name"] !== "new" && !str_ends_with($member["name"], "-travelling")) { - require_once $_SERVER['DOCUMENT_ROOT'] . "/includes/score.inc"; - $metadata = parseMetadata(json_decode(file_get_contents($_SERVER['DOCUMENT_ROOT'] . "/includes/data/metadata/$member[id].json"), true)); - $score = calculateScore($metadata, $member["display_name"] ?? $member["name"]); - - $scores[] = $score["total"]; - } - } - foreach (json_decode(file_get_contents($_SERVER['DOCUMENT_ROOT'] . "/includes/data/ynmuc/members.json"), true) as $member) { - if ($member["name"] !== "unknown" && $member["name"] !== "fusion" && $member["name"] !== "new" && !str_ends_with($member["name"], "-travelling")) { - require_once $_SERVER['DOCUMENT_ROOT'] . "/includes/score.inc"; - $metadata = parseMetadata(json_decode(file_get_contents($_SERVER['DOCUMENT_ROOT'] . "/includes/data/metadata/$member[id].json"), true)); - $score = calculateScore($metadata, $member["display_name"] ?? $member["name"]); - - $scores[] = $score["total"]; - } - } - - $total = array_reduce($scores, function($a, $b) { - return $a + $b; - }); - - echo round($total / ((count(json_decode(file_get_contents($_SERVER['DOCUMENT_ROOT'] . "/includes/data/gdapd/members.json"), true)) + count(json_decode(file_get_contents($_SERVER['DOCUMENT_ROOT'] . "/includes/data/ynmuc/members.json"), true))) - 2)); - - ?></code>)</h4> - <ul> - <?php - - $scores = []; - foreach (json_decode(file_get_contents($_SERVER['DOCUMENT_ROOT'] . "/includes/data/gdapd/members.json"), true) as $member) { - if ($member["name"] !== "unknown" && $member["name"] !== "fusion" && $member["name"] !== "new" && !str_ends_with($member["name"], "-travelling")) { - $name = $member["display_name"] ?? $member["name"]; - require_once $_SERVER['DOCUMENT_ROOT'] . "/includes/score.inc"; - $metadata = parseMetadata(json_decode(file_get_contents($_SERVER['DOCUMENT_ROOT'] . "/includes/data/metadata/$member[id].json"), true)); - $score = calculateScore($metadata, $member["display_name"] ?? $member["name"]); - - $scores[] = [ - "name" => $name, - "page" => "/" . $member["name"], - "score" => $score["total"], - "details" => $score - ]; - } - } - foreach (json_decode(file_get_contents($_SERVER['DOCUMENT_ROOT'] . "/includes/data/ynmuc/members.json"), true) as $member) { - if ($member["name"] !== "unknown" && $member["name"] !== "fusion" && $member["name"] !== "new" && !str_ends_with($member["name"], "-travelling")) { - $name = $member["display_name"] ?? $member["name"]; - require_once $_SERVER['DOCUMENT_ROOT'] . "/includes/score.inc"; - $metadata = parseMetadata(json_decode(file_get_contents($_SERVER['DOCUMENT_ROOT'] . "/includes/data/metadata/$member[id].json"), true)); - $score = calculateScore($metadata, $member["display_name"] ?? $member["name"]); - - $scores[] = [ - "name" => $name, - "page" => "/" . $member["name"], - "score" => $score["total"], - "details" => $score - ]; - } - } - - uasort($scores, function($a, $b) { - return $b["score"] - $a["score"]; - }); - - ?> - - <?php foreach ($scores as $score): ?> - <li> - <details> - <summary><a href="<?= $score["page"] ?>"><?= $score["name"] ?></a> (<code><?= $score["score"] ?></code>)</summary> - <pre><?= json_encode($score["details"], JSON_PRETTY_PRINT) ?></pre> - </details> - </li> - <?php endforeach; ?> - </ul> - </div> -</div> - -<?php require_once $_SERVER['DOCUMENT_ROOT'] . '/includes/footer.inc'; ?> diff --git a/pages/terminology.inc b/pages/terminology.inc index ec810eb..d94eddc 100644 --- a/pages/terminology.inc +++ b/pages/terminology.inc @@ -8,7 +8,7 @@ require_once $_SERVER['DOCUMENT_ROOT'] . '/includes/header.inc'; <br> <div class="container"> <div id="page-content"> - <?= file_exists($_SERVER['DOCUMENT_ROOT'] . "/content/terminology.$lang[_name].html") ? file_get_contents($_SERVER['DOCUMENT_ROOT'] . "/content/terminology.$lang[_name].html") : file_get_contents($_SERVER['DOCUMENT_ROOT'] . "/content/terminology.html") ?> + <?= file_get_contents($_SERVER['DOCUMENT_ROOT'] . "/includes/terminology.html") ?> </div> </div> diff --git a/pages/thinkpad.inc b/pages/thinkpad.inc deleted file mode 100644 index af1bcfa..0000000 --- a/pages/thinkpad.inc +++ /dev/null @@ -1,50 +0,0 @@ -<?php - -// 2:20 - -require_once $_SERVER['DOCUMENT_ROOT'] . "/includes/init.inc"; global $title; global $isLoggedIn; global $lang; global $pages; -require_once $_SERVER['DOCUMENT_ROOT'] . '/includes/header.inc'; - -$password = json_decode(file_get_contents($_SERVER['DOCUMENT_ROOT'] . "/includes/app.json"), true)["thinkpad"]["password"]; -$mac = json_decode(file_get_contents($_SERVER['DOCUMENT_ROOT'] . "/includes/app.json"), true)["thinkpad"]["mac"]; -$error = ""; -$success = ""; - -if (isset($_POST["submit"]) && isset($_POST["pwd"])) { - if (password_verify($_POST["pwd"], $password)) { - $out = []; - exec("bash -c '/usr/sbin/ether-wake " . $mac . "'", $out); - - if (count($out) === 0) { - $success = "Successfully turned laptop on, please wait 5 minutes before connecting to it, and don't forget to turn it back off afterwards you dork"; - } else { - $error = "Failed to initiate Wake on LAN message: " . implode(", ", $out); - } - } else { - $error = "Invalid password, I am going to burn down your house if you're trying to touch my laptop"; - } -} - -?> - -<br> -<div class="container"> - <div id="page-content"> - <h2>ThinkPad</h2> - - <?php if (trim($error) !== ""): ?> - <div class="alert alert-danger"><b>Error:</b> <?= $error ?></div> - <?php endif; ?> - <?php if (trim($success) !== ""): ?> - <div class="alert alert-success"><b>Success:</b> <?= $success ?></div> - <?php endif; ?> - - <form method="post"> - <input type="hidden" name="submit" action="/-/thinkpad"> - <p><input type="password" name="pwd" class="form-control" placeholder="Password" style="filter: invert(1) hue-rotate(180deg);"></p> - <button class="btn btn-primary">Flip the switch!</button> - </form> - </div> -</div> - -<?php require_once $_SERVER['DOCUMENT_ROOT'] . '/includes/footer.inc'; ?> diff --git a/pages/together-dev.inc b/pages/together-dev.inc deleted file mode 100644 index 6ea9704..0000000 --- a/pages/together-dev.inc +++ /dev/null @@ -1,4 +0,0 @@ -<?php - -global $WebSocketAddress; $WebSocketAddress = "ws://localhost:22666"; -require_once $_SERVER['DOCUMENT_ROOT'] . "/pages/together.inc";
\ No newline at end of file diff --git a/pages/together.inc b/pages/together.inc deleted file mode 100644 index c210fa5..0000000 --- a/pages/together.inc +++ /dev/null @@ -1,940 +0,0 @@ -<?php - -$_GET['old'] = ""; -require_once $_SERVER['DOCUMENT_ROOT'] . "/includes/init.inc"; global $title; global $isLoggedIn; global $lang; global $pages; -require_once $_SERVER['DOCUMENT_ROOT'] . '/includes/header.inc'; - -global $WebSocketAddress; - -if (!isset($WebSocketAddress)) { - $WebSocketAddress = "wss://ponies.equestria.horse/_WatchTogether-WebSocket-EntryPoint/socket"; -} - -?> - -<style> - .list-group-item { - color: #fff; - background-color: #222; - border: 1px solid rgba(255, 255, 255, .125); - } - - .list-group-item.disabled { - color: #fff; - background-color: #222; - border-color: rgba(255, 255, 255, .125); - opacity: .75; - } - - .list-group-item-action:hover { - background-color: #252525; - color: #ddd; - } - - .list-group-item-action:active, .list-group-item-action:focus { - background-color: #272727; - color: #bbb; - } - - .video-queue-item { - display: grid; - grid-template-columns: 1fr max-content; - grid-gap: 10px; - cursor: pointer; - } - - .video-queue-item-status { - filter: invert(1); - display: block; - height: 32px; - width: 32px; - } - - .video-queue-item-part { - display: flex; - align-items: center; - } - - .video-queue-item-metadata { - width: 100%; - text-overflow: ellipsis; - white-space: nowrap; - overflow: hidden; - } - - .video-queue-item-title-outer, .video-queue-item-author-outer { - display: flex; - align-items: center; - } - - .video-queue-item-title, .video-queue-item-title-outer, .video-queue-item-author, .video-queue-item-author-outer { - text-overflow: ellipsis; - white-space: nowrap; - overflow: hidden; - width: 100%; - } - - .modal-header { - border-bottom: 1px solid #353738; - } - - .modal-content { - border: 1px solid rgba(255, 255, 255, .2); - background-color: #111; - } - - .btn-close { - filter: invert(1); - } - - .user-ping { - float: right; - display: inline-block; - width: 16px; - height: 16px; - border-radius: 999px; - position: relative; - top: 5px; - } - - .control-item { - display: inline-block; - cursor: pointer; - border-radius: 999px; - background-color: rgba(0, 0, 0, 0); - border: 1px solid rgba(255, 255, 255, 0); - transition: background-color 200ms, border-color 200ms; - } - - .control-item:hover { - background-color: rgba(0, 0, 0, .25); - border-color: rgba(255, 255, 255, .1); - } - - .control-item:active { - background-color: rgba(0, 0, 0, .5); - border-color: rgba(255, 255, 255, .25); - } - - .control-icon { - filter: invert(1); - width: 24px; - height: 24px; - margin: 12px; - pointer-events: none; - } - - body.hide-controls * { - cursor: none; - } - - #controls-outer { - opacity: 1; - transition: opacity 500ms; - } - - .navbar, #sidebar { - opacity: 1; - transition: opacity 500ms; - } - - body.hide-controls #controls-outer { - opacity: 0; - } - - body.hide-controls .navbar, body.hide-controls #sidebar { - opacity: .25; - } - - body.fullscreen #app-container { - grid-template-columns: 1fr !important; - } - - body.fullscreen .navbar, body.fullscreen #sidebar { - display: none; - } - - body.fullscreen #app-container div, body.fullscreen #app-container video { - height: 100vh !important; - } - - body.fullscreen #controls-outer, body.fullscreen #notification { - inset: 0 !important; - } - - #notification { - opacity: 0; - pointer-events: none; - transition: opacity 200ms; - } - - #video-title { - opacity: 1; - transition: opacity 200ms; - } - - body.notification #notification { - opacity: 1; - } - - body.notification #video-title { - opacity: 0; - } - - body.skipper #skipper { - opacity: 1 !important; - pointer-events: initial !important; - } - - #skipper { - opacity: 0; - pointer-events: none; - transition: opacity 200ms; - position: fixed; - bottom: 79px; - z-index: 999; - background: rgba(0, 0, 0, .5); - border-radius: 10px; - padding: 10px 20px; - left: 20px; - border: 1px solid rgba(255, 255, 255, .25); - cursor: pointer; - } - - #skipper:hover { - background: rgba(0, 0, 0, .75) !important; - } - - #skipper:active { - background: rgba(0, 0, 0, 1) !important; - } -</style> - -<script src="/assets/editor/thing.js"></script> - -<div class="modal fade" id="error" data-bs-backdrop="static" data-bs-keyboard="false" style="z-index: 99999;"> - <div class="modal-dialog"> - <div class="modal-content"> - <div class="modal-header"> - <h4 class="modal-title">An error occurred</h4> - </div> - - <div class="modal-body"> - <div class="alert alert-danger" id="error-message"></div> - </div> - </div> - </div> -</div> - -<div class="modal fade" id="add" data-bs-backdrop="static" data-bs-keyboard="false"> - <div class="modal-dialog"> - <div class="modal-content"> - <div class="modal-header"> - <h4 class="modal-title">Add new video</h4> - </div> - - <div class="modal-body"> - <p>Enter a YouTube video ID to add to the queue:</p> - <input type="text" class="form-control" id="add-id" placeholder="e.g. K9tUKbOFots" style="color:white;background:#111;border-color:#222;"> - <p style="margin-top:10px;margin-bottom: 0;"> - <div class="btn-group"> - <span onclick="doAdd();" id="add-btn-yes" class="btn btn-primary">Add</span> - <span onclick="closeAdd();" id="add-btn-no" class="btn btn-secondary">Cancel</span> - </div> - <a href="#" onclick="document.getElementById('add-id').value = 'K9tUKbOFots';">test</a> - </p> - </div> - </div> - </div> -</div> - -<div class="modal fade" id="welcome" data-bs-backdrop="static" data-bs-keyboard="false"> - <div class="modal-dialog"> - <div class="modal-content"> - <div class="modal-header"> - <h4 class="modal-title">Welcome to Watch Together!</h4> - </div> - - <div class="modal-body"> - <h5>Host a new session</h5> - <p>You will be given an invite code to share with your partner·s.</p> - <span class="btn btn-primary" id="host-start" onclick="hostSession();">Start</span> - - <hr> - - <h5>Join an existing session</h5> - <p>Enter the invite code your partner has given you:</p> - <div style="display:grid;grid-template-columns: repeat(8, 1fr);grid-gap:10px;"> - <input type="text" class="form-control" id="invite-input-1" style="text-align: center;color:white;background:#111;border-color:#222;" onchange="processInviteCode(event);" onkeydown="processInviteCode(event);" onkeyup="processInviteCode(event);" maxlength="1"> - <input type="text" class="form-control" id="invite-input-2" style="text-align: center;color:white;background:#111;border-color:#222;" onchange="processInviteCode(event);" onkeydown="processInviteCode(event);" onkeyup="processInviteCode(event);" maxlength="1"> - <input type="text" class="form-control" id="invite-input-3" style="text-align: center;color:white;background:#111;border-color:#222;" onchange="processInviteCode(event);" onkeydown="processInviteCode(event);" onkeyup="processInviteCode(event);" maxlength="1"> - <input type="text" class="form-control" id="invite-input-4" style="text-align: center;color:white;background:#111;border-color:#222;" onchange="processInviteCode(event);" onkeydown="processInviteCode(event);" onkeyup="processInviteCode(event);" maxlength="1"> - <input type="text" class="form-control" id="invite-input-5" style="text-align: center;color:white;background:#111;border-color:#222;" onchange="processInviteCode(event);" onkeydown="processInviteCode(event);" onkeyup="processInviteCode(event);" maxlength="1"> - <input type="text" class="form-control" id="invite-input-6" style="text-align: center;color:white;background:#111;border-color:#222;" onchange="processInviteCode(event);" onkeydown="processInviteCode(event);" onkeyup="processInviteCode(event);" maxlength="1"> - <input type="text" class="form-control" id="invite-input-7" style="text-align: center;color:white;background:#111;border-color:#222;" onchange="processInviteCode(event);" onkeydown="processInviteCode(event);" onkeyup="processInviteCode(event);" maxlength="1"> - <input type="text" class="form-control" id="invite-input-8" style="text-align: center;color:white;background:#111;border-color:#222;" onchange="processInviteCode(event);" onkeydown="processInviteCode(event);" onkeyup="processInviteCode(event);" maxlength="1"> - </div> - </div> - </div> - </div> -</div> -<script> - document.getElementById("invite-input-1").disabled = true; - document.getElementById("invite-input-2").disabled = true; - document.getElementById("invite-input-3").disabled = true; - document.getElementById("invite-input-4").disabled = true; - document.getElementById("invite-input-5").disabled = true; - document.getElementById("invite-input-6").disabled = true; - document.getElementById("invite-input-7").disabled = true; - document.getElementById("invite-input-8").disabled = true; - document.getElementById("host-start").classList.add("disabled"); - - let modal = new bootstrap.Modal(document.getElementById('welcome')); - modal.show(); - document.getElementById("invite-input-1").focus(); - - window.modalAdd = new bootstrap.Modal(document.getElementById('add')); - - function openAdd() { - modalAdd.show(); - } - - function closeAdd() { - document.getElementById("add-id").value = ""; - modalAdd.hide(); - } - - function doAdd() { - document.getElementById("add-id").disabled = true; - document.getElementById("add-btn-yes").classList.add("disabled"); - document.getElementById("add-btn-no").classList.add("disabled"); - - socket.send(JSON.stringify({ - task: "UPDATE_QUEUE", - payload: { - operation: "+", - video: document.getElementById("add-id").value - } - })) - } - - function toPrettyTime(seconds) { - let parts = new Date(seconds * 1000).toUTCString().split(" ")[4].split(":"); - parts[0] = parseInt(parts[0]).toString(); - - if (parts[0] === "0") { - parts[1] = parseInt(parts[1]).toString(); - parts.shift(); - } - - return parts.join(":"); - } - - function processInviteCode(event) { - let i1 = document.getElementById("invite-input-1").value.trim().toLowerCase().replace(/[^\da-z]+/gm, ""); - let i2 = document.getElementById("invite-input-2").value.trim().toLowerCase().replace(/[^\da-z]+/gm, ""); - let i3 = document.getElementById("invite-input-3").value.trim().toLowerCase().replace(/[^\da-z]+/gm, ""); - let i4 = document.getElementById("invite-input-4").value.trim().toLowerCase().replace(/[^\da-z]+/gm, ""); - let i5 = document.getElementById("invite-input-5").value.trim().toLowerCase().replace(/[^\da-z]+/gm, ""); - let i6 = document.getElementById("invite-input-6").value.trim().toLowerCase().replace(/[^\da-z]+/gm, ""); - let i7 = document.getElementById("invite-input-7").value.trim().toLowerCase().replace(/[^\da-z]+/gm, ""); - let i8 = document.getElementById("invite-input-8").value.trim().toLowerCase().replace(/[^\da-z]+/gm, ""); - - document.getElementById("invite-input-1").value = i1; - document.getElementById("invite-input-2").value = i2; - document.getElementById("invite-input-3").value = i3; - document.getElementById("invite-input-4").value = i4; - document.getElementById("invite-input-5").value = i5; - document.getElementById("invite-input-6").value = i6; - document.getElementById("invite-input-7").value = i7; - document.getElementById("invite-input-8").value = i8; - - if (i8 === "") { - document.getElementById("invite-input-8").focus(); - } - if (i7 === "") { - document.getElementById("invite-input-7").focus(); - } - if (i6 === "") { - document.getElementById("invite-input-6").focus(); - } - if (i5 === "") { - document.getElementById("invite-input-5").focus(); - } - if (i4 === "") { - document.getElementById("invite-input-4").focus(); - } - if (i3 === "") { - document.getElementById("invite-input-3").focus(); - } - if (i2 === "") { - document.getElementById("invite-input-2").focus(); - } - if (i1 === "") { - document.getElementById("invite-input-1").focus(); - } - - if (event instanceof KeyboardEvent) { - if (event.code === "Backspace" && event.type === "keydown") { - let el = event.target; - let ep = document.getElementById("invite-input-" + (el['id'].split("-")[2] - 1)); - - if (ep !== null) { - if (el.value.trim() === "") { - ep.value = ""; - ep.focus(); - } else { - el.value = ""; - ep.focus(); - } - } - } - } - - if (i1.length === 1 && i2.length === 1 && i3.length === 1 && i4.length === 1 && i5.length === 1 && i6.length === 1 && i7.length === 1 && i8.length === 1 && ((event.type && event.type === "keyup") || !event.type)) { - joinSession(i1 + i2 + i3 + i4 + i5 + i6 + i7 + i8); - } - } - - async function joinSession(code) { - document.getElementById("invite-input-1").disabled = true; - document.getElementById("invite-input-2").disabled = true; - document.getElementById("invite-input-3").disabled = true; - document.getElementById("invite-input-4").disabled = true; - document.getElementById("invite-input-5").disabled = true; - document.getElementById("invite-input-6").disabled = true; - document.getElementById("invite-input-7").disabled = true; - document.getElementById("invite-input-8").disabled = true; - document.getElementById("host-start").classList.add("disabled"); - - window.inviteCode = code; - - startSession(); - } - - async function hostSession() { - document.getElementById("invite-input-1").disabled = true; - document.getElementById("invite-input-2").disabled = true; - document.getElementById("invite-input-3").disabled = true; - document.getElementById("invite-input-4").disabled = true; - document.getElementById("invite-input-5").disabled = true; - document.getElementById("invite-input-6").disabled = true; - document.getElementById("invite-input-7").disabled = true; - document.getElementById("invite-input-8").disabled = true; - document.getElementById("host-start").classList.add("disabled"); - - window.inviteCode = null; - - startSession(); - } - - window.terminated = false; - window.users = null; - window.queue = null; - window.segments = []; - window.originalTitle = document.title; - - async function connect() { - window.identity = JSON.parse(await (await window.fetch("/api/me")).text()); - window.sessionToken = await (await window.fetch("/api/token")).text(); - - window.socket = new WebSocket("<?= $WebSocketAddress ?>"); - - socket.onclose = (event) => { - console.log("[ws:close] ",event); - - if (window.terminated) { - modal.hide(); - return; - } - - if (event.wasClean) { - document.getElementById('error-message').innerText = "Connection closed"; - } else { - if (event.reason) { - document.getElementById('error-message').innerText = "Connection closed unexpectedly with code " + event.code + ": " + event.reason; - } else { - document.getElementById('error-message').innerText = "Connection closed unexpectedly with code " + event.code; - } - } - - let errorModal = new bootstrap.Modal(document.getElementById('error')); - errorModal.show(); - modal.hide(); - } - - socket.onmessage = async (event) => { - let data = JSON.parse(event.data); - if (data.task !== "HEARTBEAT_ACK") console.log("[ws:message]", data); - - if (data.task === "CONFIG") { - document.getElementById("invite-input-1").disabled = false; - document.getElementById("invite-input-2").disabled = false; - document.getElementById("invite-input-3").disabled = false; - document.getElementById("invite-input-4").disabled = false; - document.getElementById("invite-input-5").disabled = false; - document.getElementById("invite-input-6").disabled = false; - document.getElementById("invite-input-7").disabled = false; - document.getElementById("invite-input-8").disabled = false; - document.getElementById("host-start").classList.remove("disabled"); - - setInterval(() => { - socket.send(JSON.stringify({ - task: "HEARTBEAT", - payload: { - videoPositon: document.getElementById("video").currentTime - } - })); - }, data.payload.heartbeatInterval); - - return; - } - - if (data.task === "SESSION") { - window.users = data.payload.users; - window.queue = data.payload.queue; - - updateQueue(); - - document.getElementById("participants").innerHTML = ""; - for (let user of data.payload.users) { - document.getElementById("participants").innerHTML += "<li class='list-group-item'>" + user.id + "<span id='user-" + user.id + "-ping' class='bg-primary user-ping'></span></li>"; - } - - document.getElementById("invite-code").innerText = data.payload.code; - } - - if (data.task === "VIDEO_UPDATE") { - if (data.payload.id !== null) { - try { - window.segments = JSON.parse(await (await window.fetch("https://sponsor.ajay.app/api/skipSegments/" + data.payload.sha.substring(0, 32) + '?categories=["sponsor","intro","outro","music_offtopic"]')).text()).filter(i => i['videoID'] === data.payload.id)[0].segments; - notification("This video is enhanced by smart playback", "success"); - } catch (e) { - notification("This video is not compatible with smart playback", "warning"); - window.segments = []; - } - } - - if (data.payload.url) document.getElementById("video").src = data.payload.url; - - if (data.payload.state === 1) { - document.getElementById("video").play(); - } else if (!!data.payload.state) { - document.getElementById("video").pause(); - } - - if (data.payload.title && data.payload.title.trim() !== "") { - document.getElementById("video-title").innerText = data.payload.title; - document.title = data.payload.title + " · " + window.originalTitle; - } else { - if (data.payload.title) { - document.getElementById("video-title").innerText = ""; - document.title = window.originalTitle; - } - } - - document.getElementById("video").currentTime = data.payload.position; - } - - if (data.task === "UPDATE_USERS") { - window.users = data.payload.users; - - document.getElementById("participants").innerHTML = ""; - for (let user of data.payload.users) { - document.getElementById("participants").innerHTML += "<li class='list-group-item'>" + user.id + "<span id='user-" + user.id + "-ping' class='bg-primary user-ping'></span></li>"; - } - } - - if (data.task === "UPDATE_QUEUE") { - window.queue = data.payload.queue; - - if (data.payload.poster === identity.id) { - document.getElementById("add-id").disabled = false; - document.getElementById("add-id").value = ""; - document.getElementById("add-btn-yes").classList.remove("disabled"); - document.getElementById("add-btn-no").classList.remove("disabled"); - - modalAdd.hide(); - } - - updateQueue(); - } - - if (data.task === "HEARTBEAT_ACK") { - for (let user of Object.keys(data.payload.delays)) { - let abs = Math.abs(data.payload.delays[user]); - let color = "primary"; - - if (abs >= 500) color = "warning"; - if (abs >= 1000) color = "danger"; - if (abs < 500) color = "success"; - - let sign = "±"; - if (data.payload.delays[user] < 0) sign = "-"; - if (data.payload.delays[user] > 0) sign = "+"; - - document.getElementById("user-" + user + "-ping").title = sign + abs + " ms"; - document.getElementById("user-" + user + "-ping").classList.remove("bg-primary"); - document.getElementById("user-" + user + "-ping").classList.remove("bg-danger"); - document.getElementById("user-" + user + "-ping").classList.remove("bg-warning"); - document.getElementById("user-" + user + "-ping").classList.remove("bg-green"); - document.getElementById("user-" + user + "-ping").classList.add("bg-" + color); - } - } - - if (data.task === "TERMINATE" || data.task === "FAILURE") { - window.terminated = true; - - if (data.payload.code) { - if (data.payload.reason) { - document.getElementById('error-message').innerText = data.payload.code + ": " + data.payload.reason; - let errorModal = new bootstrap.Modal(document.getElementById('error')); - errorModal.show(); - } else { - document.getElementById('error-message').innerText = data.payload.code; - let errorModal = new bootstrap.Modal(document.getElementById('error')); - errorModal.show(); - } - } else { - document.getElementById('error-message').innerText = "Error"; - let errorModal = new bootstrap.Modal(document.getElementById('error')); - errorModal.show(); - } - - if (data.task === "FAILURE") socket.close(); - } - } - - socket.onopen = (event) => { - console.log("[ws:open] ", event); - - socket.send(JSON.stringify({ - task: "IDENTIFY", - payload: { - token: window.sessionToken - } - })) - } - } - - function updateQueue() { - document.getElementById("queue").innerHTML = ""; - - for (let video of window.queue) { - document.getElementById("queue").innerHTML += ` -<li class="list-group-item list-group-item-action video-queue-item"> - <div class="video-queue-item-part video-queue-item-metadata"> - <div> - <div class="video-queue-item-title-outer"> - <span class="video-queue-item-title">${video.title}</span> - </div> - <div class="video-queue-item-author-outer"> - <span class="video-queue-item-author text-muted">${video.author}</span> - </div> - </div> - </div> - <div class="video-queue-item-part text-muted">${video['duration_pretty'] ?? toPrettyTime(video.duration)}</div> -</li> -`; - } - } - - function startSession() { - socket.send(JSON.stringify({ - task: "SESSION", - payload: { - id: window.inviteCode - } - })) - - modal.hide(); - } - - connect(); -</script> - -<div style="height:calc(100vh - 60px);display:grid;grid-template-columns: 3fr 1.5fr;" id="app-container"> - <div style="height:calc(100vh - 60px);"> - <video id="video" style="width:100%;height:calc(100vh - 60px);"></video> - </div> - <script> - - document.getElementById("video").onplay = () => { - console.log("play"); - - if (socket) socket.send(JSON.stringify({ - task: "VIDEO_UPDATE", - payload: { - state: 1, - position: document.getElementById("video").currentTime - } - })); - } - - document.getElementById("video").onpause = () => { - console.log("pause"); - - if (socket) socket.send(JSON.stringify({ - task: "VIDEO_UPDATE", - payload: { - state: 0, - position: document.getElementById("video").currentTime - } - })); - } - - let controlsFadeInterval; - document.body.classList.remove("hide-controls"); - - document.body.onmousemove = document.body.onmouseup = () => { - document.body.classList.remove("hide-controls"); - try { clearTimeout(controlsFadeInterval) } catch (e) {} - controlsFadeInterval = setTimeout(() => { - if (!document.getElementById("video").paused) document.body.classList.add("hide-controls"); - }, 5000); - } - - </script> - <div class="container" id="sidebar" style="border-left:1px solid rgba(255, 255, 255, .25);"> - <br> - <h4>Participants</h4> - <ul class="list-group" id="participants"></ul> - <p style="margin-top:10px;margin-bottom:0;">Invite new participants with this invite code: <code id="invite-code">--------</code></p> - - <br> - <h4>Queue</h4> - <ul class="list-group" id="queue"></ul> - <p style="margin-top:10px;margin-bottom:0;"> - <span class="btn btn-primary" onclick="openAdd()">Add video</span> - </p> - </div> -</div> - -<div id="notification" style="z-index:999;padding: 15px 20px;font-size: 20px;position: fixed;top: 60px;left:0;text-shadow: 0 0 10px black;"> - Notification. -</div> -<a onclick="controls_skipIntroOutro();" id="skipper">Skip</a> -<div id="controls-outer" style="position:fixed;background: linear-gradient(180deg, rgba(0,0,0,0.5) 0%, rgba(0,0,0,0) 35%, rgba(0,0,0,0) 65%, rgba(0,0,0,0.5) 100%);top: 60px;left: 0;right: 0;bottom: 0;"> - <div id="video-title" style="padding: 15px 20px;font-size: 20px;"></div> - <div id="controls" style="position: fixed;bottom: 20px;height: 50px;left: 15px;display:grid;grid-template-columns: max-content 1fr max-content;"> - <div> - <a id="control-play" onclick="controls_playPause();" class="control-item"> - <img alt="" src="/assets/icons/together/play.svg" id="control-play-icon" class="control-icon"> - </a> - <a id="control-next" onclick="controls_next();" class="control-item"> - <img alt="" src="/assets/icons/together/next.svg" id="control-next-icon" class="control-icon"> - </a> - </div> - <div style="display: flex;align-items: center;padding-left:15px;padding-right:15px;"> - <div style="padding: 22px 0;width:100%;" id="seek-bar"> - <div style="height:6px;width:100%;background:rgba(255, 255, 255, .1);border-radius:999px;pointer-events: none;"> - <div style="height:6px;width:0;background:rgba(255, 255, 255, .75);border-radius:999px;" id="control-progress"></div> - </div> - </div> - </div> - <div> - <div style="display: inline-flex;align-items: center;"> - <span id="time-remaining" style="font-family:monospace;">-0:00</span> - </div> - <a id="control-full" onclick="controls_fullscreen();" class="control-item"> - <img alt="" src="/assets/icons/together/full-on.svg" id="control-full-icon" class="control-icon"> - </a> - </div> - </div> - <div id="seek-bar-dot" style="position: fixed;bottom: 38px;width: 12px;height: 12px;background: white;border-radius: 999px;pointer-events: none;display:none;"></div> -</div> -<script> - document.getElementById("controls").style.width = (document.getElementById("video").clientWidth - 30) + "px"; - document.getElementById("controls-outer").style.right = (window.innerWidth - document.getElementById("video").clientWidth) + "px"; - document.getElementById("notification").style.right = (window.innerWidth - document.getElementById("video").clientWidth) + "px"; - - let notificationDecayTimeout; - - function notification(text, color) { - document.getElementById("notification").innerText = text; - document.getElementById("notification").classList.add("text-" + color); - document.body.classList.add("notification"); - - try { clearTimeout(notificationDecayTimeout) } catch (e) {} - - notificationDecayTimeout = setTimeout(() => { - document.body.classList.remove("notification"); - setTimeout(() => { - document.getElementById("notification").innerText = "Notification."; - document.getElementById("notification").classList.remove("text-" + color); - }, 200); - }, 5000) - } - - window.onresize = () => { - document.getElementById("controls").style.width = (document.getElementById("video").clientWidth - 30) + "px"; - document.getElementById("controls-outer").style.right = (window.innerWidth - document.getElementById("video").clientWidth) + "px"; - document.getElementById("notification").style.right = (window.innerWidth - document.getElementById("video").clientWidth) + "px"; - } - - function controls_playPause() { - if (document.getElementById("video").src.trim() === "") return; - - if (document.getElementById("video").paused) { - document.getElementById("video").play(); - } else { - document.getElementById("video").pause(); - } - } - - function controls_fullscreen() { - if (document.fullscreen) { - document.exitFullscreen(); - } else { - document.documentElement.requestFullscreen(); - } - } - - function controls_next() { - document.getElementById("video").play(); - document.getElementById("video").currentTime = document.getElementById("video").duration; - } - - window.seeking = false; - window.seekPosition = 0; - - document.getElementById("controls-outer").onclick = (event) => { - if (event.target === document.getElementById("controls-outer")) controls_playPause(); - } - - document.getElementById("controls-outer").ondblclick = (event) => { - if (event.target === document.getElementById("controls-outer")) controls_fullscreen(); - } - - document.getElementById("seek-bar").onmouseenter = () => { - document.getElementById("seek-bar-dot").style.display = ""; - console.log("> ENTER <"); - window.seeking = true; - } - - document.getElementById("seek-bar").onclick = (event) => { - let percentage = (event.offsetX / document.getElementById("seek-bar").clientWidth) * 100; - let multiplier = event.offsetX / document.getElementById("seek-bar").clientWidth; - - document.getElementById("seek-bar-dot").style.left = event.clientX + "px"; - - console.log(" CLICK: ", event.offsetX, "(" + percentage.toFixed(3) + "%, " + toPrettyTime(document.getElementById("video").duration * multiplier) + ")"); - window.seekPosition = document.getElementById("video").duration * multiplier; - - document.getElementById("video").pause(); - document.getElementById("video").currentTime = window.seekPosition; - document.getElementById("video").play(); - } - - document.getElementById("seek-bar").onmouseleave = () => { - document.getElementById("seek-bar-dot").style.display = "none"; - console.log("< LEAVE >"); - window.seeking = false; - } - - function controls_skipIntroOutro() { - let skipper = null; - - for (let segment of window.segments.filter(i => i['category'] === "intro")) { - if (segment.segment) { - if (document.getElementById("video").currentTime >= segment.segment[0] && document.getElementById("video").currentTime < segment.segment[1]) { - skipper = segment.segment[1]; - } - } - } - for (let segment of window.segments.filter(i => i['category'] === "outro")) { - if (segment.segment) { - if (document.getElementById("video").currentTime >= segment.segment[0] && document.getElementById("video").currentTime < segment.segment[1]) { - skipper = segment.segment[1]; - } - } - } - - if (skipper) { - document.getElementById("video").pause(); - document.getElementById("video").currentTime = skipper; - document.getElementById("video").play(); - } - } - - document.getElementById("seek-bar").onmousemove = (event) => { - let percentage = (event.offsetX / document.getElementById("seek-bar").clientWidth) * 100; - let multiplier = event.offsetX / document.getElementById("seek-bar").clientWidth; - - document.getElementById("seek-bar-dot").style.left = event.clientX + "px"; - - console.log(" POS: ", event.offsetX, "(" + percentage.toFixed(3) + "%, " + toPrettyTime(document.getElementById("video").duration * multiplier) + ")"); - window.seekPosition = document.getElementById("video").duration * multiplier; - } - - setInterval(() => { - if (document.getElementById("video").src.trim() === "") { - document.getElementById("controls").style.display = "none"; - } else { - document.getElementById("controls").style.display = "grid"; - } - - document.getElementById("control-play-icon").src = document.getElementById("video").paused ? "/assets/icons/together/play.svg" : "/assets/icons/together/pause.svg"; - document.getElementById("control-full-icon").src = document.fullscreen ? "/assets/icons/together/full-off.svg" : "/assets/icons/together/full-on.svg"; - document.getElementById("control-progress").style.width = ((document.getElementById("video").currentTime / document.getElementById("video").duration) * 100) + "%"; - - if (document.fullscreen) { - document.body.classList.add("fullscreen"); - } else { - document.body.classList.remove("fullscreen"); - } - - if (window.seeking) { - document.getElementById("time-remaining").classList.add("text-warning"); - document.getElementById("time-remaining").innerText = toPrettyTime(window.seekPosition); - } else { - document.getElementById("time-remaining").classList.remove("text-warning"); - - if (!isNaN(document.getElementById("video").duration)) { - document.getElementById("time-remaining").innerText = "-" + toPrettyTime(Math.round(document.getElementById("video").duration) - Math.round(document.getElementById("video").currentTime)); - } else { - document.getElementById("time-remaining").innerText = "-0:00"; - } - } - }) - - setInterval(() => { - if (!document.getElementById("video").paused) { - for (let segment of window.segments.filter(i => i['category'] === "sponsor")) { - if (segment.segment) { - if (document.getElementById("video").currentTime >= segment.segment[0] && document.getElementById("video").currentTime < segment.segment[1]) { - document.getElementById("video").pause(); - document.getElementById("video").currentTime = segment.segment[1]; - document.getElementById("video").play(); - notification("Advert skipped by smart playback", "primary"); - } - } - } - - let skipper = false; - - for (let segment of window.segments.filter(i => i['category'] === "intro")) { - if (segment.segment) { - if (document.getElementById("video").currentTime >= segment.segment[0] && document.getElementById("video").currentTime < segment.segment[1]) { - skipper = true; - document.getElementById("skipper").innerText = "Skip intro"; - document.body.classList.add("skipper"); - } - } - } - for (let segment of window.segments.filter(i => i['category'] === "outro")) { - if (segment.segment) { - if (document.getElementById("video").currentTime >= segment.segment[0] && document.getElementById("video").currentTime < segment.segment[1]) { - skipper = true; - document.getElementById("skipper").innerText = "Skip to the end"; - document.body.classList.add("skipper"); - } - } - } - - if (!skipper) { - document.body.classList.remove("skipper"); - } - } - }) -</script>
\ No newline at end of file diff --git a/pages/toys.inc b/pages/toys.inc deleted file mode 100644 index 4c172c6..0000000 --- a/pages/toys.inc +++ /dev/null @@ -1,905 +0,0 @@ -<?php - -return; -require_once $_SERVER['DOCUMENT_ROOT'] . "/includes/init.inc"; global $title; - -if (isset($_POST['deleteAction'])) { - $data = json_decode(file_get_contents($_SERVER['DOCUMENT_ROOT'] . "/includes/data/toys/toys.json"), true); - - $selected = null; - $selectedIndex = -1; - $id = $_POST['action']; - - foreach ($data as $index => $item) { - if ($item["id"] === $id) { - $selectedIndex = $index; - $selected = $item; - break; - } - } - - if ($selected === null) { - header("Location: /-/toys"); - die(); - } - - unset($data[$selectedIndex]); - file_put_contents($_SERVER['DOCUMENT_ROOT'] . "/includes/data/toys/toys.json", utf8_encode(json_encode($data))); - header("Location: /-/toys/?d&id=" . $id); - die(); -} - -if (isset($_POST['updateAction'])) { - $data = json_decode(file_get_contents($_SERVER['DOCUMENT_ROOT'] . "/includes/data/toys/toys.json"), true); - - $selected = null; - $selectedIndex = -1; - $id = $_POST['action']; - - foreach ($data as $index => $item) { - if ($item["id"] === $id) { - $selectedIndex = $index; - $selected = $item; - break; - } - } - - if ($selected === null) { - header("Location: /-/toys"); - die(); - } - - if (isset($_POST["sexual"])) { - $selected["sexual"] = true; - } else { - $selected["sexual"] = false; - } - - if (isset($_POST["name"])) $selected["name"] = strip_tags(trim($_POST["name"])); - if (isset($_POST["usage"])) $selected["usage"] = strip_tags(trim($_POST["usage"])); - if (isset($_POST["irl"])) $selected["irl"] = strip_tags(trim($_POST["irl"])); - if (isset($_POST["keywords"])) $selected["keywords"] = array_map(function ($i) { - return trim($i); - }, explode(",", strip_tags(trim($_POST["keywords"])))); - if (isset($_POST["description"])) $selected["description"] = strip_tags(trim($_POST["description"])); - if (isset($_POST["water"])) $selected["water"] = match ($_POST["water"]) { - "0" => "out", - "1" => "in", - "2" => "both", - "3" => "playground" - }; - - if (isset($_POST["relations"])) { - $ponies = []; - - foreach ($_POST["relations"] as $relation => $d) { - $ponies[] = [ - "members" => explode("-", $relation), - "deprecated" => isset($d["deprecated"]), - "sexual" => isset($d["sexual"]) - ]; - } - - $selected["ponies"] = $ponies; - } - - global $_PROFILE; - if ($_PROFILE['login'] === "raindrops" && isset($_POST["verified"])) { - $selected["verified"] = true; - } else { - unset($selected["verified"]); - } - - if (isset($_POST["untested"])) { - $selected["untested"] = true; - } else { - unset($selected["untested"]); - } - - $data[$selectedIndex] = $selected; - file_put_contents($_SERVER['DOCUMENT_ROOT'] . "/includes/data/toys/toys.json", utf8_encode(json_encode($data))); - - header("Location: /-/toys/" . $id); - die(); -} - -if (isset($_POST['createAction'])) { - require_once $_SERVER['DOCUMENT_ROOT'] . "/includes/random.inc"; - $data = json_decode(file_get_contents($_SERVER['DOCUMENT_ROOT'] . "/includes/data/toys/toys.json"), true); - - if (!isset($_POST["name"]) || !isset($_POST["water"])) { - header("Location: /-/toys"); - die(); - } - if (trim($_POST["name"]) === "" || !is_numeric($_POST["water"])) { - header("Location: /-/toys"); - die(); - } - - $water = match ($_POST["water"]) { - "0" => "out", - "1" => "in", - "2" => "both", - "3" => "playground" - }; - $name = strip_tags(trim($_POST["name"])); - $id = random(); - - $ponies = []; - - if (isset($_POST["relations"])) { - foreach ($_POST["relations"] as $relation => $_) { - $ponies[] = [ - "members" => explode("-", $relation), - "deprecated" => false - ]; - } - } - - if (isset($_POST["sexual"])) { - $sexual = true; - } else { - $sexual = false; - } - - $data[] = [ - "id" => $id, - "name" => $name, - "water" => $water, - "description" => null, - "ponies" => $ponies, - "usage" => null, - "irl" => null, - "keywords" => [], - "sexual" => $sexual - ]; - - file_put_contents($_SERVER['DOCUMENT_ROOT'] . "/includes/data/toys/toys.json", utf8_encode(json_encode($data))); - header("Location: /-/toys/" . $id); - die(); -} - -global $pagename; -$parts = explode("/", $pagename); -$data = json_decode(file_get_contents($_SERVER['DOCUMENT_ROOT'] . "/includes/data/toys/toys.json"), true); - -$selected = null; - -if (isset($parts[1])) { - $id = $parts[1]; - - foreach ($data as $item) { - if ($item["id"] === $id) { - $selected = $item; - break; - } - } - - if ($selected === null) { - header("Location: /-/toys/?nf&id=" . $id); - die(); - } else { - $title = $selected["name"] . " · " . $title; - } -} - -require_once $_SERVER['DOCUMENT_ROOT'] . '/includes/header.inc'; -require_once $_SERVER['DOCUMENT_ROOT'] . '/includes/keywords.inc'; - -if (!file_exists($_SERVER['DOCUMENT_ROOT'] . "/includes/data/toys/toys.json")) file_put_contents($_SERVER['DOCUMENT_ROOT'] . "/includes/data/toys/toys.json", "[]"); - -global $_PROFILE; -global $pagename; -$parts = explode("/", $pagename); - -?> - -<script src="/assets/editor/fuse.js"></script> - -<br> -<div class="container"> - <div id="<?= isset($parts[1]) ? "page-content" : "" ?>"> - <?php if (isset($_GET['nf'])): ?> - <div class="alert alert-danger alert-dismissible"> - <button onclick='window.history.pushState({"html":null,"pageTitle":document.title},"", "/-/toys/");' type="button" class="btn-close" data-bs-dismiss="alert" style="filter: none !important;"></button> - <b>Error: </b> The requested toy (<code><?= strip_tags($_GET['id'] ?? "-") ?></code>) was not found, it may have been deleted or has never existed. - </div> - <?php endif; ?> - - <?php if (isset($_GET['d'])): ?> - <div class="alert alert-success alert-dismissible"> - <button onclick='window.history.pushState({"html":null,"pageTitle":document.title},"", "/-/toys");' type="button" class="btn-close" data-bs-dismiss="alert" style="filter: none !important;"></button> - <b>Success: </b> The toy with ID <code><?= strip_tags($_GET['id'] ?? "-") ?></code> has been successfully deleted. - </div> - <?php endif; ?> - - <?php if (isset($parts[1])): ?> - - <h2> - <span style="vertical-align: middle;"><?= $selected["name"] ?></span> - <a href="/-/toys" class="small btn btn-outline-light" style="float:right;margin-top:5px;vertical-align:middle;opacity:1 !important; color:white;">Back</a> - </h2> - <p> - <a onclick="event.target.blur();" data-bs-toggle="modal" data-bs-target="#editor" href="#">Edit</a> · - <?php if ($selected["sexual"]): ?> - <span style="" class="badge rounded-pill bg-danger">Sexual</span> - <?php else: ?> - <span style="" class="badge rounded-pill bg-success">Pleasurable</span> - <?php endif; ?> - <?php if (!isset($selected["verified"])): ?><span class="badge bg-warning rounded-pill text-black">Unverified</span><?php endif; ?> - <?php if (isset($selected["untested"])): ?><span class="badge bg-info rounded-pill">Untested</span><?php endif; ?> - <?php if ($selected["water"] === "in"): ?> - <span style="" class="badge rounded-pill bg-primary">Underwater</span> - <?php elseif ($selected["water"] === "out"): ?> - <span style="background-color:#d63384;" class="badge rounded-pill">Outside of water</span> - <?php elseif ($selected["water"] === "playground"): ?> - <span class="badge rounded-pill" style="background-color:#20c997;">In playground</span> - <?php else: ?> - <span style="" class="badge rounded-pill bg-primary">Underwater</span> - <span style="background-color:#d63384;" class="badge rounded-pill">Outside of water</span> - <?php endif; ?> - </p> - - <?php if (isset($selected["description"]) && trim($selected["description"]) !== ""): ?> - <?= replaceKeyWords(str_replace("\n", "<br>", strip_tags($selected["description"]))); ?> - <?php else: ?> - <p><i>No description provided for this toy. Enter edit mode to add a description to this toy.</i></p> - <?php endif; ?> - - <hr> - <!-- - <b>Can be used by:</b> - <?php - - $hasMultipleTypes = false; - $seenType = ""; - - foreach ($selected["ponies"] as $relation) { - if (isset($relation["sexual"]) && $relation["sexual"]) { - $type = "sexual"; - } else { - $type = "affectionate"; - } - - if ($type !== $seenType && $seenType !== "") { - $hasMultipleTypes = true; - } - - if (trim($seenType) === "") { - $seenType = $type; - } - } - - ?> - <ul> - <?php foreach ($selected["ponies"] as $relation): if (!$relation["deprecated"]): - - $member1 = getMemberWithoutSystem($relation["members"][0]); - $member2 = getMemberWithoutSystem($relation["members"][1]); - - ?> - <li> - <img style="vertical-align: middle;width:24px;height:24px;" src="/assets/uploads/pt-<?= $member1["name"] ?>.png"> - <img style="vertical-align: middle;width:24px;height:24px;" src="/assets/uploads/pt-<?= $member2["name"] ?>.png"> - - <span style="vertical-align: middle;"><?= getMiniName($member1["display_name"] ?? $member1["name"]) ?> and <?= getMiniName($member2["display_name"] ?? $member2["name"]) ?></span> - </li> - <?php endif; endforeach; ?> - <?php foreach ($selected["ponies"] as $relation): if ($relation["deprecated"]): - - $member1 = getMemberWithoutSystem($relation["members"][0]); - $member2 = getMemberWithoutSystem($relation["members"][1]); - - ?> - <li> - <span style="opacity:.5;"> - <img style="vertical-align: middle;width:24px;height:24px;" src="/assets/uploads/pt-<?= $member1["name"] ?>.png"> - <img style="vertical-align: middle;width:24px;height:24px;" src="/assets/uploads/pt-<?= $member2["name"] ?>.png"> - - <span style="vertical-align: middle;"><?= getMiniName($member1["display_name"] ?? $member1["name"]) ?> and <?= getMiniName($member2["display_name"] ?? $member2["name"]) ?></span> - </span> - <span class="badge bg-danger rounded-pill">Deprecated</span> - </li> - <?php endif; endforeach; ?> - </ul>--> - - <div style="margin-top:10px;"></div> - - <b>Usage:</b><br> - <?php if (isset($selected["usage"]) && trim($selected["usage"]) !== ""): ?> - <?php - - $lines = explode("\n", strip_tags($selected["usage"])); - - if (count($lines) > 1) echo("<ul>"); - - foreach ($lines as $line) { - if (count($lines) > 1) echo("<li>"); - - $parts = explode(":", $line); - - if (count($parts) > 1 && strlen($parts[0]) < 30) { - $p0 = $parts[0]; array_shift($parts); - echo(replaceKeyWords("<b>" . $p0 . ":</b>" . implode(":", $parts))); - } else { - echo(replaceKeyWords(implode(":", $parts))); - } - - if (count($lines) > 1) echo("</li>"); - } - - if (count($lines) > 1) echo("</ul>"); - - ?> - <?php else: ?> - <p><i>No usage provided for this toy. Enter edit mode to add usage information to this toy.</i></p> - <?php endif; ?> - - <div style="margin-top:10px;"></div> - - <b>Instructions to craft in real life:</b><br> - <?php if (isset($selected["irl"]) && trim($selected["irl"]) !== ""): ?> - <?= replaceKeyWords(strip_tags($selected["irl"])) ?> - <?php else: ?> - <p><i>This toy is not craftable in real life.</i></p> - <?php endif; ?> - - <hr> - - <h4>Similar toys</h4> - <div class="row"> - <?php - - $names = []; - $currentName = $selected["name"]; - $namesByDistance = []; - - foreach ($data as $action) { - if ($action["name"] !== $currentName) $names[$action["name"]] = [ - "id" => $action["id"], - "water" => $action["water"], - "ponies" => $action["ponies"], - "sexual" => $action["sexual"] - ]; - } - - foreach ($names as $name => $data) { - $namesByDistance[] = [ - "name" => $name, - "distance" => levenshtein($currentName, $name) + ((int)($data["water"] !== $selected["water"]) * 2), - "id" => $data["id"], - "water" => $data["water"], - "ponies" => $data["ponies"], - "sexual" => $data["sexual"] - ]; - } - - uasort($namesByDistance, function ($a, $b) use ($selected) { - return $a["distance"] - $b["distance"]; - }); - - foreach ($namesByDistance as $item) { - echo("<!-- " . $currentName . " <-> " . $item["name"] . " => " . $item["distance"] . " (artif: " . ((int)($item["water"] !== $selected["water"]) * 10) . ") -->"); - } - - $index = 0; - foreach ($namesByDistance as $item): if ($index < 3): - ?> - <div class="col-md-4" style="margin-bottom:20px;"> - <a class="linked-card" href="/-/toys/<?= $item["id"] ?>"><div class="card"> - <div class="card-body"> - <h4 class="card-title"><?= $item["name"] ?></h4> - <p class="card-text"> - <!-- - <?php - - $uniquePonies = []; - - foreach ($item["ponies"] as $ponies) { - foreach ($ponies["members"] as $member) { - if (isset($uniquePonies[$member]) && !$uniquePonies[$member]) { - $uniquePonies[$member] = false; - } else { - $uniquePonies[$member] = $ponies["deprecated"]; - } - } - } - - foreach ($uniquePonies as $name => $deprecated): if (!$deprecated): ?> - <span data-bs-toggle="tooltip" title="<?= getMemberWithoutSystem($name)["display_name"] ?? getMemberWithoutSystem($name)["display_name"] ?>" style="display: inline-block;"> - <img src="/assets/uploads/pt-<?= getMemberWithoutSystem($name)["name"] ?>.png" style="width:32px;"> - </span> - <?php endif; endforeach; ?> - <?php foreach ($uniquePonies as $name => $deprecated): if ($deprecated): ?> - <span data-bs-toggle="tooltip" data-bs-html="true" title="<i><?= strip_tags(getMemberWithoutSystem($name)["display_name"] ?? getMemberWithoutSystem($name)["name"]) ?></i>" style="opacity:.5;display: inline-block;"> - <img src="/assets/uploads/pt-<?= getMemberWithoutSystem($name)["name"] ?>.png" style="width:32px;"> - </span> - <?php endif; endforeach; ?>--> - - - </p> - <?php if ($item["sexual"]): ?> - <span style="" class="badge rounded-pill bg-danger">Sexual</span> - <?php else: ?> - <span style="" class="badge rounded-pill bg-success">Pleasurable</span> - <?php endif; ?> - <?php if ($item["water"] === "in"): ?> - <span style="" class="badge rounded-pill bg-primary">Underwater</span> - <?php elseif ($item["water"] === "out"): ?> - <span style="background-color:#d63384;" class="badge rounded-pill">Outside of water</span> - <?php elseif ($item["water"] === "playground"): ?> - <span class="badge rounded-pill" style="background-color:#20c997;">In playground</span> - <?php else: ?> - <span style="" class="badge rounded-pill bg-primary">Underwater</span> - <span style="background-color:#d63384;" class="badge rounded-pill">Outside of water</span> - <?php endif; ?> - </div> - </div></a> - </div> - <?php $index++; endif; endforeach; ?> - </div> - - <div class="modal fade" id="editor"> - <div class="modal-dialog"> - <div class="modal-content"> - <div class="modal-header"> - <h4 class="modal-title">Edit toy</h4> - <button type="button" class="btn-close" data-bs-dismiss="modal"></button> - </div> - - <div class="modal-body"> - <form method="post" style="display:inline;"> - <input type="text" placeholder="Toy name" name="name" class="form-control" style="color:white;background:#111;border-color:#222;margin-bottom:10px;" value="<?= str_replace('"', '"', $selected["name"]) ?>"> - <select name="water" class="form-select" style='color:white;background-color:#111;border-color:#222;background-image:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3e%3cpath fill='none' stroke='%23ffffff' stroke-linecap='round' stroke-linejoin='round' stroke-width='2' d='M2 5l6 6 6-6'/%3e%3c/svg%3e");margin-bottom:10px;'> - <option value="0" <?= $selected["water"] === "out" ? "selected" : "" ?>>Usable outside of the water</option> - <option value="1" <?= $selected["water"] === "in" ? "selected" : "" ?>>Usable inside of the water</option> - <option value="2" <?= $selected["water"] === "both" ? "selected" : "" ?>>Usable both inside and outside</option> - <option value="3" <?= $selected["water"] === "playground" ? "selected" : "" ?>>Usable in a playground</option> - </select> - - <label style="margin-left:5px;"> - <input <?= ($selected["sexual"] ?? false) ? "checked" : "" ?> type="checkbox" name="sexual"> - Sexual toy - </label><br> - - <label style="margin-left:5px;"> - <input <?= ($selected["verified"] ?? false) ? "checked" : "" ?> <?= $_PROFILE['login'] !== "raindrops" ? "disabled" : "" ?> type="checkbox" name="verified"> - Mark as verified - </label><br> - - <label style="margin-left:5px;"> - <input <?= ($selected["untested"] ?? false) ? "checked" : "" ?> type="checkbox" name="untested"> - Mark as untested - </label> - - <hr> - - <textarea name="description" class="form-control" style="resize: none;color:white;background:#111;border-color:#222;margin-bottom:10px;" placeholder="Description"><?= strip_tags($selected["description"] ?? "") ?></textarea> - - <textarea placeholder="Toy usage" name="usage" class="form-control" style="resize: none;color:white;background:#111;border-color:#222;margin-bottom:10px;"><?= strip_tags($selected["usage"] ?? "") ?></textarea> - - <hr> - - <input type="text" placeholder="Keywords (comma-separated)" name="keywords" class="form-control" style="color:white;background:#111;border-color:#222;margin-bottom:10px;" value="<?= str_replace('"', '"', implode(",", $selected["keywords"] ?? [])) ?>"> - - <input type="text" placeholder="Instructions to craft IRL" name="irl" class="form-control" style="color:white;background:#111;border-color:#222;" value="<?= str_replace('"', '"', $selected["irl"] ?? "") ?>"> - - <div style="display:none;"> - <hr> - - <p>Select the groups of ponies who can use this toy:</p> - <?php - - $relations = []; - $actions = json_decode(file_get_contents($_SERVER['DOCUMENT_ROOT'] . "/includes/data/actions/actions.json"), true); - - foreach ($actions as $action) { - if ($action["type"] !== "sexual") continue; - - foreach ($action["ponies"] as $ponies) { - $id = implode("", $ponies["members"]); - - $member = getMemberWithoutSystem($ponies["members"][0]); - $otherMember = getMemberWithoutSystem($ponies["members"][1]); - - $parts = [ - $member["id"], - $otherMember["id"] - ]; - - asort($parts); - - $relations[implode("-", $parts)] = [ - "name" => getMiniName($member["display_name"] ?? $member["name"]) . " and " . getMiniName($otherMember["display_name"] ?? $otherMember["name"]), - "images" => [ - file_exists($_SERVER['DOCUMENT_ROOT'] . "/assets/uploads/pt-$member[name].png") ? "/assets/uploads/pt-$member[name].png" : "/assets/uploads/pt.png", - file_exists($_SERVER['DOCUMENT_ROOT'] . "/assets/uploads/pt-$otherMember[name].png") ? "/assets/uploads/pt-$otherMember[name].png" : "/assets/uploads/pt.png", - ] - ]; - } - } - - $inFileRelations = []; - $inFileDeprecations = []; - - foreach ($selected["ponies"] as $ponies) { - $inFileRelations[] = $ponies["members"][0] . "-" . $ponies["members"][1]; - - if (isset($ponies["deprecated"]) && $ponies["deprecated"]) $inFileDeprecations[] = $ponies["members"][0] . "-" . $ponies["members"][1]; - } - - foreach ($relations as $id => $relation): - ?> - <label style="display:block;" class="creator-relation <?= in_array($id, $inFileRelations) ? "checked" : "" ?>"> - <input <?= in_array($id, $inFileRelations) ? "checked" : "" ?> name="relations[<?= $id ?>][member]" style="display:none;" type="checkbox" class="checkbox-input"> - - <img style="vertical-align: middle;width:24px;height:24px;" src="<?= $relation["images"][0] ?>"> - <img style="vertical-align: middle;width:24px;height:24px;" src="<?= $relation["images"][1] ?>"> - <span style="vertical-align: middle;"><?= $relation["name"] ?></span> - - <label class="deprecated" style="display:none;margin-left: 20px;margin-top: 5px;"> - <input <?= in_array($id, $inFileDeprecations) ? "checked" : "" ?> name="relations[<?= $id ?>][deprecated]" type="checkbox"> - Mark as deprecated - </label> - </label> - <?php endforeach; ?></div> - - <br> - <input type="hidden" name="updateAction"> - <input type="hidden" name="action" value="<?= $selected["id"] ?>"> - <input type="submit" class="btn btn-primary" value="Save"> - </form> - <form method="post" style="display:inline;"> - <input type="hidden" name="deleteAction"> - <input type="hidden" name="action" value="<?= $selected["id"] ?>"> - <input type="submit" class="btn btn-danger" value="Delete"> - </form> - </div> - </div> - </div> - </div> - - <?php else: ?> - - <h2>Toys database</h2> - <p><?= count($data) ?> toys (<?= count(array_filter($data, function ($i) { - return $i["sexual"] === false; - })) ?> non-sexual, <?= count(array_filter($data, function ($i) { - return $i["sexual"] === true; - })) ?> sexual, <?= count(array_filter($data, function ($i) { - return isset($i["untested"]) && $i["untested"]; - })) ?> untested, <?= count(array_filter($data, function ($i) { - return (isset($i["description"]) && trim($i["description"]) === "") || !isset($i["description"]); - })) ?> incomplete)</p> - - <input type="text" placeholder="Search for a toy..." class="form-control" style="margin-bottom:15px;color:white;background:#111;border-color:#222;" onchange="search();" onkeydown="search();" onkeyup="search();" id="search"> - - <div id="list"> - <div class="list-group"> - <?php - - $init = []; - foreach ($data as $value) { - $init[$value["name"]] = $value; - } - - ksort($init); - - $sorted = array_values($init); - - foreach ($sorted as $item): ?> - <a href="/-/toys/<?= $item["id"] ?>" id="action-<?= $item["id"] ?>" style="display:grid;grid-template-columns: 1fr 0.2fr;" class="list-group-item list-group-item-action action-listing"> - <div> - <span class="<?= trim($item["description"]) === "" ? "text-danger" : "" ?>"><?= $item["name"] ?></span> - <?php if (!isset($item["verified"])): ?><span class="badge bg-warning rounded-pill text-black">Unverified</span><?php endif; ?> - <?php if (isset($item["untested"])): ?><span class="badge bg-info rounded-pill">Untested</span><?php endif; ?> - </div> - <!-- - <div> - <?php - - $uniquePonies = []; - $longPonyList = false; - - foreach ($item["ponies"] as $ponies) { - foreach ($ponies["members"] as $member) { - if (isset($uniquePonies[$member]) && !$uniquePonies[$member]) { - $uniquePonies[$member] = false; - } else { - $uniquePonies[$member] = $ponies["deprecated"]; - } - } - } - - if (count($uniquePonies) > 6) { - $longPonyList = true; - } - - $index = 1; - foreach ($uniquePonies as $name => $deprecated): if (!$deprecated): ?> - <span title="<?= getMemberWithoutSystem($name)["display_name"] ?? getMemberWithoutSystem($name)["display_name"] ?>" style="display: inline-block;<?= $longPonyList && $index % 2 === 0 ? "position:absolute;margin-left:-12px;z-index:" . (999 - $index) . ";" : "position:relative;z-index:" . (999 - $index) . ";" ?>"> - <img src="/assets/uploads/pt-<?= getMemberWithoutSystem($name)["name"] ?>.png" style="width:24px;"> - </span> - <?php $index++; endif; endforeach; ?> - <?php foreach ($uniquePonies as $name => $deprecated): if ($deprecated): ?> - <span title="<?= strip_tags(getMemberWithoutSystem($name)["display_name"] ?? getMemberWithoutSystem($name)["name"]) ?> (deprecated)" style="opacity:.5;display: inline-block;<?= $longPonyList && $index % 2 === 0 ? "position:absolute;margin-left:-12px;z-index:" . (999 - $index) . ";" : "position:relative;z-index:" . (999 - $index) . ";" ?>"> - <img src="/assets/uploads/pt-<?= getMemberWithoutSystem($name)["name"] ?>.png" style="width:24px;"> - </span> - <?php $index++; endif; endforeach; ?> - </div> - --> - <div style="text-align: right;"> - <?php if ($item["sexual"]): ?> - <span style="" class="badge rounded-pill bg-danger">Sexual</span> - <?php else: ?> - <span style="" class="badge rounded-pill bg-success">Pleasurable</span> - <?php endif; ?> - </div> - </a> - <?php endforeach; ?> - </div> - </div> - - <div id="search-results" class="list-group"></div> - - <div id="page-content"> - <hr> - <p>Not finding what you are looking for? <a onclick="event.target.blur(); document.getElementById('creator-title').focus();" href="#" data-bs-toggle="modal" data-bs-target="#creator">Add a toy.</a></p> - </div> - - <script> - window.actions = JSON.parse(atob(`<?= base64_encode(json_encode(array_values(json_decode(file_get_contents($_SERVER['DOCUMENT_ROOT'] . "/includes/data/toys/toys.json"), true)))) ?>`)); - </script> - - <div class="modal fade" id="creator"> - <div class="modal-dialog"> - <div class="modal-content"> - <div class="modal-header"> - <h4 class="modal-title">Add a new toy</h4> - <button type="button" class="btn-close" data-bs-dismiss="modal"></button> - </div> - - <div class="modal-body"> - <form method="post"> - <input id="creator-title" type="text" placeholder="Toy name" name="name" class="form-control" style="color:white;background:#111;border-color:#222;margin-bottom:10px;"> - <select name="water" class="form-select" style='color:white;background-color:#111;border-color:#222;background-image:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3e%3cpath fill='none' stroke='%23ffffff' stroke-linecap='round' stroke-linejoin='round' stroke-width='2' d='M2 5l6 6 6-6'/%3e%3c/svg%3e");margin-bottom:10px;'> - <option value="0" selected>Usable outside of the water</option> - <option value="1">Usable inside of the water</option> - <option value="2">Usable both inside and outside</option> - <option value="3">Usable in a playground</option> - </select> - - <label style="margin-left:5px;"> - <input type="checkbox" name="sexual"> - Sexual toy - </label> - - <div style="display: none;"> - <hr> - - <p>Select the groups of ponies who can use this toy:</p> - <?php - - $relations = []; - $actions = json_decode(file_get_contents($_SERVER['DOCUMENT_ROOT'] . "/includes/data/actions/actions.json"), true); - - foreach ($actions as $action) { - if ($action["type"] !== "sexual") continue; - - foreach ($action["ponies"] as $ponies) { - $id = implode("", $ponies["members"]); - - $member = getMemberWithoutSystem($ponies["members"][0]); - $otherMember = getMemberWithoutSystem($ponies["members"][1]); - - $parts = [ - $member["id"], - $otherMember["id"] - ]; - - asort($parts); - - $relations[implode("-", $parts)] = [ - "name" => getMiniName($member["display_name"] ?? $member["name"]) . " and " . getMiniName($otherMember["display_name"] ?? $otherMember["name"]), - "images" => [ - file_exists($_SERVER['DOCUMENT_ROOT'] . "/assets/uploads/pt-$member[name].png") ? "/assets/uploads/pt-$member[name].png" : "/assets/uploads/pt.png", - file_exists($_SERVER['DOCUMENT_ROOT'] . "/assets/uploads/pt-$otherMember[name].png") ? "/assets/uploads/pt-$otherMember[name].png" : "/assets/uploads/pt.png", - ] - ]; - } - } - - foreach ($relations as $id => $relation): - ?> - <label style="display:block;" class="creator-relation"> - <input name="relations[<?= $id ?>]" style="display:none;" type="checkbox" class="checkbox-input"> - - <img style="vertical-align: middle;width:24px;height:24px;" src="<?= $relation["images"][0] ?>"> - <img style="vertical-align: middle;width:24px;height:24px;" src="<?= $relation["images"][1] ?>"> - <span style="vertical-align: middle;"><?= $relation["name"] ?></span> - </label> - <?php endforeach; ?></div> - - <p style="margin-top:10px;">You can add additional data (description, how to use) after adding the toy.</p> - <input type="hidden" name="createAction"> - <input type="submit" class="btn btn-primary" value="Add"> - </form> - </div> - </div> - </div> - </div> - - <?php endif; ?> - </div> -</div> - -<!--suppress JSUnresolvedFunction --> -<script> - Array.from(document.getElementsByClassName("checkbox-input")).forEach((el) => { - el.onchange = () => { - let parent = el.parentElement; - - if (el.checked) { - parent.classList.add("checked"); - } else { - parent.classList.remove("checked"); - } - } - }); - - const fuse = new Fuse(window.actions, { - includeScore: true, - keys: [ - { - name: 'name', - weight: 1 - }, - { - name: 'description', - weight: 1 - }, - { - name: 'example', - weight: 0.7 - }, - { - name: 'irl', - weight: 0.5 - } - ] - }) - - function search() { - let query = document.getElementById("search").value; - let results = fuse.search(query).map((i) => { - return { - id: i.item.id, - score: i.score - }; - }); - - let unfiltered = results; - - results = results.filter((i) => { - return i.score < 0.7; - }); - - console.log("Before:", unfiltered, "After:", results); - - document.getElementById("list").style.display = "none"; - document.getElementById("search-results").style.display = "block"; - document.getElementById("search-results").innerHTML = ""; - - for (let result of results) { - document.getElementById("search-results").innerHTML += document.getElementById("action-" + result.id).outerHTML; - } - - console.log(results); - - if (query.trim() === "") { - document.getElementById("list").style.display = "block"; - document.getElementById("search-results").style.display = "none"; - } - } - - function changeMixed() { - let value = document.getElementById("editor-type").value; - console.log(value); - - if (value === "2") { - Array.from(document.getElementsByClassName("creator-relation")).forEach((el) => { - el.classList.add("mixed"); - }); - } else { - Array.from(document.getElementsByClassName("creator-relation")).forEach((el) => { - el.classList.remove("mixed"); - }); - } - } -</script> - -<style> - .modal-header { - border-bottom: 1px solid #353738; - } - - .modal-content { - border: 1px solid rgba(255, 255, 255, .2); - background-color: #111; - } - - .btn-close { - filter: invert(1); - } - - .creator-relation { - border-radius: 10px; - padding: 5px 10px; - opacity: .5; - } - - .creator-relation.checked { - background-color: rgba(255, 255, 255, .1); - opacity: 1; - } - - .creator-relation:hover { - background-color: rgba(255, 255, 255, .1); - } - - .creator-relation.checked:hover { - background-color: rgba(255, 255, 255, .25) !important; - } - - .creator-relation.checked .deprecated { - display: block !important; - } - - .creator-relation.mixed.checked .sexual { - display: block !important; - } - - .list-group-item { - color: #fff; - background-color: #222; - border: 1px solid rgba(255, 255, 255, .125); - } - - .list-group-item.disabled { - color: #fff; - background-color: #222; - border-color: rgba(255, 255, 255, .125); - opacity: .75; - } - - .list-group-item:hover { - background-color: #252525; - color: #ddd; - } - - .list-group-item:active, .list-group-item:focus { - background-color: #272727; - color: #bbb; - } - - @media (max-width: 991px) { - .action-listing { - grid-template-columns: 1fr !important; - text-align: center !important; - } - - .action-listing > * { - margin-bottom: 10px; - text-align: center !important; - } - - .action-listing > *:nth-last-child(1) { - margin-bottom: 0 !important; - } - - .action-listing img { - width: 32px !important; - } - } -</style> - -<?php require_once $_SERVER['DOCUMENT_ROOT'] . '/includes/footer.inc'; ?> diff --git a/pages/travelling.inc b/pages/travelling.inc index 46b1a7f..2064ce1 100644 --- a/pages/travelling.inc +++ b/pages/travelling.inc @@ -141,7 +141,7 @@ global $travelling; <?php if ($travelling[$member['id']]["travelling"] && $travelling[$member['id']]["equestria"]): ?> <img style="width:24px;" src="/assets/logo/equestria.png"> Equestria <?php else: ?> - <a class="member-link" href="/<?= $system === "gdapd" ? "raindrops" : "cloudburst" ?>"><img style="width:24px;border-radius:5px;" src="/assets/uploads/<?= $system === "gdapd" ? "raindrops" : "cloudburst" ?>.png"> <?= $system === "gdapd" ? "Raindrops" : "Cloudburst" ?> System</a> + <a class="member-link" href="/<?= $system === "gdapd" ? "raindrops" : "cloudburst" ?>"><img style="width:24px;border-radius:5px;" src="<?= getAsset($system) ?>"> <?= $system === "gdapd" ? "Raindrops" : "Cloudburst" ?> System</a> <?php endif; ?> <?php if ($travelling[$member['id']]["travelling"]): ?> <span class="text-muted">(<?= timeAgo($travelling[$member['id']]["history"][count($travelling[$member['id']]["history"]) - 1]["start"]) ?>)</span> |