diff --git a/create-critter.php b/create-critter.php
index d62db8f..f43ef8e 100644
--- a/create-critter.php
+++ b/create-critter.php
@@ -56,9 +56,11 @@ $pdo->exec('CREATE INDEX IF NOT EXISTS idx_critters_verb_id ON critters (verb_id
$pdo->exec('CREATE INDEX IF NOT EXISTS idx_critters_location_id ON critters (location_id)');
$pdo->exec('CREATE INDEX IF NOT EXISTS idx_critters_author_id ON critters (author_id)');
-function countCrittersCreatedToday(PDO $pdo): int
+function countCrittersCreatedTodayByAuthor(PDO $pdo, int $authorId): int
{
- return (int) $pdo->query("SELECT COUNT(*) FROM critters WHERE date(datetime) = date('now')")->fetchColumn();
+ $stmt = $pdo->prepare("SELECT COUNT(*) FROM critters WHERE author_id = :author_id AND date(datetime) = date('now')");
+ $stmt->execute(['author_id' => $authorId]);
+ return (int) $stmt->fetchColumn();
}
function secondsSinceLastCritterByAuthor(PDO $pdo, int $authorId): ?int
@@ -69,7 +71,7 @@ function secondsSinceLastCritterByAuthor(PDO $pdo, int $authorId): ?int
return $seconds === false ? null : (int) $seconds;
}
-$dailyLimitReached = countCrittersCreatedToday($pdo) >= DAILY_CRITTER_LIMIT;
+$dailyLimitReached = countCrittersCreatedTodayByAuthor($pdo, (int) $_SESSION['user_id']) >= DAILY_CRITTER_LIMIT;
$cooldownRemaining = 0;
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
@@ -157,7 +159,7 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST' && $userCredits > 0 && !$dailyLimitRea
}
}
- if (empty($errors) && countCrittersCreatedToday($pdo) >= DAILY_CRITTER_LIMIT) {
+ if (empty($errors) && countCrittersCreatedTodayByAuthor($pdo, (int) $_SESSION['user_id']) >= DAILY_CRITTER_LIMIT) {
$dailyLimitReached = true;
}
@@ -249,10 +251,6 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST' && $userCredits > 0 && !$dailyLimitRea
$output = $prediction['output'] ?? null;
$imageUrl = is_array($output) ? ($output[0] ?? null) : $output;
}
- } else {
- // The Replicate request never went through, so give the reserved credit back.
- $refundStmt = $pdo->prepare('UPDATE users SET credits = credits + 1 WHERE id = :id');
- $refundStmt->execute(['id' => $_SESSION['user_id']]);
}
$imageFilename = null;
@@ -282,6 +280,15 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST' && $userCredits > 0 && !$dailyLimitRea
}
}
+ if ($imageFilename === null) {
+ // Every unsuccessful path above (request failure, failed/canceled prediction,
+ // disallowed or missing image URL, oversized or non-image download) leaves
+ // $imageFilename null, so this single check refunds the reserved credit for
+ // all of them instead of only the initial request-failure case.
+ $refundStmt = $pdo->prepare('UPDATE users SET credits = credits + 1 WHERE id = :id');
+ $refundStmt->execute(['id' => $_SESSION['user_id']]);
+ }
+
$stmt = $pdo->prepare('INSERT INTO critters (noun_id, adjective_id, verb_id, location_id, author_id, image, datetime) VALUES (:noun_id, :adjective_id, :verb_id, :location_id, :author_id, :image, :datetime)');
$stmt->execute([
'noun_id' => $selected['noun_id'],
diff --git a/forgot-password.php b/forgot-password.php
index 98faed8..2b85f63 100644
--- a/forgot-password.php
+++ b/forgot-password.php
@@ -28,7 +28,7 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST') {
$user = $stmt->fetch(PDO::FETCH_ASSOC);
if ($user) {
- $token = createTicket((int) $user['id'], 'password_reset');
+ $token = createPasswordResetTicket($pdo, (int) $user['id']);
$appUrl = rtrim(getenv('APP_URL') ?: 'https://ourapp.local', '/');
$resetLink = $appUrl . '/reset-password.php?token=' . urlencode($token);
sendPasswordResetEmail($email, $user['username'], $resetLink);
diff --git a/lib/head.php b/lib/head.php
index 9875b9e..268febf 100644
--- a/lib/head.php
+++ b/lib/head.php
@@ -7,7 +7,7 @@
-
+