старое + новое + проломил башку

This commit is contained in:
Arsen Mirzaev Tatyano-Muradovich 2023-12-21 23:10:18 +07:00
parent 78ec4bb359
commit b925ebe64e
11 changed files with 103 additions and 77 deletions

0
.gitignore vendored Normal file → Executable file
View File

0
LICENSE Normal file → Executable file
View File

0
README.md Normal file → Executable file
View File

0
composer.json Normal file → Executable file
View File

0
composer.lock generated Normal file → Executable file
View File

View File

View File

@ -30,36 +30,61 @@ function authorization(string $id): _document|null|false
{ {
global $arangodb; global $arangodb;
if (collection::init($arangodb->session, 'telegram')) if (collection::init($arangodb->session, 'telegram')) {
if ( if ($telegram = collection::search($arangodb->session, sprintf("FOR d IN telegram FILTER d.id == '%s' RETURN d", $id))) {
($telegram = collection::search($arangodb->session, sprintf("FOR d IN telegram FILTER d.id == '%s' RETURN d", $id)))
|| $telegram = collection::search(
$arangodb->session,
sprintf(
"FOR d IN telegram FILTER d._id == '%s' RETURN d",
document::write($arangodb->session, 'telegram', ['id' => $id, 'status' => 'inactive'])
)
)
)
if ($telegram->number === null) return null; if ($telegram->number === null) return null;
else if ( else if (
$telegram->status === 'active' $telegram->active
&& collection::init($arangodb->session, 'workers') && collection::init($arangodb->session, 'account')
&& $worker = collection::search( && $account = collection::search(
$arangodb->session, $arangodb->session,
sprintf( sprintf(
"FOR d IN workers LET e = (FOR e IN connections FILTER e._to == '%s' RETURN e._from)[0] FILTER d._id == e RETURN d", "FOR d IN account FILTER d.number == '%s' RETURN d",
$telegram->number,
$telegram->getId() $telegram->getId()
) )
) )
) return $worker; ) return $account;
else return false; else return false;
else throw new exception('Не удалось найти или создать аккаунт'); }
else throw new exception('Не удалось инициализировать коллекцию'); } else throw new exception('Не удалось инициализировать коллекцию');
return false; return false;
} }
/**
* Сотрудник
*
* @param string $id Идентификатор аккаунта
*
* @return _document|null|false (инстанция аккаунта, если подключен и авторизован; null, если не подключен; false, если подключен но неавторизован)
*/
function worker(string $id): _document|null|false
{
global $arangodb;
return collection::search(
$arangodb->session,
sprintf(
<<<'AQL'
FOR d IN worker
LET e = (
FOR e IN account_edge_worker
FILTER e._from == '%s'
SORT e.created DESC, e._key DESC
LIMIT 1
RETURN e
)
FILTER d._id == e[0]._to && d.active == true
SORT d.created DESC, d._key DESC
LIMIT 1
RETURN d
AQL,
$id
)
);
}
function registration(string $id, string $number): bool function registration(string $id, string $number): bool
{ {
global $arangodb; global $arangodb;
@ -71,49 +96,52 @@ function registration(string $id, string $number): bool
// Запись номера // Запись номера
$telegram->number = $number; $telegram->number = $number;
if (!document::update($arangodb->session, $telegram)) return false; if (!document::update($arangodb->session, $telegram)) return false;
} else if (!collection::search( } else if (
$number === null
|| !$telegram = collection::search(
$arangodb->session, $arangodb->session,
sprintf( sprintf(
"FOR d IN telegram FILTER d._id == '%s' RETURN d", "FOR d IN telegram FILTER d._id == '%s' RETURN d",
document::write($arangodb->session, 'telegram', ['id' => $id, 'status' => 'inactive', 'number' => $number]) document::write($arangodb->session, 'telegram', ['id' => $id, 'active' => false, 'number' => $number])
) )
)) return false; )
) return false;
// Инициализация ребра: workers -> telegram // Инициализация ребра: account -> telegram
if ( if (
collection::init($arangodb->session, 'workers') collection::init($arangodb->session, 'account')
&& ($worker = collection::search( && ($account = collection::search(
$arangodb->session, $arangodb->session,
sprintf( sprintf(
"FOR d IN workers FILTER d.phone == '%d' RETURN d", "FOR d IN account FILTER d.number == '%d' RETURN d",
$telegram->number $telegram->number
) )
)) ))
&& collection::init($arangodb->session, 'connections', true) && collection::init($arangodb->session, 'connection', true)
&& (collection::search( && (collection::search(
$arangodb->session, $arangodb->session,
sprintf( sprintf(
"FOR d IN connections FILTER d._from == '%s' && d._to == '%s' RETURN d", "FOR d IN connection FILTER d._from == '%s' && d._to == '%s' RETURN d",
$worker->getId(), $account->getId(),
$telegram->getId() $telegram->getId()
) )
) )
?? collection::search( ?? collection::search(
$arangodb->session, $arangodb->session,
sprintf( sprintf(
"FOR d IN connections FILTER d._id == '%s' RETURN d", "FOR d IN connection FILTER d._id == '%s' RETURN d",
document::write( document::write(
$arangodb->session, $arangodb->session,
'connections', 'connection',
['_from' => $worker->getId(), '_to' => $telegram->getId()] ['_from' => $account->getId(), '_to' => $telegram->getId()]
) )
) )
)) ))
) { ) {
// Инициализировано ребро: workers -> telegram // Инициализировано ребро: account -> telegram
// Активация // Активация
$telegram->status = 'active'; $telegram->active = true;
return document::update($arangodb->session, $telegram); return document::update($arangodb->session, $telegram);
} }
} else throw new exception('Не удалось инициализировать коллекцию'); } else throw new exception('Не удалось инициализировать коллекцию');
@ -137,10 +165,10 @@ function generateAuthenticationKeyboard(): array
function generateMenu(Context $ctx): void function generateMenu(Context $ctx): void
{ {
if ($worker = authorization($ctx->getMessage()?->getFrom()?->getId() ?? $ctx->getCallbackQuery()->getFrom()->getId())) { if ($account = authorization($ctx->getMessage()?->getFrom()?->getId() ?? $ctx->getCallbackQuery()->getFrom()->getId())) {
// Успешная авторизация // Успешная авторизация
$ctx->sendMessage('👋 Здравствуйте, ' . $worker->name, [ $ctx->sendMessage('👋 Здравствуйте, ' . preg_replace('/([._\-()!#])/', '\\\$1', $account->name['first']), [
'reply_markup' => [ 'reply_markup' => [
'inline_keyboard' => [ 'inline_keyboard' => [
[ [
@ -170,7 +198,9 @@ function requests(int $amount = 5, int $page = 1): Cursor
$arangodb->session, $arangodb->session,
[ [
'query' => sprintf( 'query' => sprintf(
"FOR d IN works FILTER d.worker == null && d.confirmed != 'да' SORT d.created DESC LIMIT %d, %d RETURN d", "FOR d IN task FILTER d.date >= %s && d.date <= %s && d.worker == null && d.confirmed != true && d.published == true && d.completed != true SORT d.created DESC, d._key DESC LIMIT %d, %d RETURN d",
(new DateTime('now'))->setTime(7, 0)->format('U'),
(new DateTime('tomorrow'))->setTime(7, 0)->format('U'),
$offset, $offset,
$amount + $offset $amount + $offset
), ),
@ -207,42 +237,37 @@ function request_choose(Context $ctx): void
{ {
global $arangodb; global $arangodb;
if (($worker = authorization($ctx->getCallbackQuery()->getFrom()->getId())) instanceof _document) { if (($account = authorization($ctx->getCallbackQuery()->getFrom()->getId())) instanceof _document) {
// Авторизован // Авторизован
// Инициализация ключа инстанции works в базе данных // Инициализация ключа инстанции task в базе данных
preg_match('/^#(\d+)\n/', $ctx->getCallbackQuery()->getMessage()->getText(), $matches); preg_match('/^#(\d+)\n/', $ctx->getCallbackQuery()->getMessage()->getText(), $matches);
$_key = $matches[1]; $_key = $matches[1];
// Инициализация инстанции works в базе данных (выбранного задания) // Инициализация инстанции task в базе данных (выбранного задания)
$work = collection::search($arangodb->session, sprintf("FOR d IN works FILTER d._key == '%s' RETURN d", $_key)); $task = collection::search($arangodb->session, sprintf("FOR d IN task FILTER d._key == '%s' && d.published == true && d.completed != true RETURN d", $_key));
// Запись о том, что задание подтверждено (в будущем здесь будет отправка на потдверждение модераторам) if ($worker = worker($account->getId())) {
$work->confirmed = 'да'; // Найден сотрудник
// Запись о том, что необходимо перенести изменения в Google Sheets // Запись идентификатора нового сотрудника
$work->transfer_to_sheets = 'да'; $task->worker = $worker->getKey();
// Запись идентификатора Google Sheets нового сотрудника // Снятие с публикации
$work->worker = $worker->id; $task->published = false;
if (document::update($arangodb->session, $work)) { if (document::update($arangodb->session, $task)) {
// Записано обновление в базу данных // Записано обновление в базу данных
if (collection::search(
$arangodb->session,
sprintf(
"FOR d IN readinesses FILTER d._id == '%s' RETURN d",
document::write($arangodb->session, 'readinesses', ['_from' => $worker->getId(), '_to' => $work->getId()])
)
)) {
// Записано ребро: worker -> work (принятие заявки)
$ctx->sendMessage("✅ *Заявка принята:* \#$_key", ['reply_markup' => ['remove_keyboard' => true]])->then(function () use ($ctx) { $ctx->sendMessage("✅ *Заявка принята:* \#$_key", ['reply_markup' => ['remove_keyboard' => true]])->then(function () use ($ctx) {
generateMenu($ctx); generateMenu($ctx);
}); });
} } else $ctx->sendMessage("❎ *Не удалось принять заявку:* \#$_key", ['reply_markup' => ['remove_keyboard' => true]])->then(function () use ($ctx) {
} generateMenu($ctx);
});
} else $ctx->sendMessage("❎ *Не удалось принять заявку:* \#$_key", ['reply_markup' => ['remove_keyboard' => true]])->then(function () use ($ctx) {
generateMenu($ctx);
});
} }
} }
@ -263,29 +288,29 @@ function search(Context $ctx): void
} }
// Поиск заявок из базы данных // Поиск заявок из базы данных
$requests = requests(6, $page); $tasks = requests(6, $page);
// Подсчёт количества прочитанных заявок из базы данных // Подсчёт количества прочитанных заявок из базы данных
$count = $requests->getCount(); $count = $tasks->getCount();
// Проверка существования избытка // Проверка существования избытка
$excess = $count % 6 === 0; $excess = $count % 6 === 0;
// Обрезка заявок до размера страницы // Обрезка заявок до размера страницы
$requests = array_slice($requests->getAll(), 0, 5); $tasks = array_slice($tasks->getAll(), 0, 5);
if ($count === 0) $ctx->sendMessage('📦 *Заявок нет*'); if ($count === 0) $ctx->sendMessage('📦 *Заявок нет*');
else { else {
// Найдены заявки // Найдены заявки
foreach ($requests as $i => $request) { foreach ($tasks as $i => $task) {
// Перебор найденных заявок // Перебор найденных заявок
if (($market = collection::search( if (($market = collection::search(
$arangodb->session, $arangodb->session,
sprintf( sprintf(
"FOR d IN markets LET e = (FOR e IN requests FILTER e._to == '%s' RETURN e._from)[0] FILTER d._id == e RETURN d", "FOR d IN market FILTER d._key == '%s' RETURN d",
$request->getId() $task->market
) )
)) instanceof _document) { )) instanceof _document) {
// Найден магазин // Найден магазин
@ -303,7 +328,7 @@ function search(Context $ctx): void
preg_replace( preg_replace(
'/([._\-()!#])/', '/([._\-()!#])/',
'\\\$1', '\\\$1',
"*#{$request->getKey()}*\n" . $request->date['converted'] . " (" . $request->start['converted'] . " - " . $request->end['converted'] . ")\n\n*Город:* $market->city\n*Адрес:* $market->address\n*Работа:* \"$request->work\"" "*#{$task->getKey()}*\n" . (new DateTime('@' . $task->date))->format('d.m.Y') . " (" . $task->start . " - " . $task->end . ")\n\n*Город:* $market->city\n*Адрес:* $market->address\n*Работа:* $task->work" . (mb_strlen($task->description) > 0 ? "\n\n$task->description" : '')
), ),
[ [
'reply_markup' => [ 'reply_markup' => [
@ -314,10 +339,11 @@ function search(Context $ctx): void
] ]
] ]
] ]
)->then(function ($message) use ($ctx, $requests, $i, $page, $excess) { )->then(function ($message) use ($ctx, $tasks, $i, $page, $excess) {
// Запись сообщения в кеш (на случай необходимости его удаления при смене страницы) // Запись сообщения в кеш (на случай необходимости его удаления при смене страницы)
$ctx->setChatDataItem("request_$i", $message)->then(function () use ($ctx, $requests, $i, $page, $excess) { $ctx->setChatDataItem("request_$i", $message)->then(function () use ($ctx, $tasks, $i, $page, $excess) {
if ($i === array_key_last($requests)) {
if ($i === array_key_last($tasks)) {
// Удаление предыдущего меню // Удаление предыдущего меню
$ctx->getChatDataItem("request_menu")->then(function ($message) use ($ctx) { $ctx->getChatDataItem("request_menu")->then(function ($message) use ($ctx) {
$ctx->deleteMessage($message->getChat()->getId(), $message->getMessageId()); $ctx->deleteMessage($message->getChat()->getId(), $message->getMessageId());

View File

0
telegram-robot.service Normal file → Executable file
View File