J.A.R.V.I.S-rust/resources/commands/wiki/wiki.lua
Bossiara13 9d8b917149 feat(commands): analog-inspired tier-2 — news, currency, crypto, fun, wiki, power, help (33 packs)
Seven more portable Lua packs lifted from common voice-assistant
playbooks (Siri/Alexa/Алиса/Cortana). All sandbox=full, jarvis.http
+ jarvis.system.exec, zero new Rust code. cargo test still 3/3.

news/ — pulls Lenta.ru RSS (en switches to BBC), regex-extracts the
top 5 <title> entries (skipping the channel header), drops them into
the clipboard, then asks Groq for a 2-3 sentence summary at temp 0.4
and speaks it via SAPI. If GROQ_TOKEN is missing it falls back to
just reading the first three headlines.

currency/ — cbr-xml-daily.ru/daily_json.js. Picks USD/EUR/CNY/GBP/
JPY/KZT by keyword in the phrase, computes value / nominal, diffs
against Valute.Previous, says "X стоит N рублей, поднялся/опустился
на M" with ▲/▼ in the notify body.

crypto/ — CoinGecko simple/price with usd,rub and 24hr_change.
Recognises bitcoin / ethereum / solana / dogecoin / the-open-network.
Reports price + direction in plain Russian.

fun/ — joke / fact / quote / compliment, single ask.lua dispatched by
command_id. Per-command system prompt at temp 1.0; seeds with a
random integer so consecutive calls don't repeat.

wiki/ — ru.wikipedia opensearch → REST summary endpoint. If Groq is
available and extract > 350 chars, asks for a 2-3 sentence retell;
otherwise speaks the first 400 chars verbatim. Full extract goes to
clipboard.

power/ — shutdown_pc / restart_pc / sleep_pc / hibernate_pc /
logoff_user / cancel_shutdown. Single act.lua keyed by command_id.
shutdown/restart use shutdown.exe /s|/r /t 30 with a /c message —
30-second grace window so "отмени выключение" actually works.
sleep uses rundll32 powrprof,SetSuspendState, hibernate uses
shutdown.exe /h.

help/ — "что ты умеешь". Reads the parent commands/ dir via
jarvis.fs.list, sorts subdirs (pack names), pairs each with a
hardcoded Russian/English one-liner description, copies the full
list to clipboard and speaks a count + "see clipboard for full list".

Total command packs is now 33 (was 26).
2026-05-15 12:43:09 +03:00

103 lines
4.1 KiB
Lua
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.

local lang = jarvis.context.language
local phrase = (jarvis.context.phrase or ""):lower()
local triggers = {
"найди в википедии про", "википедия про", "расскажи про",
"кто такая", "кто такой", "что такое",
"tell me about", "wikipedia about", "who is", "what is",
"розкажи про", "хто такий", "що таке",
}
local query = phrase
for _, t in ipairs(triggers) do
local s, e = string.find(query, t, 1, true)
if s == 1 then
query = query:sub(e + 1)
break
end
end
query = query:gsub("^%s+", ""):gsub("%s+$", "")
if query == "" then
jarvis.system.notify("Wiki", lang == "ru" and "О чём рассказать?" or "What to look up?")
jarvis.audio.play_error()
return { chain = false }
end
local function url_encode(s)
return (s:gsub("([^%w%-_%.~])", function(c) return string.format("%%%02X", string.byte(c)) end))
end
local host = lang == "en" and "en.wikipedia.org" or "ru.wikipedia.org"
local search_url = string.format(
"https://%s/w/api.php?action=opensearch&search=%s&limit=1&format=json",
host, url_encode(query)
)
local search = jarvis.http.get(search_url)
if not search.ok then
jarvis.system.notify("Wiki", "Поиск не удался")
jarvis.audio.play_error()
return { chain = false }
end
local title = search.body:match('%["[^"]+",%s*%["([^"]+)"')
if not title or title == "" then
jarvis.system.notify("Wiki", (lang == "ru" and "Не нашёл: " or "Not found: ") .. query)
jarvis.audio.play_not_found()
return { chain = false }
end
local summary_url = string.format(
"https://%s/api/rest_v1/page/summary/%s",
host, url_encode(title)
)
local summary = jarvis.http.json(summary_url)
if not summary or type(summary) ~= "table" or not summary.extract then
jarvis.system.notify("Wiki", "Не получил конспект")
jarvis.audio.play_error()
return { chain = false }
end
local extract = summary.extract
local article_title = summary.title or title
local token = jarvis.system.env("GROQ_TOKEN")
local say_text = extract:sub(1, 400)
if token and token ~= "" and #extract > 350 then
local base = jarvis.system.env("GROQ_BASE_URL"); if not base or base == "" then base = "https://api.groq.com/openai/v1" end
local model = jarvis.system.env("GROQ_MODEL"); if not model or model == "" then model = "llama-3.3-70b-versatile" end
local sys = lang == "ru"
and "Тебе дана статья из Википедии. Перескажи суть простым разговорным языком в 2-3 предложения. Без 'википедия гласит' и подобных вступлений."
or "Summarise this Wikipedia text in 2-3 plain-language sentences. No 'wikipedia says' preambles."
local payload = {
model = model,
messages = {
{ role = "system", content = sys },
{ role = "user", content = extract:sub(1, 2500) },
},
max_tokens = 220,
temperature = 0.3,
}
local lr = jarvis.http.post_json(base .. "/chat/completions", payload, { Authorization = "Bearer " .. token })
if lr.ok then
local c = (lr.body or ""):match('"content"%s*:%s*"(.-[^\\])"')
if c then
c = c:gsub('\\n', ' '):gsub('\\"', '"'):gsub('\\\\', '\\'):gsub("%s+", " ")
say_text = c:gsub("^%s+", ""):gsub("%s+$", "")
end
end
end
jarvis.system.clipboard.set(article_title .. "\n\n" .. extract)
jarvis.system.notify(article_title, say_text:sub(1, 240))
local sapi = say_text:gsub("'", "''"):gsub("\r?\n", " ")
local ps = string.format(
[[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')]],
sapi
)
jarvis.system.exec(string.format('powershell -NoProfile -Command "%s"', ps:gsub('"', '\\"')))
jarvis.audio.play_ok()
return { chain = false }