This repository has been archived on 2021-04-24. You can view files and clone it, but cannot push or open issues or pull requests.
Mikubot-2/otouto/plugins/wikipedia.lua

220 lines
6.0 KiB
Lua

local wikipedia = {}
wikipedia.command = 'wiki <Begriff>'
function wikipedia:init(config)
wikipedia.triggers = {
"^/[Ww]iki(%w+) (search) (.+)$",
"^/[Ww]iki (search) ?(.*)$",
"^/[Ww]iki(%w+) (.+)$",
"^/[Ww]iki ?(.*)$",
"(%w+).wikipedia.org/wiki/(.+)"
}
wikipedia.inline_triggers = {
"^wiki(%w+) (.+)",
"^wiki (.+)"
}
wikipedia.doc = [[*
]]..config.cmd_pat..[[wiki* _<Begriff>_: Gibt Wikipedia-Artikel aus
Alias: ]]..config.cmd_pat..[[wikipedia]]
end
local decodetext
do
local char, gsub, tonumber = string.char, string.gsub, tonumber
local function _(hex) return char(tonumber(hex, 16)) end
function decodetext(s)
s = gsub(s, '%%(%x%x)', _)
return s
end
end
local server = {
-- http://meta.wikimedia.org/wiki/List_of_Wikipedias
wiki_server = "https://%s.wikipedia.org",
wiki_path = "/w/api.php",
wiki_load_params = {
action = "query",
prop = "extracts",
format = "json",
exchars = 350,
exsectionformat = "plain",
explaintext = "",
redirects = ""
},
wiki_search_params = {
action = "query",
list = "search",
srlimit = 20,
format = "json",
},
default_lang = "de",
}
function wikipedia:getWikiServer(lang)
return string.format(server.wiki_server, lang or server.default_lang)
end
--[[
-- return decoded JSON table from Wikipedia
--]]
function wikipedia:loadPage(text, lang, intro, plain, is_search)
local request, sink = {}, {}
local query = ""
local parsed
if is_search then
for k,v in pairs(server.wiki_search_params) do
query = query .. k .. '=' .. v .. '&'
end
parsed = URL.parse(wikipedia:getWikiServer(lang))
parsed.path = server.wiki_path
parsed.query = query .. "srsearch=" .. URL.escape(text)
else
server.wiki_load_params.explaintext = plain and "" or nil
for k,v in pairs(server.wiki_load_params) do
query = query .. k .. '=' .. v .. '&'
end
parsed = URL.parse(wikipedia:getWikiServer(lang))
parsed.path = server.wiki_path
parsed.query = query .. "titles=" .. URL.escape(text)
end
-- HTTP request
request['url'] = URL.build(parsed)
request['method'] = 'GET'
request['sink'] = ltn12.sink.table(sink)
local httpRequest = parsed.scheme == 'http' and http.request or https.request
local code, headers, status = socket.skip(1, httpRequest(request))
if not headers or not sink then
return nil
end
local content = table.concat(sink)
if content ~= "" then
local ok, result = pcall(json.decode, content)
if ok and result then
return result
else
return nil
end
else
return nil
end
end
-- extract intro passage in wiki page
function wikipedia:wikintro(text, lang)
local text = decodetext(text)
local result = self:loadPage(text, lang, true, true)
if result and result.query then
local query = result.query
if query and query.normalized then
text = query.normalized[1].to or text
end
local page = query.pages[next(query.pages)]
if page and page.extract then
local lang = lang or "de"
local title = page.title
local title_enc = URL.escape(title)
return '*'..title.."*:\n"..utilities.md_escape(page.extract), '{"inline_keyboard":[[{"text":"Artikel aufrufen","url":"https://'..lang..'.wikipedia.org/wiki/'..title_enc..'"}]]}'
else
local text = text.." nicht gefunden"
return text
end
else
return "Ein Fehler ist aufgetreten."
end
end
-- search for term in wiki
function wikipedia:wikisearch(text, lang)
local result = wiki:loadPage(text, lang, true, true, true)
if result and result.query then
local titles = ""
for i,item in pairs(result.query.search) do
titles = titles .. "\n" .. item["title"]
end
titles = titles ~= "" and titles or "Keine Ergebnisse gefunden"
return titles
else
return "Ein Fehler ist aufgetreten."
end
end
function wikipedia:snip_snippet(snippet)
local snippet = snippet:gsub("<span class%=\"searchmatch\">", "")
local snippet = snippet:gsub("</span>", "")
return snippet
end
function wikipedia:inline_callback(inline_query, config, matches)
if matches[2] then
lang = matches[1]
query = matches[2]
else
lang = 'de'
query = matches[1]
end
local url = 'https://'..lang..'.wikipedia.org/w/api.php?action=query&list=search&srsearch='..URL.escape(query)..'&format=json&prop=extracts&srprop=snippet'
local res, code = https.request(url)
if code ~= 200 then utilities.answer_inline_query(self, inline_query) return end
local data = json.decode(res).query
if data.searchinfo.totalhits == 0 then utilities.answer_inline_query(self, inline_query) return end
local results = '['
for num in pairs(data.search) do
local title = data.search[num].title
results = results..'{"type":"article","id":"'..math.random(100000000000000000)..'","title":"'..title..'","description":"'..wikipedia:snip_snippet(data.search[num].snippet)..'","url":"https://'..lang..'.wikipedia.org/wiki/'..URL.escape(title)..'","hide_url":true,"thumb_url":"https://anditest.perseus.uberspace.de/inlineQuerys/wiki/logo.jpg","thumb_width":95,"thumb_height":86,"input_message_content":{"message_text":"https://'..lang..'.wikipedia.org/wiki/'..URL.escape(title)..'","disable_web_page_preview":true}}'
if num < #data.search then
results = results..','
end
end
local results = results..']'
utilities.answer_inline_query(self, inline_query, results, 3600)
end
function wikipedia:action(msg, config, matches)
local search, term, lang
if matches[1] == "search" then
search = true
term = matches[2]
lang = nil
elseif matches[2] == "search" then
search = true
term = matches[3]
lang = matches[1]
else
term = matches[2]
lang = matches[1]
end
if not term then
term = lang
lang = nil
end
if term == "" then
utilities.send_reply(self, msg, wikipedia.doc, true)
return
end
local result
if search then
result = wikipedia:wikisearch(term, lang)
else
result, keyboard = wikipedia:wikintro(term, lang)
end
utilities.send_reply(self, msg, result, true, keyboard)
end
return wikipedia