diff options
Diffstat (limited to 'includes')
-rw-r--r-- | includes/external/jobs/index.js | 26 | ||||
-rw-r--r-- | includes/external/matrix/index.js | 40 | ||||
-rw-r--r-- | includes/fragments/metadata.inc | 228 | ||||
-rw-r--r-- | includes/util/functions.inc | 6 |
4 files changed, 260 insertions, 40 deletions
diff --git a/includes/external/jobs/index.js b/includes/external/jobs/index.js index 39b7de5..0f44cc9 100644 --- a/includes/external/jobs/index.js +++ b/includes/external/jobs/index.js @@ -1,13 +1,21 @@ const fs = require('fs'); const child_process = require('child_process'); -let jobs = require('../../data/jobs.json'); +let jobsList = []; +let jobs = []; let history = require('../../data/history.json'); +fs.writeFileSync("../../data/running.json", "null"); + setInterval(() => { - if (JSON.stringify(JSON.parse(fs.readFileSync("../../data/jobs.json").toString())) !== JSON.stringify(jobs)) { + if (JSON.stringify(fs.readdirSync("../../data/jobs")) !== JSON.stringify(jobsList)) { console.log("Updating the jobs list..."); - jobs = JSON.parse(fs.readFileSync("../../data/jobs.json").toString()); + jobs = fs.readdirSync("../../data/jobs").map((i) => { + let obj = JSON.parse(fs.readFileSync("../../data/jobs/" + i).toString()); + obj["_id"] = i; + return obj; + }); + jobsList = fs.readdirSync("../../data/jobs"); } }, 1000); @@ -20,11 +28,13 @@ setTimeout(() => { console.log("\nRunning jobs:"); for (let job of jobs) { - console.log(" " + job.name); + console.log(" " + job.name + " [" + job._id + "]"); let output; let start; let end; + fs.writeFileSync("../../data/running.json", JSON.stringify(job._id)); + try { start = new Date(); output = child_process.execFileSync("php", [job.name + ".php", JSON.stringify(job.options)], { cwd: "../../jobs" }); @@ -37,8 +47,7 @@ setTimeout(() => { description = "," + name + "=" + JSON.stringify(job.options[name]); } - jobs.splice(jobs.indexOf(job), 1); - fs.writeFileSync("../../data/jobs.json", JSON.stringify(jobs)); + fs.unlinkSync("../../data/jobs/" + job._id); history.unshift({ completed: true, @@ -58,6 +67,7 @@ setTimeout(() => { history = history.slice(0, 200); fs.writeFileSync("../../data/history.json", JSON.stringify(history)); + fs.writeFileSync("../../data/running.json", "null"); } catch (e) { end = start ? new Date() : null; console.log(" Failed to process job"); @@ -70,8 +80,7 @@ setTimeout(() => { description = "," + name + "=" + JSON.stringify(job.options[name]); } - jobs.splice(jobs.indexOf(job), 1); - fs.writeFileSync("../../data/jobs.json", JSON.stringify(jobs)); + fs.unlinkSync("../../data/jobs/" + job._id); history.unshift({ completed: false, @@ -91,6 +100,7 @@ setTimeout(() => { history = history.slice(0, 200); fs.writeFileSync("../../data/history.json", JSON.stringify(history)); + fs.writeFileSync("../../data/running.json", "null"); } } diff --git a/includes/external/matrix/index.js b/includes/external/matrix/index.js index 5149005..1bfb8d4 100644 --- a/includes/external/matrix/index.js +++ b/includes/external/matrix/index.js @@ -1,5 +1,6 @@ const user = process.argv[2]; const info = require('../../app.json')['matrix'][user]; +const fs = require('fs'); if (typeof info !== "object") throw new Error("Unable to find info"); @@ -7,6 +8,7 @@ const token = info.token; const sdk = require("matrix-js-sdk"); const axios = require("axios"); +const child_process = require("child_process"); const client = sdk.createClient({ baseUrl: "https://chat.equestria.dev", accessToken: token, @@ -24,13 +26,16 @@ client.once("sync", async function (state, prevState, res) { console.log(fronters.members.length + " member(s) at front"); let name = system.name; - let avatar = system.avatar_url; + let avatar1 = system.avatar_url; + let avatar2 = null; - if (fronters.members.length === 1) { + if (fronters.members.length === 1 || (fronters.members.length === 2 && (fronters.members[0].name === "scootaloo" && fronters.members[1].name === "rainbowdash"))) { name = fronters.members[0].display_name ?? fronters.members[0].name; - avatar = fronters.members[0].avatar_url ?? avatar; - } else if (fronters.members.length >= 2) { + avatar1 = fronters.members[0].avatar_url ?? avatar1; + } else if (fronters.members.length >= 2 && !(fronters.members[0].name === "scootaloo" && fronters.members[1].name === "rainbowdash")) { name = (fronters.members[0].display_name ?? fronters.members[0].name) + " and " + (fronters.members[1].display_name ?? fronters.members[1].name); + avatar1 = fronters.members[0].avatar_url ?? avatar1; + avatar2 = fronters.members[1].avatar_url ?? avatar2; } await client.setDeviceDetails(info.device, { @@ -52,7 +57,32 @@ client.once("sync", async function (state, prevState, res) { }); console.log("Uploading avatar"); - let res = await client.uploadContent((await axios.get(avatar, {responseType: "arraybuffer"})).data); + let pfp; + + if (avatar2) { + let img1 = (await axios.get(avatar1, {responseType: "arraybuffer"})).data; + let img2 = (await axios.get(avatar2, {responseType: "arraybuffer"})).data; + + fs.writeFileSync("/tmp/chm-" + user + "-1", img1); + fs.writeFileSync("/tmp/chm-" + user + "-2", img2); + + child_process.execSync("convert /tmp/chm-" + user + "-1 -gravity center -crop 50%x100% /tmp/chm-" + user + "-1.webp"); + child_process.execSync("convert /tmp/chm-" + user + "-2 -gravity center -crop 50%x100% /tmp/chm-" + user + "-2.webp"); + child_process.execSync("montage -mode concatenate -tile x1 /tmp/chm-" + user + "-1.webp /tmp/chm-" + user + "-2.webp /tmp/chm-" + user + ".webp"); + + pfp = fs.readFileSync("/tmp/chm-" + user + ".webp"); + + fs.unlinkSync("/tmp/chm-" + user + "-1"); + fs.unlinkSync("/tmp/chm-" + user + "-2"); + fs.unlinkSync("/tmp/chm-" + user + "-1.webp"); + fs.unlinkSync("/tmp/chm-" + user + "-2.webp"); + fs.unlinkSync("/tmp/chm-" + user + ".webp"); + } else { + pfp = (await axios.get(avatar1, {responseType: "arraybuffer"})).data; + } + + let res = await client.uploadContent(pfp); + await axios.put("https://chat.equestria.dev/_matrix/client/r0/profile/%40" + user + "%3Aequestria.dev/avatar_url", { avatar_url: res.content_uri }, { diff --git a/includes/fragments/metadata.inc b/includes/fragments/metadata.inc index 0d2187c..719abbc 100644 --- a/includes/fragments/metadata.inc +++ b/includes/fragments/metadata.inc @@ -6,9 +6,51 @@ if (file_exists($_SERVER['DOCUMENT_ROOT'] . "/includes/data/metadata/" . $member ?> +<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); + } + + .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; + } + + .member-link, .list-group-item-action { + cursor: pointer !important; + } +</style> + <br> -<div class="container" id="page-content"> - <h2><a href="/<?= $memberData["name"] ?>"><?= $memberData["display_name"] ?? $memberData["name"] ?></a></h2> +<div class="container"> + <h2 id="page-content"><a href="/<?= $memberData["name"] ?>"><?= $memberData["display_name"] ?? $memberData["name"] ?></a></h2> <?php if (file_exists($_SERVER['DOCUMENT_ROOT'] . "/includes/data/metadata/" . $memberID . ".json")): ?> <form> <input name="submit" type="hidden"> @@ -94,28 +136,166 @@ if (file_exists($_SERVER['DOCUMENT_ROOT'] . "/includes/data/metadata/" . $member <h3>Relationships</h3> - <?php if ($systemID !== $app["other"]["id"]): ?> - <p> - <b>Sexfriends (full IDs, comma-separated)</b><br> - <input name="sexfriends" class="form-control" style="filter: invert(1) hue-rotate(180deg);" type="text" value="<?= implode(", ", $metadata["sexfriends"]) ?>"> - </p> - <?php endif; ?> - <p> - <b>Marefriends (full IDs, comma-separated)</b><br> - <input name="marefriends" class="form-control" style="filter: invert(1) hue-rotate(180deg);" type="text" value="<?= implode(", ", $metadata["marefriends"]) ?>"> - </p> - <p> - <b>Sisters (full IDs, comma-separated)</b><br> - <input name="sisters" class="form-control" style="filter: invert(1) hue-rotate(180deg);" type="text" value="<?= implode(", ", $metadata["sisters"]) ?>"> - </p> - <p> - <b>Caretakers (full IDs, comma-separated)</b><br> - <input name="caretakers" class="form-control" style="filter: invert(1) hue-rotate(180deg);" type="text" value="<?= implode(", ", $metadata["caretakers"]) ?>"> - </p> - <p> - <b>Friends (full IDs, comma-separated)</b><br> - <input name="friends" class="form-control" style="filter: invert(1) hue-rotate(180deg);" type="text" value="<?= implode(", ", $metadata["friends"] ?? []) ?>"> - </p> + <div class="modal" id="new-relation" 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 a new <span id="new-relation-type">-</span> for <?= $memberData["display_name"] ?? $memberData["name"] ?></h4> + <button id="new-fronter-close" type="button" class="btn-close" data-bs-dismiss="modal"></button> + </div> + + <div class="modal-body"> + <input type="text" placeholder="Search for a pony..." class="form-control" style="margin-bottom:15px;color:white;background:#111;border-color:#222;" id="search"> + + <div id="list"> + <div class="list-group"> + <?php foreach (scoreOrderGlobal() as $member): ?> + <a id="list-pony-<?= $member['id'] ?>" onclick="confirmAdd('<?= $member['system'] ?>/<?= $member['id'] ?>');" class="new-fronter-link list-group-item list-group-item-action"><img src="<?= getAsset($member["system"], $member["id"], "heads") ?>" style="width:24px;"> <?= $member["display_name"] ?? $member["name"] ?></a> + <?php endforeach; ?> + </div> + </div> + + <div id="search-results" class="list-group"></div> + </div> + + </div> + </div> + </div> + + <script src="/assets/editor/fuse.js"></script> + <script> + window.modal = new bootstrap.Modal(document.getElementById("new-relation")); + window.currentSelectedValue = null; + + function openAddDialog(value, text) { + modal.show(); + window.currentSelectedValue = value; + document.getElementById("new-relation-type").innerText = text; + document.getElementById("search").value = ""; search({}); + document.getElementById("search").focus(); + } + + window.poniesList = JSON.parse(atob(`<?= base64_encode(json_encode(array_values(scoreOrderGlobal()))) ?>`)); + window.avatars = JSON.parse(atob(`<?php + + $avatars = []; + + foreach (scoreOrderGlobal() as $pony) { + $avatars[$pony["system"] . "/" . $pony["id"]] = getAsset($pony["system"], $pony["id"]); + } + + echo(base64_encode(json_encode($avatars))); ?>`)) + + const fuse = new Fuse(window.poniesList, { + includeScore: true, + keys: [ + { + name: 'name', + weight: 1 + }, + { + name: 'display_name', + weight: 1 + }, + { + name: 'id', + weight: 0.7 + }, + { + name: 'species', + weight: 0.5 + } + ] + }) + + function search(event) { + if (event.key === "Enter") { + return; + } + + 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) { + if (document.getElementById("list-pony-" + result.id)) document.getElementById("search-results").innerHTML += document.getElementById("list-pony-" + result.id).outerHTML; + } + + console.log(results); + + if (query.trim() === "") { + document.getElementById("list").style.display = "block"; + document.getElementById("search-results").style.display = "none"; + } + } + + document.getElementById("search").onchange = document.getElementById("search").onkeyup = document.getElementById("search").onkeydown = search; + + document.getElementById("search").addEventListener("keydown", (event) => { + if (event.key === "Enter") { + document.querySelector("#search-results .new-fronter-link").click(); + event.preventDefault(); + } + }); + + function update(type) { + document.getElementById(type + "-list").innerHTML = document.getElementsByName(type)[0].value.split(",").map(i => i.trim()).filter(i => i && i.trim() !== "").map(i => ` + <a style="margin-top: 4px;" class="btn btn-dark" onclick="deleteRelation('${type}', '${i}');"> + <img src="${window.avatars[i]}" style="width: 24px; vertical-align: middle; border-radius: 999px;"> + <span style="vertical-align: middle; margin-left: 5px;">${window.poniesList.filter(j => j.id === i.split("/")[1])[0]['display_name'] ?? window.poniesList.filter(j => j.id === i.split("/")[1])[0]['name']}</span> + </a> + `).join(""); + } + + function confirmAdd(item) { + document.getElementsByName(window.currentSelectedValue)[0].value += ", " + item; + update(window.currentSelectedValue); + window.currentSelectedValue = null; + modal.hide(); + } + + function deleteRelation(type, relation) { + let relations = document.getElementsByName(type)[0].value.split(",").map(i => i.trim()).filter(i => i && i !== ""); + relations = relations.filter(i => i !== relation); + document.getElementsByName(type)[0].value = relations.join(", "); + update(type); + } + </script> + + <?php foreach ([ + $systemID !== $app["other"]["id"] ? [ "sexfriends", "Sexfriends" ] : null, + [ "marefriends", "Marefriends", "marefriend" ], + [ "sisters", "Sisters", "sister" ], + [ "caretakers", "Caretakers", "caretaker" ], + [ "friends", "Friends", "friend" ], + ] as $relations): if (isset($relations)): ?> + <p> + <b><?= $relations[1] ?></b><br> + <input name="<?= $relations[0] ?>" type="hidden" value="<?= implode(", ", $metadata[$relations[0]] ?? []) ?>"> + <span id="<?= $relations[0] ?>-list"></span> + <a style="margin-top: 4px;" class="btn btn-secondary" onclick="openAddDialog('<?= $relations[0] ?>', '<?= $relations[2] ?>')">+</a> + <script> + update('<?= $relations[0] ?>'); + </script> + </p> + <?php endif; endforeach; ?> <hr> diff --git a/includes/util/functions.inc b/includes/util/functions.inc index 79a47c6..fe97980 100644 --- a/includes/util/functions.inc +++ b/includes/util/functions.inc @@ -3,17 +3,17 @@ require_once $_SERVER['DOCUMENT_ROOT'] . "/includes/util/score.inc"; require_once $_SERVER['DOCUMENT_ROOT'] . "/includes/util/bitset.inc"; require_once $_SERVER['DOCUMENT_ROOT'] . "/includes/util/homepage.inc"; +require_once $_SERVER['DOCUMENT_ROOT'] . "/includes/util/random.inc"; if (!function_exists("createJob")) { function createJob($title, $options) { - $jobs = json_decode(file_get_contents($_SERVER['DOCUMENT_ROOT'] . "/includes/data/jobs.json"), true); - $jobs[] = [ + $job = [ "name" => $title, "options" => $options, "date" => date('c') ]; - file_put_contents($_SERVER['DOCUMENT_ROOT'] . "/includes/data/jobs.json", json_encode($jobs)); + file_put_contents($_SERVER['DOCUMENT_ROOT'] . "/includes/data/jobs/" . round(microtime(true) * 1000) . "-" . random() . ".json", json_encode($job)); } } |