Files
dx4/backend-php/api.php
T
2026-09-03 21:07:15 +03:00

595 lines
21 KiB
PHP
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<?php
include 'k-api.php';
function db()
{
$pdo = new PDO('sqlite:./data.db');
$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
return $pdo;
};
function findClosestDateSort(array $array, string $targetDate)
{
if (empty($array) || !preg_match('/^\d{1,2}-\d{1,2}-\d{2}$/', $targetDate)) {
return null;
}
$targetDateTime = DateTime::createFromFormat('d-m-y', $targetDate);
if ($targetDateTime === false) return null;
$targetTimestamp = $targetDateTime->getTimestamp();
$result = null;
$maxTimestamp = null;
foreach ($array as $item) {
$itemDateTime = DateTime::createFromFormat('d-m-y', $item['fromDate']);
if ($itemDateTime === false) continue;
$itemTimestamp = $itemDateTime->getTimestamp();
if ($itemTimestamp <= $targetTimestamp && ($maxTimestamp === null || $itemTimestamp > $maxTimestamp)) {
$maxTimestamp = $itemTimestamp;
$result = $item;
}
}
return $result ?: ['content' => '[]'];
}
function getDayOfWeek(string $date)
{
$p = explode('-', $date);
if (count($p) !== 3) throw new InvalidArgumentException('DD-MM-YY|YYYY');
[$d, $m, $y] = $p;
if (strlen($y) === 2) $y = '20' . $y;
$dt = DateTime::createFromFormat('Y-m-d', "$y-$m-$d");
if (!$dt) throw new InvalidArgumentException('Invalid date');
return (int)$dt->format('N') - 1; // 0=Mon ... 6=Sun
}
function joinArraysByKey(array $primaryArray, array $secondaryArray, bool $doNotOverwrite = false, string $key = 'num'): array
{
// Index secondary array once for O(1) lookups
$indexedArray = array_column($secondaryArray, null, $key);
$result = [];
foreach ($primaryArray as $item) {
if (!isset($item[$key])) {
$result[] = $item;
continue;
}
$currentKey = $item[$key];
if (isset($indexedArray[$currentKey])) {
// Merge based on $doNotOverwrite flag
$result[] = $doNotOverwrite
? array_merge($indexedArray[$currentKey], $item) // Primary values take precedence
: array_merge($item, $indexedArray[$currentKey]); // Secondary values take precedence
} else {
$result[] = $item;
}
}
return $result;
}
function FastDBReq(PDO $db, string $sql, array $params = []): array
{
try {
$stmt = $db->prepare($sql);
$stmt->execute($params);
return $stmt->fetchAll(PDO::FETCH_ASSOC);
} catch (PDOException $e) {
throw $e;
}
}
CreateApi(function ($api) {
if (file_exists('./api.lock')) {
http_response_code(500);
$f = fopen('./api.lock', 'r') or die("server eгor");
$fs = filesize('./api.lock');
if ($fs == 0) {
$cnt = "";
} else {
$cnt = fread($f, $fs);
}
fclose($f);
die($cnt);
}
$api->useUpdates(db());
$api->on('/', 'GET', function () {
return 'dengi';
});
$api->on('/login', 'POST', function ($req) {
if (!isset($req->data['classId'])) {
$req->res->code(400);
return "class is empty";
}
$classId = substr(strtoupper($req->data['classId']), 0, 10);
// according docs (UPPERCASE, MIN 3 MAX 10)
$db = db();
$results = FastDBReq($db, "SELECT classid, userclassname FROM classes WHERE classid = ?", [$classId]);
if (count($results) != 0) {
return $results[0];
} else {
$req->res->code(400);
return "класс $classId не найден";
}
});
$api->on('/get_class_user_f', 'POST', function ($req) {
if (!isset($req->data['classId'])) {
$req->res->code(400);
return "";
}
$classId = substr(strtoupper($req->data['classId']), 0, 10);
// according docs (UPPERCASE, MIN 3 MAX 10)
$db = db();
$results = FastDBReq($db, "SELECT userclassname FROM classes WHERE classid = ?", [$classId]);
if (count($results) != 0) {
return $results[0];
} else {
$req->res->code(400);
return;
}
});
$api->on('/get_admin_user_f', 'POST', function ($req) {
if (!isset($req->data['adminId'])) {
$req->res->code(400);
return "";
}
$adminId = $req->data['adminId'];
$db = db();
$results = FastDBReq($db, "SELECT adminName FROM admins where adminid = ?", [$adminId]);
if (count($results) != 0) {
return $results[0];
} else {
$req->res->code(400);
return;
}
});
$api->on('/get_admin_level', 'POST', function ($req) {
if (!isset($req->data['adminId'])) {
$req->res->code(400);
return "";
}
$adminId = $req->data['adminId'];
$db = db();
$results = FastDBReq($db, "SELECT adminPrems FROM admins where adminid = ?", [$adminId]);
if (count($results) != 0) {
return $results[0];
} else {
$req->res->code(400);
return;
}
});
$api->on('/admin_login', 'POST', function ($req) {
if (!isset($req->data['adminId'])) {
$req->res->code(400);
return "admin is empty";
}
$adminId = $req->data['adminId'];
$db = db();
$results = FastDBReq($db, "SELECT * FROM admins WHERE adminid = ?", [$adminId]);
if (count($results) != 0) {
return $results[0];
} else {
$req->res->code(400);
return "админ не найден";
}
});
$api->on('/req_client_schedule', 'POST', function ($req) {
// NOTE: THIS IS SCHEDULE FOR USER (SHOULD BE WITH CHANGES AND CALLS)
// types = [0 - default schedule, 1 - with schedule changes, 2 - with schedule and rings]
if (!$req->hasData(['classId', 'day'])) {
$req->res->code(400);
return "net dannih";
}
$classId = substr(strtoupper($req->data['classId']), 0, 10);
$day = $req->data['day'];
if (!preg_match('/\d{1,2}-\d{1,2}-(\d{2}|\d{4})$/', $day)) return "wrong date format";
$db = db();
$results = FastDBReq($db, "SELECT content FROM changes WHERE classId = ? AND forDay = ?", [$classId, $day]);
if (count($results) > 0) {
// return only changes
$content = json_decode($results[0]['content'], true);
$has_full_rings = true;
foreach ($content as $_idx => $item) {
if (!isset($item['t-begin']) || !isset($item['t-end'])) {
$has_full_rings = false;
// optionally record $idx
break;
}
}
if ($has_full_rings) {
// with rings
return ['data' => $content, 'type' => 2];
} else {
// without rings
$results = FastDBReq($db, "SELECT content, fromDate FROM RINGS WHERE classId = ?", [$classId]);
$rings = json_decode(findClosestDateSort($results, $day)['content'], true);
$out = $content;
if ($rings !== null) {
$out = joinArraysByKey($content, $rings, true);
}
return ['data' => $out, 'type' => 1];
}
} else {
// return shedules + calls
$dayOfWeek = getDayOfWeek($day);
$results = FastDBReq($db, "SELECT content, fromDate FROM schedules WHERE classId = ? AND dayOfWeek = ?", [$classId, $dayOfWeek]);
if (count($results) > 0) {
$out = [];
$schedule = json_decode(findClosestDateSort($results, $day)['content'], true);
$results = FastDBReq($db, "SELECT content, fromDate FROM RINGS WHERE classId = ?", [$classId]);
$rings = json_decode(findClosestDateSort($results, $day)['content'], true);
$out = $schedule;
if ($rings !== null) {
$out = joinArraysByKey($schedule, $rings);
}
return ['data' => $out, 'type' => 0];
} else {
return ['data' => []];
}
}
});
$api->on('/editor_data', "POST", function ($req) {
if (!$req->hasData(['tab', 'day', 'adminId'])) {
$req->res->code(400);
return "bad data";
}
$adminId = $req->data['adminId'];
$db = db();
$results = FastDBReq($db, "SELECT adminClass FROM admins WHERE adminId=?", [$adminId]);
if (count($results) == 0) {
$req->res->code(400);
return "админ не найден";
# end
}
$classId = $results[0]['adminClass'];
$day = $req->data['day'];
$tab = intval($req->data['tab']);
$changes = null;
$schedule = [];
$rings = [];
if ($tab != 2) {
if ($tab == 0) {
$results = FastDBReq($db, "SELECT content FROM changes WHERE classId = ? AND forDay = ?", [$classId, $day]);
if (count($results) > 0) {
$changes = json_decode($results[0]['content'], true);
}
}
$dayOfWeek = getDayOfWeek($day);
$results = FastDBReq($db, "SELECT content, fromDate FROM schedules WHERE classId = ? AND dayOfWeek = ?", [$classId, $dayOfWeek]);
if (count($results) > 0) {
$schedule = json_decode(findClosestDateSort($results, $day)['content'], true);
}
} else {
$results = FastDBReq($db, "SELECT content, fromDate FROM RINGS WHERE classId = ?", [$classId]);
if (count($results) > 0) {
$rings = json_decode(findClosestDateSort($results, $day)['content'], true);
}
}
switch ($tab) {
case 0:
if ($changes === null) { // type check!!!
return $schedule;
} else {
return $changes;
}
case 1:
return $schedule;
case 2:
return $rings;
default:
return "tab not found dengi dengi";
}
});
$api->on(
"/editor_publish",
"POST",
function ($req) {
if (!$req->hasData(['adminId', 'tab', 'day', 'newData'])) {
$req->res->code(400);
return "bad data";
}
$adminId = $req->data['adminId'];
$db = db();
$results = FastDBReq($db, "SELECT adminClass FROM admins WHERE adminId=?", [$adminId]);
if (count($results) == 0) {
$req->res->code(400);
return "админ не найден";
# end
}
$classId = $results[0]['adminClass'];
$day = $req->data['day'];
$tab = intval($req->data['tab']);
$newDataRaw = $req->data['newData'];
$newData = json_decode($newDataRaw, true);
switch ($tab) {
case 0: // changes
// first get rasp and compare
// if no chnages skip, else publish
$dayOfWeek = getDayOfWeek($day);
$results = FastDBReq($db, "SELECT fromDate, content FROM schedules WHERE classId = ? AND dayOfWeek = ?", [$classId, $dayOfWeek]);
$publish = true;
if (count($results) > 0) {
$schedule = json_decode(findClosestDateSort($results, $day)['content'], true);
if ($newData === $schedule) { // position sentensive
$publish = false;
}
}
if ($publish) {
// removing changes for today if they are exists
$results = FastDBReq($db, "SELECT content FROM changes WHERE classId = ? AND forDay = ?", [$classId, $day]);
if (count($results) > 0) {
$changes = json_decode($results[0]['content'], true);
if ($newData === $changes) {
// already present
return true;
}
FastDBReq($db, "DELETE FROM changes WHERE forDay = ? AND classId = ?", [$day, $classId]); // SCARY 💀💀💀
}
// creating new
FastDBReq($db, 'INSERT INTO changes VALUES (?, ?, ?)', [$classId, $day, $newDataRaw]);
return true;
}
return false;
case 1: // rasp
$dayOfWeek = getDayOfWeek($day);
// FIXME: im to lazy to find if closest rasp are the same
FastDBReq($db, 'DELETE FROM schedules WHERE classId=? AND fromDate=?', [$classId, $day]);
FastDBReq($db, 'INSERT INTO schedules VALUES (?,?,?,?)', [$classId, $day, $dayOfWeek, $newDataRaw]);
return true;
case 2: // rigns
//same
FastDBReq($db, 'DELETE FROM rings WHERE classId=? AND fromDate=?', [$classId, $day]);
FastDBReq($db, 'INSERT INTO rings VALUES (?,?,?)', [$classId, $day, $newDataRaw]);
return true;
default:
return "tab not found dengi dengi";
}
}
);
$api->on('/editor_fullitems_del', "POST", function ($req) {
// SCARY!!!!!!
// LEVEL 10000000
// 💀💀💀💀💀
if (!$req->hasData(['tab', 'day', 'adminId'])) {
$req->res->code(400);
return "bad data";
}
$adminId = $req->data['adminId'];
$db = db();
$results = FastDBReq($db, "SELECT adminClass FROM admins WHERE adminId=?", [$adminId]);
if (count($results) == 0) {
$req->res->code(400);
return "админ не найден";
# end
}
$classId = $results[0]['adminClass'];
$day = $req->data['day'];
$tab = intval($req->data['tab']);
switch ($tab) {
case 0:
FastDBReq($db, "DELETE FROM changes WHERE forDay = ? AND classId = ?", [$day, $classId]);
break;
case 1:
FastDBReq($db, 'DELETE FROM schedules WHERE classId=? AND fromDate=?', [$classId, $day]);
break;
case 2:
FastDBReq($db, 'DELETE FROM rings WHERE classId=? AND fromDate=?', [$classId, $day]);
break;
default:
return "you saved your live because you didn't know what tabs are here";
}
return true;
});
$api->on('/update_admin', "POST", function ($req) {
if (!$req->hasData(['adminId', 'action'])) {
$req->res->code(400);
return "bad data";
}
$adminId = $req->data['adminId'];
$withSelf = true;
$action = $req->data['action'];
if (isset($req->data['person'])) {
$withSelf = false;
}
$adminId = $req->data['adminId'];
$db = db();
$results = FastDBReq($db, "SELECT adminPrems FROM admins WHERE adminId=?", [$adminId]);
if (count($results) == 0) {
$req->res->code(400);
return "админ не найден";
}
if (!$withSelf && !in_array($results[0]['adminPrems'], [-1, 2])) {
$req->res->code(400);
return 'нету прав';
}
if ($withSelf) {
switch ($action) {
case "change_name":
if (!isset($req->data['value'])) {
$req->res->code(400);
return "bad data";
}
$value = trim($req->data['value']);
if (strlen($value) == 0) {
$req->res->code(400);
return "bad data";
}
try {
FastDBReq($db, 'UPDATE admins SET adminName = ? WHERE adminId = ?', [$value, $adminId]);
} catch (PDOException) {
return "egor";
}
break;
}
} else {
$person = $req->data['person'];
switch ($action) {
case "change_name":
if (!isset($req->data['value'])) {
$req->res->code(400);
return "bad data";
}
$value = trim($req->data['value']);
if (strlen($value) == 0) {
$req->res->code(400);
return "bad data";
}
try {
FastDBReq($db, 'UPDATE admins SET adminName = ? WHERE adminId = ?', [$value, $person]);
} catch (PDOException) {
return "egor";
}
break;
default:
return "?";
}
}
return true;
});
$api->on('/classprofile_view', "POST", function ($req) {
if (!$req->hasData(['adminId'])) {
$req->res->code(400);
return "bad data";
}
$adminId = $req->data['adminId'];
$db = db();
$results = FastDBReq($db, "SELECT adminPrems, adminClass FROM admins WHERE adminId=?", [$adminId]);
if (count($results) == 0) {
$req->res->code(400);
return "админ не найден";
}
if (!in_array($results[0]['adminPrems'], [-1, 2])) {
$req->res->code(400);
return "недостаточно прав";
}
$classId = $results[0]['adminClass'];
$results = FastDBReq($db, "SELECT classid FROM classes WHERE classid=?", [$classId]);
if (count($results) == 0) {
$req->res->code(400);
return "класса не существует";
}
$classData = $results[0];
$adminsData = FastDBReq($db, "SELECT * FROM admins WHERE adminClass=?", [$classId]);
return ["status" => 1, "class" => $classData, "admins" => $adminsData];
});
$api->on('/classprofile_edit', "POST", function ($req) {
if (!$req->hasData(['adminId', 'action'])) {
$req->res->code(400);
return "bad data";
}
$adminId = $req->data['adminId'];
$db = db();
$results = FastDBReq($db, "SELECT adminPrems, adminClass FROM admins WHERE adminId=?", [$adminId]);
if (count($results) == 0) {
$req->res->code(400);
return "админ не найден";
}
if (!in_array($results[0]['adminPrems'], [-1, 2])) {
$req->res->code(400);
return "недостаточно прав";
}
$classId = $results[0]['adminClass'];
$action = $req->data['action'];
switch ($action) {
case 'update_name':
try {
if (!isset($req->data['value'])) {
$req->res->code(400);
return "bad data";
}
$value = trim($req->data['value']);
if (strlen($value) == 0) {
$req->res->code(400);
return "bad data";
}
FastDBReq($db, "UPDATE classes SET userclassname = ? WHERE classid=?", [$value, $classId]);
return true;
} catch (PDOException $e) {
error_log($e);
return "егор";
}
break;
case 'create_admin':
if (!isset($req->data['value'])) {
$req->res->code(400);
return "bad data";
}
$value = trim($req->data['value']);
if (strlen($value) == 0 || !str_contains($value, ';')) {
$req->res->code(400);
return "bad data";
}
$value = explode(';', $value);
if (sizeof($value) != 2) {
$req->res->code(400);
return 'bad data';
}
$n_adminId = $value[0];
$n_adminName = base64_decode($value[1]);
try {
FastDBReq($db, "INSERT INTO admins (adminId,adminName,adminClass,adminPrems) VALUES (?,?,?,?)", [$n_adminId, $n_adminName, $classId, 1]);
return true;
} catch (PDOException) {
$req->res->code(500);
return "ошибка";
}
case "delete_admin":
if (!isset($req->data['value'])) {
$req->res->code(400);
return "bad data";
}
$person = trim($req->data['value']);
if (strlen($person) == 0) {
$req->res->code(400);
return "bad data";
}
FastDBReq($db, "DELETE FROM admins WHERE adminId=?", [$person]);
return true;
default:
return "?";
}
});
});