Сильно я подсел на новую игрушку. Пришла мысль из напоминалки сделать шаблон, который может отложить выполнение любой задачи на какое то время. Допустим выключить свет через пять минут, или телик через час. Вообщем что угодно, что уже настроено в шаблонах.
Суть в следующем, Создаем шаблон с большим приоритетом, чтобы он первый перехватил сообщение и прекратил дальнейшую обработку шаблонов. У меня он располагается сразу после шаблона с общим контекстом
- шаблон.jpg (18.67 КБ) 1505 просмотров
Ставим галки не проверять другие шаблоны при совпадении и Не реагировать на системные сообщения
Шаблон (.*) через (.*)
Он сработает если после обычной команды мы добавим "через какое то время". Варианты пока небольшие: х дней х часов х минут х секунд. далее будет создано задание с текстом команды и таймером чтобы отложить выполнение. По истечении таймера текст будет добавлен в чат функцией say() но от имени пользователя, который это сказал ранее, что вызовет обычную реакцию других шаблонов.
Код шаблона:
Код: Выделить всё
$rnumber = 1;
while (1) {
$rname = "Reminder_$rnumber";
if (!timeOutExists($rname)) break;
$rnumber++;
}
// "/(?<!\S)(....)(?!\S)/"
$parts = preg_split("/(?<=\s|^)(день|дня|дней|час|часа|часов|минут|минута|минуту|минуты|секунд|секунда|секунду|секунды)(?=\s|$)/", $matches[2],-1, PREG_SPLIT_DELIM_CAPTURE);
$s=0;
for ($i = 0; $i <= count($parts)-2; $i+=2) {
//debmes($parts[$i+1].'='.trim(parts[$i]));
if (stripos($parts[$i+1], 'д') === 0) { $s+=word_to_number(trim($parts[$i]))*86400; }
elseif (stripos($parts[$i+1], 'ч') === 0) { $s+=word_to_number(trim($parts[$i]))*3600; }
elseif (stripos($parts[$i+1], 'м') === 0) { $s+=word_to_number(trim($parts[$i]))*60; }
elseif (stripos($parts[$i+1], 'с') === 0) { $s+=word_to_number(trim($parts[$i]))*1; }
}
$msgs=array('Задание создано', 'Сделаем', 'Постараюсь не забыть', 'Хорошо', 'Конечно');
say($msgs[array_rand($msgs)], 1); //через $s сек
setTimeOut($rname,"say('Задание: " . trim($matches[1]) . "', 0, $from_user_id);", $s);
function word_to_number(string $text)
{
$replaces = [
'один' => 1,
'одну' => 1,
'одна' => 1,
'два' => 2,
'две' => 2,
'три' => 3,
'четыре' => 4,
'пять' => 5,
'шесть' => 6,
'семь' => 7,
'восемь' => 8,
'девять' => 9,
'десять' => 10,
'одиннадцать' => 11,
'двенадцать' => 12,
'тринадцать' => 13,
'четырнадцать' => 14,
'пятнадцать' => 15,
'шестнадцать' => 16,
'семнадцать' => 17,
'восемнадцать' => 18,
'девятнадцать' => 19,
'двадцать' => 20,
'тридцать' => 30,
'сорок' => 40,
'пятьдесят' => 50,
'шестьдесят' => 60,
'семьдесят' => 70,
'восемьдесят' => 80,
'девяносто' => 90,
'сто' => 100,
'двести' => 200,
'триста' => 300,
'четыреста' => 400,
'пятьсот' => 500,
'шестьсот' => 600,
'семьсот' => 700,
'восемьсот' => 800,
'девятьсот' => 900
];
return preg_replace('/0(?(?=0\s\d{2,})0)\s/', '', strtr($text, $replaces));
}
Теперь о том, над чем ещё можно поработать. функция word_to_number не всегда хорошо отрабатывает замену цифр прописью, если в тексте присутствует ещё что то. Например "десять секунд", поэтому я вызываю её каждый раз после разбиения строки на массив по часам, минутам, секундам. По сути, в этом нет ничего страшного.
Сам вариант разбиения строки на массив. От моего кода у самого глаза слезятся. Идея в том, чтобы регуляркой разбить строку по ключам (часы, минуты ...) и затем умножить цифры на количество секунд в каждой группе. То есть, если бы после разбиения получить массив с фиксированной позицией дней, часов минут ... то тогда код выглядел бы очень хорошо. Так что если кто то поможет навести тут порядок, буду очень благодарен. Но тем не менее вариант уже вполне рабочий.
P. S. можно немного сократить регулярку
$parts = preg_split("/(?<=\s|^)(день|дня|дней|час\S*|минут\S*|секунд\S*)(?=\s|$)/", $matches[2],-1, PREG_SPLIT_DELIM_CAPTURE);