120 lines
4.5 KiB
Lua
120 lines
4.5 KiB
Lua
|
|
local lang = jarvis.context.language
|
||
|
|
local phrase = (jarvis.context.phrase or ""):lower()
|
||
|
|
|
||
|
|
local triggers = {
|
||
|
|
"поставь напоминание через", "установи таймер на",
|
||
|
|
"напомни мне через", "напомни через", "напомни",
|
||
|
|
"remind me in", "set reminder in", "set timer for", "timer for",
|
||
|
|
"постав нагадування через", "нагадай через", "таймер на",
|
||
|
|
}
|
||
|
|
|
||
|
|
local rest = phrase
|
||
|
|
for _, t in ipairs(triggers) do
|
||
|
|
local s, e = string.find(rest, t, 1, true)
|
||
|
|
if s == 1 then
|
||
|
|
rest = rest:sub(e + 1)
|
||
|
|
break
|
||
|
|
end
|
||
|
|
end
|
||
|
|
rest = rest:gsub("^%s+", "")
|
||
|
|
|
||
|
|
local unit_words = {
|
||
|
|
["секунд"] = 1, ["секунду"] = 1, ["секунды"] = 1,
|
||
|
|
["second"] = 1, ["seconds"] = 1, ["sec"] = 1,
|
||
|
|
["минут"] = 60, ["минуту"] = 60, ["минуты"] = 60, ["мин"] = 60,
|
||
|
|
["minute"] = 60, ["minutes"] = 60, ["min"] = 60,
|
||
|
|
["час"] = 3600, ["часа"] = 3600, ["часов"] = 3600, ["часик"] = 3600,
|
||
|
|
["hour"] = 3600, ["hours"] = 3600, ["hr"] = 3600,
|
||
|
|
}
|
||
|
|
local rus_numerals = {
|
||
|
|
["один"] = 1, ["одну"] = 1, ["одна"] = 1, ["полторы"] = 1, ["полтора"] = 1,
|
||
|
|
["два"] = 2, ["две"] = 2, ["три"] = 3, ["четыре"] = 4, ["пять"] = 5,
|
||
|
|
["шесть"] = 6, ["семь"] = 7, ["восемь"] = 8, ["девять"] = 9, ["десять"] = 10,
|
||
|
|
["пятнадцать"] = 15, ["двадцать"] = 20, ["тридцать"] = 30, ["сорок"] = 40,
|
||
|
|
["пятьдесят"] = 50, ["час"] = 60, -- "через час" without number
|
||
|
|
}
|
||
|
|
|
||
|
|
local number, unit, body = nil, nil, nil
|
||
|
|
|
||
|
|
local num_str, rest_after_num = rest:match("^(%d+)%s+(.+)")
|
||
|
|
if num_str then
|
||
|
|
number = tonumber(num_str)
|
||
|
|
rest = rest_after_num
|
||
|
|
else
|
||
|
|
local first_word, after = rest:match("^(%S+)%s*(.*)")
|
||
|
|
if first_word and rus_numerals[first_word] then
|
||
|
|
number = rus_numerals[first_word]
|
||
|
|
rest = after or ""
|
||
|
|
end
|
||
|
|
end
|
||
|
|
|
||
|
|
if rest and #rest > 0 then
|
||
|
|
local first_word, after = rest:match("^(%S+)%s*(.*)")
|
||
|
|
if first_word then
|
||
|
|
for w, secs in pairs(unit_words) do
|
||
|
|
if first_word:sub(1, #w) == w then
|
||
|
|
unit = secs
|
||
|
|
body = after or ""
|
||
|
|
break
|
||
|
|
end
|
||
|
|
end
|
||
|
|
end
|
||
|
|
end
|
||
|
|
|
||
|
|
if not number then
|
||
|
|
number = 5
|
||
|
|
if not unit then unit = 60 end
|
||
|
|
body = rest
|
||
|
|
elseif not unit then
|
||
|
|
unit = 60
|
||
|
|
body = rest
|
||
|
|
end
|
||
|
|
|
||
|
|
local total_seconds = number * unit
|
||
|
|
if total_seconds < 1 then total_seconds = 1 end
|
||
|
|
if total_seconds > 86400 then total_seconds = 86400 end
|
||
|
|
|
||
|
|
body = (body or ""):gsub("^%s+", ""):gsub("%s+$", "")
|
||
|
|
if body == "" then
|
||
|
|
body = lang == "ru" and "Напоминание!" or "Reminder!"
|
||
|
|
end
|
||
|
|
|
||
|
|
local function human_time(sec)
|
||
|
|
if sec < 60 then return sec .. " сек" end
|
||
|
|
if sec < 3600 then return math.floor(sec/60) .. " мин" end
|
||
|
|
return string.format("%d ч %d мин", math.floor(sec/3600), math.floor((sec%3600)/60))
|
||
|
|
end
|
||
|
|
|
||
|
|
local title_esc = (lang == "ru" and "Напоминание J.A.R.V.I.S." or "J.A.R.V.I.S. reminder"):gsub("'", "''")
|
||
|
|
local body_esc = body:gsub("'", "''")
|
||
|
|
local sapi_text = ((lang == "ru" and "Сэр, напоминаю: " or "Reminder: ") .. body):gsub("'", "''"):gsub("\r?\n", " ")
|
||
|
|
|
||
|
|
local ps = string.format(
|
||
|
|
[[Start-Sleep -Seconds %d; ]]
|
||
|
|
.. [[$null = New-Object -ComObject Shell.Application; ]]
|
||
|
|
.. [[try { ]]
|
||
|
|
.. [[ Import-Module BurntToast -ErrorAction SilentlyContinue; ]]
|
||
|
|
.. [[ New-BurntToastNotification -Text '%s', '%s' -ErrorAction SilentlyContinue ]]
|
||
|
|
.. [[} catch {}; ]]
|
||
|
|
.. [[Add-Type -AssemblyName System.Speech; ]]
|
||
|
|
.. [[$s = New-Object System.Speech.Synthesis.SpeechSynthesizer; ]]
|
||
|
|
.. [[foreach ($v in $s.GetInstalledVoices()) { if ($v.VoiceInfo.Culture.TwoLetterISOLanguageName -eq 'ru') { try { $s.SelectVoice($v.VoiceInfo.Name); break } catch {} } }; ]]
|
||
|
|
.. [[$s.Speak('%s'); ]]
|
||
|
|
.. [[$wsh = New-Object -ComObject WScript.Shell; $wsh.Popup('%s', 30, '%s', 64) | Out-Null]],
|
||
|
|
total_seconds, title_esc, body_esc, sapi_text, body_esc, title_esc
|
||
|
|
)
|
||
|
|
local cmd = string.format(
|
||
|
|
'powershell -NoProfile -WindowStyle Hidden -ExecutionPolicy Bypass -Command "%s"',
|
||
|
|
ps:gsub('"', '\\"')
|
||
|
|
)
|
||
|
|
|
||
|
|
jarvis.system.exec("start /b " .. cmd)
|
||
|
|
|
||
|
|
jarvis.system.notify(
|
||
|
|
lang == "ru" and "Таймер установлен" or "Timer set",
|
||
|
|
string.format(lang == "ru" and "Через %s: %s" or "In %s: %s", human_time(total_seconds), body)
|
||
|
|
)
|
||
|
|
jarvis.log("info", string.format("reminder in %ds: %s", total_seconds, body))
|
||
|
|
jarvis.audio.play_ok()
|
||
|
|
return { chain = false }
|