J.A.R.V.I.S-rust/resources/commands/news/news.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

82 lines
3.3 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 feed = lang == "en"
and "https://feeds.bbci.co.uk/news/rss.xml"
or "https://lenta.ru/rss/news"
local res = jarvis.http.get(feed)
if not res.ok then
jarvis.system.notify("News", "Не получил RSS: " .. tostring(res.status))
jarvis.audio.play_error()
return { chain = false }
end
local titles = {}
for title in res.body:gmatch("<title>%s*<!%[CDATA%[(.-)%]%]>%s*</title>") do
if title ~= "" and title:lower():find("rss") == nil and title:lower():find("новости") ~= 1 then
table.insert(titles, title)
end
if #titles >= 7 then break end
end
if #titles == 0 then
for title in res.body:gmatch("<title>%s*(.-)%s*</title>") do
if title ~= "" then
table.insert(titles, title)
end
if #titles >= 7 then break end
end
end
if #titles <= 1 then
jarvis.system.notify("News", lang == "ru" and "Не получилось распарсить" or "Could not parse feed")
jarvis.audio.play_error()
return { chain = false }
end
local top = {}
for i = 2, math.min(6, #titles) do table.insert(top, titles[i]) end
local joined = table.concat(top, " | ")
jarvis.system.clipboard.set(joined)
jarvis.system.notify(lang == "ru" and "Новости" or "News", joined:sub(1, 280))
local token = jarvis.system.env("GROQ_TOKEN")
local say_text
if token and token ~= "" 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 "Ты диктор. Дам список заголовков новостей. Сжато перескажи 3 главные темы простым языком, 2-3 предложения суммарно. Не упоминай номера и не повторяй заголовки дословно."
or "You are a news anchor. Summarise the top 3 headlines in 2-3 sentences. No numbering, no verbatim repeats."
local payload = {
model = model,
messages = {
{ role = "system", content = sys },
{ role = "user", content = joined },
},
max_tokens = 220,
temperature = 0.4,
}
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('\\\\', '\\')
say_text = c
end
end
end
if not say_text then
say_text = (lang == "ru" and "Главные новости: " or "Top news: ") .. (top[1] or "") .. ". " .. (top[2] or "") .. ". " .. (top[3] or "")
end
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 }