Compare commits

...

10 commits

25 changed files with 582 additions and 426 deletions

View file

@ -1,4 +1,10 @@
trinkey's fork of [notfire's qna](https://git.notfire.cc/notfire/qna)
has the same functionality but i added custom css support and made the code less messy
---
to set up, generally:
- make a database in postgres
- set up config.php based off of the example
- run `php setup.php` to create the database table
- run `php setup.php` to create the database table

View file

@ -1,3 +1,3 @@
- modifying whether a cw is used or not?
- POSSIBLY editing messages / changing their visibility? idk
- some way to automatically get notified
- some way to automatically get notified

View file

@ -4,74 +4,76 @@ $query = "
SELECT * FROM data;
";
$qresp = pg_query($db, $query);
$queryResponse = pg_query($db, $query);
$questions = pg_fetch_all($queryResponse);
asort($questions);
$rows = pg_fetch_all($qresp);
$properTitle = "{$pageTitle} — admin";
$CSSdownDirectory = 1;
include "../boilerplate/pageStart.php";
include "../boilerplate/question.php";
$totalUnresponded = 0;
$totalPriv = 0;
$totalRespondedPub = 0;
foreach (array_reverse($rows) as $i) {
if ($i["isrespondedto"] === "f" && $i["ispublic"] === "t") {
$totalUnresponded++;
} else if ($i["ispublic"] === "f") {
$totalPriv++;
} else {
$totalRespondedPub++;
}
}
echo("<h2 class=\"title\">" . $pageTitle . " admin</h2>");
echo("<h2 class=\"title\"> {$pageTitle} &mdash; admin</h2>");
if ($_GET["deleted"] == 1) {
echo("<span class=\"sentconf\">deleted!</span>");
echo("<div class=\"sentconf\">deleted!</div>");
}
if ($_GET["responded"] == 1) {
echo("<span class=\"sentconf\">response sent!</span>");
echo("<div class=\"sentconf\">response sent!</div>");
}
asort($rows);
if ($_GET["read"] == 1) {
echo("<div class=\"sentconf\">marked as read!</div>");
}
echo("<h3 class=\"sect\">not responded to ({$totalUnresponded})</h3>");
foreach (array_reverse($rows) as $i){
if ($i["isrespondedto"] === "f" && $i["ispublic"] == "t") {
echo("<div class=\"question\">");
if ($i["iscwed"] === "t") {
echo("<details><summary>cw: " . $i["cw"] . "</summary><span class=\"cwfiller\"></span>");
}
echo(htmlspecialchars($i["text"]));
echo("<div class=\"time\">" . $i["time"] . "</div>");
echo("<a class=\"permalink\" href=\"index.php?page=respond&id=" . $i["id"] . "&pw={$adminPassword}\">respond</a> / <a class=\"permalink\" href=\"index.php?page=delete&id=" . $i["id"] . "&pw={$adminPassword}\">delete</a></div>");
if ($_GET["unread"] == 1) {
echo("<div class=\"sentconf\">marked as unread!</div>");
}
if ($_GET["migrated"] == 1) {
echo("<div class=\"sentconf\">migrations have been run!</div>");
}
$totalUnresponded = 0;
$totalPriv = 0;
$totalPrivRead = 0;
$totalRespondedPub = 0;
$unresponded = "";
$private = "";
$privateRead = "";
$responded = "";
foreach (array_reverse($questions) as $question) {
if ($question["isrespondedto"] === "f" && $question["ispublic"] === "t") {
$totalUnresponded++;
$unresponded .= getQuestion($question, 0, 1, 0, $adminPassword);
} else if ($question["ispublic"] === "f") {
if ($question["isprivread"] === "t") {
$totalPrivRead++;
$privateRead .= getQuestion($question, 0, 1, 0, $adminPassword);
} else {
$totalPriv++;
$private .= getQuestion($question, 0, 1, 0, $adminPassword);
}
} else {
$totalRespondedPub++;
$responded .= getQuestion($question, 0, 1, 0, $adminPassword);
}
}
echo("<h3 class=\"sect\">private ({$totalPriv})</h3>");
foreach (array_reverse($rows) as $i){
if ($i["ispublic"] === "f") {
echo("<div class=\"question\">");
if ($i["iscwed"] === "t") {
echo("<details><summary>cw: " . $i["cw"] . "</summary><span class=\"cwfiller\"></span>");
}
echo(htmlspecialchars($i["text"]));
echo("<div class=\"time\">" . $i["time"] . "</div>");
echo("<a class=\"permalink\" href=\"index.php?page=delete&id=" . $i["id"] . "&pw={$adminPassword}\">delete</a></div>");
}
}
echo("
<h3 class=\"sect\">not responded to ({$totalUnresponded})</h3>
{$unresponded}
<h3 class=\"sect\">unread private ({$totalPriv})</h3>
{$private}
<h3 class=\"sect\">public ({$totalRespondedPub})</h3>
{$responded}
<h3 class=\"sect\">read private ({$totalPrivRead})</h3>
{$privateRead}
");
echo("<h3 class=\"sect\">public ({$totalRespondedPub})</h3>");
foreach (array_reverse($rows) as $i){
if ($i["ispublic"] === "t" && $i["isrespondedto"] === "t") {
echo("<div class=\"question\">");
if ($i["iscwed"] === "t") {
echo("<details><summary>cw: " . $i["cw"] . "</summary><span class=\"cwfiller\"></span>");
}
echo(htmlspecialchars($i["text"]));
echo("<div class=\"time\">" . $i["time"] . "</div>");
echo("<div class=\"response\">" . htmlspecialchars($i["responsetext"]) . "");
echo("<div class=\"time\">" . $i["responsetime"] . "</div></div>");
echo("<a class=\"permalink\" href=\"index.php?page=respond&responded=1&id=" . $i["id"] . "&pw={$adminPassword}\">edit response</a> / <a class=\"permalink\" href=\"index.php?page=delete&id=" . $i["id"] . "&pw={$adminPassword}\">delete</a></div>");
}
}
include '../boilerplate/pageEnd.php';
?>
?>

View file

@ -1,9 +1,9 @@
<?php
$id = $_GET["id"];
$id = (int)$_GET["id"];
if ($id === null) {
exit();
exit();
}
$query = "
@ -13,8 +13,6 @@ WHERE id = {$id};
pg_query($db, $query);
echo("done");
header("Location: index.php?deleted=1&pw={$adminPassword}");
?>
?>

View file

@ -5,31 +5,43 @@ SELECT * FROM data
WHERE id = {$id};
";
$qresp = pg_query($db, $query);
$arr = pg_fetch_array($qresp);
$queryResponse = pg_query($db, $query);
$question = pg_fetch_array($queryResponse);
$url = "{$pageProto}://" . $_SERVER["HTTP_HOST"] . $pagePath . "/fetch.php?id={$id}";
if (strlen($question["fedipostid"]) == 0) {
$method = "POST";
$route = $fediAPIRoute;
} else {
$method = "PUT";
$route = $fediAPIRoute . "/" . $question["fedipostid"];
}
$cw = "anonymous question response (automated)";
if ($question["iscwed"] == "t") {
$cw .= "; cw: {$question['cw']}";
}
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL,$fediAPIRoute);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_HTTPHEADER,
array("Authorization: {$fediAPIToken}"));
curl_setopt($ch, CURLOPT_HTTPHEADER, array("Authorization: {$fediAPIToken}"));
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_URL, $route);
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, $method);
curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query(array(
"status" => "question: {$question['text']}\n\nresponse: {$question['responsetext']}\n\nlink: {$url}",
"visibility" => $fediVisibility,
"spoiler_text" => $cw
)));
$contentO = $arr["text"];
$contentR = $arr["responsetext"];
$url = "{$pageProto}://" . $_SERVER["HTTP_HOST"] . $pagePath . "/fetch.php?id={$id}";
if ($arr["iscwed"] == "t") {
$contentCW = $arr["cw"];
curl_setopt($ch, CURLOPT_POSTFIELDS,
http_build_query(array('status' => "question: {$contentO}\n\nresponse: {$contentR}\n\nlink: {$url}", 'visibility' => "{$fediVisibility}", 'spoiler_text' => "anonymous question response (automated); cw: {$contentCW}")));
} else {
curl_setopt($ch, CURLOPT_POSTFIELDS,
http_build_query(array('status' => "question: {$contentO}\n\nresponse: {$contentR}\n\nlink: {$url}", 'visibility' => "{$fediVisibility}", 'spoiler_text' => "anonymous question response (automated)")));
$resp = curl_exec($ch);
if (strlen($question["fedipostid"]) == 0) {
$jsonResp = json_decode($resp, true);
$fediID = $jsonResp["id"];
pg_update($db, "data", array("fedipostid" => $fediID), array("id" => $id));
}
curl_exec($ch);
curl_close($ch);
?>
?>

View file

@ -2,19 +2,25 @@
include '../config.php';
echo("<link rel=\"stylesheet\" href=\"../css/admin.css\">");
if ($_GET["pw"] === $adminPassword) {
if ($_GET["page"] === "delete") {
include 'delete.php';
} elseif ($_GET["page"] === "respond") {
include 'respond.php';
} else {
include 'all.php';
}
switch ($_GET["page"]) {
case "delete": include "delete.php"; break;
case "respond": include "respond.php"; break;
case "mark": include "mark.php"; break;
case "migrate": include "migrate.php"; break;
default: include "all.php";
}
} else {
echo("<h2 class=\"sect\">enter password</h2>");
echo("<form class=\"frm\" action=\"index.php\"><input id=\"passinput\" name=\"pw\" required=\"\"><br><button class=\"submitbutton\" type=\"submit\">login</button></form>");
$properTitle = $pageTitle . " &mdash; sign in";
$CSSdownDirectory = 1;
include "../boilerplate/pageStart.php";
echo("
<h2 class=\"sect\">enter password</h2>
<form class=\"frm\" action=\"index.php\"><input id=\"passinput\" name=\"pw\" required=\"\"><br><button class=\"submitbutton\" type=\"submit\">login</button></form>
");
include "../boilerplate/pageEnd.php";
}
?>
?>

29
admin/mark.php Normal file
View file

@ -0,0 +1,29 @@
<?php
$id = (int)$_GET["id"];
if ($id === null) {
exit();
}
if ($_GET["action"] === "unread") {
$query = "
UPDATE data
SET isprivread = False
WHERE id = {$id};
";
$headerinfo = "Location: index.php?unread=1&pw={$adminPassword}";
} else if ($_GET["action"] === "read") {
$query = "
UPDATE data
SET isprivread = True
WHERE id = {$id};
";
$headerinfo = "Location: index.php?read=1&pw={$adminPassword}";
}
pg_query($db, $query);
header($headerinfo);
?>

26
admin/migrate.php Normal file
View file

@ -0,0 +1,26 @@
<?php
$query = "
SELECT * FROM migrations;
";
$queryResponse = pg_query($db, $query);
$rows = pg_fetch_all($queryResponse);
$migrations = array(
"20240218-AddMigrationsTable-40641e8d",
"20240218-AddMarkReadOption-a7e43358",
"20240218-AddFalsesToPrivRead-67d82b18",
"20250310-AddFediIDColumn-64520350"
);
foreach ($migrations as $mig) {
if (!in_array($mig, array_column($rows, 'id'))) {
include "../migrations/{$mig}.php";
}
}
header("Location: index.php?migrated=1&pw={$adminPassword}");
?>

View file

@ -1,29 +1,30 @@
<?php
$id = $_GET["id"];
$id = (int)$_GET["id"];
if ($id === null) {
exit();
exit();
}
if ($_GET["text"] !== null) {
$text = $_GET["text"];
$cdate = date("Y-m-d H:i:sP");
$query = "
UPDATE data
SET \"responsetime\" = timestamptz'{$cdate}', isrespondedto = True
WHERE id = {$id};
";
$text = $_GET["text"];
$cdate = date("Y-m-d H:i:sP");
pg_query($db, $query);
$query = "
UPDATE data
SET \"responsetime\" = timestamptz'{$cdate}', isrespondedto = True
WHERE id = {$id};
";
pg_update($db, "data", array("responsetext" => $text), array("id" => $id));
pg_query($db, $query);
pg_update($db, "data", array("responsetext" => $text), array("id" => $id));
if ($fediEnabled) {
include 'fedi.php';
}
if ($fediEnabled) {
include "fedi.php";
}
header("Location: index.php?responded=1&pw={$adminPassword}");
header("Location: index.php?responded=1&pw={$adminPassword}");
exit();
}
$query = "
@ -31,33 +32,27 @@ SELECT * FROM data
WHERE id = {$id};
";
$qresp = pg_query($db, $query);
$arr = pg_fetch_array($qresp);
$queryResponse = pg_query($db, $query);
$question = pg_fetch_array($queryResponse);
echo("<link rel=\"stylesheet\" href=\"css/indiv.css\">");
$properTitle = $pageTitle . " &mdash; respond to question #" . $id;
$CSSdownDirectory = 1;
include "../boilerplate/pageStart.php";
include "../boilerplate/question.php";
if ($arr["ispublic"] === "f") {
echo("<h2 class=\"title\">{$pageTitle} no such question exists</h2>");
echo("<a class=\"goback\" href=\"index.php\">(go back?)</a>");
http_response_code(404);
if ($question["ispublic"] === "f") {
echo("
<h2 class=\"title\">{$pageTitle} &mdash; no such question exists</h2>
<a class=\"go-back\" href=\"index.php\">(go back?)</a>
");
http_response_code(404);
} else {
echo("<h2 class=\"title\">{$pageTitle} question number " . $arr["id"] . "</h2>");
echo("<a class=\"goback\" href=\"index.php?pw={$adminPassword}\">(go back?)</a>");
echo("<div class=\"question\">");
if ($arr["iscwed"] === "t") {
echo("<h3>cw: " . $arr["cw"] . "</h3>");
}
echo(htmlspecialchars($arr["text"]));
echo("<div class=\"time\">" . $arr["time"] . "</div>");
if ($_GET["responded"] == 1) {
echo("<div class=\"response\">" . htmlspecialchars($arr["responsetext"]) . "");
echo("<div class=\"time\">" . $arr["responsetime"] . "</div></div>");
echo("<h3>enter your edits</h3>");
} else {
echo("<h3>enter a response</h3>");
}
echo("<form class=\"frm\" action=\"index.php\"><input hidden name=\"id\" value=\"{$id}\"><input hidden name=\"page\" value=\"respond\"><input hidden name=\"pw\" value=\"{$adminPassword}\"><input id=\"passinput\" name=\"text\" required=\"\"><br><button class=\"submitbutton\" type=\"submit\">send</button></form>");
echo("
<h2 class=\"title\">{$pageTitle} &mdash; question number {$question['id']}</h2>
<a class=\"go-back\" href=\"index.php?pw={$adminPassword}\">(go back?)</a>
");
echo(getQuestion($question, 0, 0, 1, $adminPassword));
}
?>
?>

2
boilerplate/pageEnd.php Normal file
View file

@ -0,0 +1,2 @@
</body>
</html>

14
boilerplate/pageStart.php Normal file
View file

@ -0,0 +1,14 @@
<!DOCTYPE html>
<html>
<head>
<title><?php echo($properTitle) ?></title>
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="stylesheet" href="<?php if ($CSSdownDirectory) { echo("../"); } ?>css/base.css">
<?php
if ($customCSSurl) {
echo("<link rel=\"stylesheet\" href=\"" . $customCSSurl . "\">");
}
?>
</head>
<body>

87
boilerplate/question.php Normal file
View file

@ -0,0 +1,87 @@
<?php
function getQuestion(
$question,
$includePermalink=1,
$isAdmin=0,
$isResponding=0,
$adminPassword=""
) {
$q = htmlspecialchars($question["text"]);
$q .= "<div class=\"time\">{$question['time']}</div>";
if ($question["responsetext"]) {
$q .= "<div class=\"response\">" . htmlspecialchars($question['responsetext']);
$q .= "<div class=\"time\">{$question['responsetime']}</div></div>";
}
if ($isResponding) {
if ($question["responsetext"]) {
$q .= "<h3>enter your edits</h3>";
} else {
$q .= "<h3>enter a response</h3>";
}
$q .= "
<form class=\"frm\" action=\"index.php\">
<input hidden name=\"id\" value=\"{$question['id']}\">
<input hidden name=\"page\" value=\"respond\">
<input hidden name=\"pw\" value=\"{$adminPassword}\">
<input id=\"passinput\" name=\"text\" value=\"{$question['responsetext']}\" autofocus required><br>
<button class=\"submitbutton\" type=\"submit\">send</button>
</form>
";
}
if ($includePermalink === 1) {
$q .= "<a class=\"permalink\" href=\"fetch.php?id={$question['id']}\">permalink</a>";
}
if ($isAdmin === 1) {
if ($question["ispublic"] === "t") {
$q .= "<a class=\"permalink\" href=\"index.php?page=respond&id={$question['id']}&pw={$adminPassword}\">";
if ($question["isrespondedto"] === "t") {
$q .= "edit response";
} else {
$q .= "respond";
}
$q .= "</a>";
} else {
$q .= "<a class=\"permalink\" href=\"index.php?page=mark&action=";
if ($question["isprivread"] === "t") {
$q .= "unread";
} else {
$q .= "read";
}
$q .= "&id={$question['id']}&pw={$adminPassword}\">mark ";
if ($question["isprivread"] === "t") {
$q .= "unread";
} else {
$q .= "read";
}
$q .= "</a>";
}
$q .= " / <a class=\"permalink\" href=\"index.php?page=delete&id={$question['id']}&pw={$adminPassword}\">delete</a>";
}
if ($question["iscwed"] === "t") {
$open = "";
if ($isResponding) {
$open = " open";
}
$q = "<details{$open}><summary>cw: " . htmlspecialchars($question["cw"]) . "</summary>{$q}</details>";
}
return "<div class=\"question\">{$q}</div>";
}
?>

View file

@ -1,7 +1,7 @@
<?php
// timezone (valid ones: https://www.php.net/manual/en/timezones.php)
date_default_timezone_set('America/New_York');
date_default_timezone_set("America/New_York");
// admin
$adminPassword = "setAPasswordHere!123";
@ -11,16 +11,20 @@ $pageTitle = "the cool qna";
$pageDomainEnabled = True;
$pageProto = "https";
$pagePath = "/qna";
$pageDomain = "example.com";
$pageDomainOther = $pageDomain; // you can comment out and change this to a subdomain you want to "go back to". eg your site is me.example.org but you want it to say example.org
//$pageDomainOther = "me.example.com";
$pageRoot = "/"; // path to go to
// set this to the url of any custom css
$customCSSurl = NULL;
// post to fedi?
$fediEnabled = False;
$fediAPIRoute = "https://example.com/api/v1/statuses";
$fediAPIToken = "Bearer AUTHTOKENGOESHERE";
$fediVisibility = "private";
$fediVisibility = "private"; // "direct", "private", "unlisted", "public"
// database setup
$dbHost = "localhost";
@ -28,9 +32,8 @@ $dbName = "postgres";
$dbUsername = "postgres";
$dbPassword = "postgres";
// !!! DON'T CHANGE ANYTHING AFTER THIS UNLESS YOU KNOW WHAT YOU'RE DOING !!!
$dbInfo = "host={$dbHost} dbname={$dbName} user={$dbUsername} password={$dbPassword}";
$db = pg_connect($dbInfo);
?>
?>

View file

@ -1,82 +0,0 @@
body {
background-image: url(https://notfire.cc/design/images/groundback.gif);
background-color: black;
color: white;
font-family: Arial, Helvetica, sans-serif;
}
.permalink {
color: #ff0000;
font-size: .9em;
}
.goback {
color: #ff0000;
}
.title {
margin-bottom: .1em;
}
.question {
margin-top: .7em;
background-color: #2c2c2c;
border-radius: 5px;
max-width: fit-content;
padding: .5em;
}
.response {
background-color: #505050;
border-radius: 5px;
margin-top: .3em;
padding: .4em;
margin-bottom: .25em;
}
.time {
font-size: .8em;
}
.cwfiller {
height: 1.3em;
display: inline-block;
}
.sect {
margin-top: .2em;
margin-bottom: .2em;
}
.sentconf {
color: lime;
margin-bottom: .3em;
}
.sendsum {
font-size: 1.17em;
font-weight: bold;
}
.sendmsg {
margin-top: 1em;
border-radius: 5px;
background-color: #2c2c2c;
max-width: fit-content;
padding: .7em;
}
#passinput, .submitbutton {
background-color: black;
color: white;
margin-bottom: .3em;
}
.submitbutton {
font-size: 1.17em;
margin-top: .3em;
}
.frm {
margin-bottom: 0px;
}

99
css/base.css Normal file
View file

@ -0,0 +1,99 @@
:root {
--background-color: #000000;
--text-color: #ffffff;
--hr-color: #808080;
--link-color: #ff0000;
--confirmation-color: #00ff00;
--question-background: #2c2c2c;
--response-background: #505050;
/* set to "none" to disable the background image */
--background-image: url("https://notfire.cc/design/images/groundback.gif");
--font-family: Arial, Helvetica, sans-serif;
}
body {
background-image: var(--background-image);
background-color: var(--background-color);
color: var(--text-color);
font-family: var(--font-family);
}
hr {
border: none;
height: 1.5px;
background-color: var(--hr-color);
}
.permalink {
color: var(--link-color);
font-size: .9em;
}
.go-back {
color: var(--link-color);
}
.title {
margin-bottom: .1em;
}
.question {
margin-top: .7em;
background-color: var(--question-background);
border-radius: 5px;
max-width: fit-content;
padding: .5em;
}
.response {
background-color: var(--response-background);
border-radius: 5px;
margin-top: .3em;
padding: .4em;
}
.time {
font-size: .8em;
}
.sect {
margin-top: .2em;
margin-bottom: .2em;
}
.sentconf {
color: var(--confirmation-color);
margin-bottom: .3em;
}
.sendsum {
font-size: 1.17em;
font-weight: bold;
}
.sendmsg {
margin-top: 1em;
border-radius: 5px;
background-color: var(--question-background);
max-width: fit-content;
padding: .7em;
}
#passinput,
#questioninput,
#cwinput,
.submitbutton {
background-color: var(--background-color);
color: var(--text-color);
margin-bottom: .3em;
}
.submitbutton {
font-size: 1.17em;
margin-top: .3em;
}
.frm {
margin-bottom: 0px;
}

View file

@ -1,38 +0,0 @@
body {
background-image: url(https://notfire.cc/design/images/groundback.gif);
background-color: black;
color: white;
font-family: Arial, Helvetica, sans-serif;
}
.goback {
color: #ff0000;
}
.title {
margin-bottom: .1em;
}
.question {
margin-top: .7em;
background-color: #2c2c2c;
border-radius: 5px;
max-width: fit-content;
padding: .5em;
}
.response {
background-color: #505050;
border-radius: 5px;
margin-top: .3em;
padding: .4em;
}
.time {
font-size: .8em;
}
.cwfiller {
height: 1.3em;
display: inline-block;
}

View file

@ -1,83 +0,0 @@
body {
background-image: url(https://notfire.cc/design/images/groundback.gif);
background-color: black;
color: white;
font-family: Arial, Helvetica, sans-serif;
}
.permalink {
color: #ff0000;
font-size: .9em;
}
.goback {
color: #ff0000;
}
.title {
margin-bottom: .1em;
}
.question {
margin-top: .7em;
background-color: #2c2c2c;
border-radius: 5px;
max-width: fit-content;
padding: .5em;
}
.response {
background-color: #505050;
border-radius: 5px;
margin-top: .3em;
padding: .4em;
margin-bottom: .25em;
}
.time {
font-size: .8em;
}
.cwfiller {
height: 1.3em;
display: inline-block;
}
.sect {
margin-bottom: .2em;
margin-top: .2em;
}
.sentconf {
color: lime;
margin-top: .3em;
margin-bottom: .3em;
}
.sendsum {
font-size: 1.17em;
font-weight: bold;
}
.sendmsg {
margin-top: 1em;
border-radius: 5px;
background-color: #2c2c2c;
max-width: fit-content;
padding: .7em;
}
#questioninput, #cwinput, .submitbutton {
background-color: black;
color: white;
margin-bottom: .3em;
}
.submitbutton {
font-size: 1.17em;
margin-top: .3em;
}
.frm {
margin-bottom: 0px;
}

View file

@ -1,11 +1,12 @@
<?php
include 'config.php';
include "config.php";
include "boilerplate/question.php";
$id = $_GET["id"];
$id = (int)$_GET["id"];
if ($id === null) {
exit();
exit();
}
$query = "
@ -13,27 +14,28 @@ SELECT * FROM data
WHERE id = {$id};
";
$qresp = pg_query($db, $query);
$arr = pg_fetch_array($qresp);
$queryResponse = pg_query($db, $query);
$question = pg_fetch_array($queryResponse);
echo("<link rel=\"stylesheet\" href=\"css/indiv.css\">");
$properTitle = "{$pageTitle} &mdash; question #{$id}";
include "boilerplate/pageStart.php";
if (pg_num_rows($qresp) === 0 || $arr["ispublic"] === "f" || $arr["isrespondedto"] === "f") {
echo("<h2 class=\"title\">{$pageTitle} no such question exists</h2>");
echo("<a class=\"goback\" href=\"index.php\">(go back?)</a>");
http_response_code(404);
if (pg_num_rows($queryResponse) === 0 || $question["ispublic"] === "f" || $question["isrespondedto"] === "f") {
echo("
<h2 class=\"title\">{$pageTitle} &mdash; no such question exists</h2>
<a class=\"go-back\" href=\"index.php\">(go back?)</a>
");
http_response_code(404);
} else {
echo("<h2 class=\"title\">{$pageTitle} question number " . $arr["id"] . "</h2>");
echo("<a class=\"goback\" href=\"index.php\">(go back?)</a>");
echo("<div class=\"question\">");
if ($arr["iscwed"] === "t") {
echo("<details><summary>cw: " . $arr["cw"] . "</summary><span class=\"cwfiller\"></span>");
}
echo(htmlspecialchars($arr["text"]));
echo("<div class=\"time\">" . $arr["time"] . "</div>");
echo("<div class=\"response\">" . $arr["responsetext"] . "");
echo("<div class=\"time\">" . $arr["responsetime"] . "</div></div></div>");
echo("
<h2 class=\"title\">{$pageTitle} &mdash; question number {$question['id']}</h2>
<a class=\"go-back\" href=\"index.php\">(go back?)</a>
");
echo(getQuestion($question));
}
?>
include "boilerplate/pageEnd.php";
?>

View file

@ -1,49 +1,56 @@
<?php
include 'config.php';
include "config.php";
include "boilerplate/question.php";
$query = "
SELECT * FROM data;
SELECT * FROM data
WHERE ispublic=true
AND isrespondedto=true;
";
$qresp = pg_query($db, $query);
$queryResponse = pg_query($db, $query);
$questions = pg_fetch_all($queryResponse);
asort($questions);
$rows = pg_fetch_all($qresp);
echo("<link rel=\"stylesheet\" href=\"css/main.css\">");
$properTitle = "{$pageTitle} &mdash; all messages";
include "boilerplate/pageStart.php";
echo("<h2 class=\"title\">" . $pageTitle . "</h2>");
if ($pageDomainEnabled) {
echo("<a class=\"goback\" href=\"https://{$pageDomainOther}{$pageRoot}\">(go back to " . $pageDomain . "?)</a>");
echo("<a class=\"go-back\" href=\"https://{$pageDomainOther}{$pageRoot}\">(go back to " . $pageDomain . "?)</a>");
}
if ($_GET["sent"] == 1) {
echo("<span class=\"sentconf\"><br>message sent!</span>");
echo("<span class=\"sentconf\"><br>message sent!</span>");
}
echo("<div class=\"sendmsg\"><details open=\"\"><summary class=\"sendsum\">send a message!</summary>");
?>
echo("<form class=\"frm\" action=\"send.php\"><label for=\"questioninput\">enter your message: </label><input id=\"questioninput\" name=\"text\" required=\"\"><br><label for=\"cwinput\">cw if applicable: </label><input id=\"cwinput\" name=\"cw\"><br><input type=\"checkbox\" id=\"pubbox\" name=\"public\" value=\"1\" checked> <label for=\"pubbox\">if this is checked, your message will be available publicly</label><br><button class=\"submitbutton\" type=\"submit\">send!</button></form></details></div>");
<div class="sendmsg">
<details open>
<summary class="sendsum">send a message!</summary>
<form class="frm" action="send.php">
<label for="questioninput">enter your message: </label>
<input id="questioninput" name="text" required><br>
<label for="cwinput">cw if applicable: </label>
<input id="cwinput" name="cw"><br>
<input type="checkbox" id="pubbox" name="public" value="1" checked>
<label for="pubbox">if this is checked, your message will be available publicly</label><br>
<button class="submitbutton" type="submit">send!</button>
</form>
</details>
</div>
<hr>
<h3 class="sect">all past messages</h3>
echo("<hr>");
<?php
echo("<h3 class=\"sect\">all past messages</h3>");
asort($rows);
foreach (array_reverse($rows) as $i){
if ($i["ispublic"] === "t" && $i["isrespondedto"] === "t") {
echo("<div class=\"question\">");
if ($i["iscwed"] === "t") {
echo("<details><summary>cw: " . $i["cw"] . "</summary><span class=\"cwfiller\"></span>");
}
echo(htmlspecialchars($i["text"]));
echo("<div class=\"time\">" . $i["time"] . "</div>");
echo("<div class=\"response\">" . htmlspecialchars($i["responsetext"]) . "");
echo("<div class=\"time\">" . $i["responsetime"] . "</div></div>");
echo("<a class=\"permalink\" href=\"fetch.php?id=" . $i["id"] . "\">permalink</a></div>");
}
foreach (array_reverse($questions) as $question){
echo(getQuestion($question));
}
?>
include "boilerplate/pageEnd.php";
?>

View file

@ -0,0 +1,19 @@
<?php
// ensure already private messages still get shown
$query = "
UPDATE data
SET isprivread = False
WHERE ispublic IS FALSE;
";
pg_query($db, $query);
$dataArray = array(
"id" => "20240218-AddFalsesToPrivRead-67d82b18"
);
pg_insert($db, "migrations", $dataArray);
?>

View file

@ -0,0 +1,18 @@
<?php
// add "isprivread" to data columns
$query = "
ALTER TABLE data
ADD COLUMN isprivread BOOLEAN;
";
pg_query($db, $query);
$dataArray = array(
"id" => "20240218-AddMarkReadOption-a7e43358"
);
pg_insert($db, "migrations", $dataArray);
?>

View file

@ -0,0 +1,19 @@
<?php
// add migrations table to track migrations that have been run
$query = "
CREATE TABLE migrations (
id TEXT NOT NULL
);
";
pg_query($db, $query);
$dataArray = array(
"id" => "20240218-AddMigrationsTable-40641e8d"
);
pg_insert($db, "migrations", $dataArray);
?>

View file

@ -0,0 +1,18 @@
<?php
// add "fedipostid" column to data
$query = "
ALTER TABLE data
ADD COLUMN fedipostid TEXT;
";
pg_query($db, $query);
$dataArray = array(
"id" => "20250310-AddFediIDColumn-64520350"
);
pg_insert($db, "migrations", $dataArray);
?>

View file

@ -1,36 +1,22 @@
<?php
include 'config.php';
include "config.php";
if ($_GET["text"] === null) {
exit();
exit();
}
if ($_GET["cw"] === null || $_GET["cw"] === "") {
$iscw = False;
} else {
$iscw = True;
}
if ($_GET["public"] == 1) {
$isPublic = True;
} else {
$isPublic = False;
}
$curTime = date("Y-m-d H:i:sP");
$dataArray = array(
"text" => $_GET["text"],
"cw" => $_GET["cw"],
"iscwed" => $iscw,
"time" => $curTime,
"ispublic" => $isPublic,
"isrespondedto" => False
"text" => $_GET["text"],
"cw" => $_GET["cw"],
"iscwed" => !($_GET["cw"] === null || $_GET["cw"] === ""),
"time" => date("Y-m-d H:i:sP"),
"ispublic" => $_GET["public"] == 1,
"isrespondedto" => False
);
pg_insert($db, "data", $dataArray);
header("Location: index.php?sent=1");
?>
?>

View file

@ -1,23 +1,34 @@
<?php
include 'config.php';
include "config.php";
$query = "
CREATE TABLE data (
id SERIAL PRIMARY KEY,
text TEXT NOT NULL,
cw TEXT,
iscwed BOOLEAN NOT NULL,
time TIMESTAMPTZ NOT NULL,
ispublic BOOLEAN NOT NULL,
isrespondedto BOOLEAN NOT NULL,
responsetext TEXT,
responsetime TIMESTAMPTZ
id SERIAL PRIMARY KEY,
text TEXT NOT NULL,
cw TEXT,
iscwed BOOLEAN NOT NULL,
time TIMESTAMPTZ NOT NULL,
ispublic BOOLEAN NOT NULL,
isrespondedto BOOLEAN NOT NULL,
responsetext TEXT,
responsetime TIMESTAMPTZ,
isprivread BOOLEAN
);
";
pg_query($db, $query);
$query = "
CREATE TABLE migrations (
id TEXT NOT NULL
);
";
pg_query($db, $query);
include "admin/migrate.php";
echo "database set up";
?>
?>