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/plugins/rss.lua

246 lines
6.9 KiB
Lua
Raw Normal View History

2015-09-13 18:23:35 +02:00
feedparser = (loadfile "./libs/feedparser.lua")()
local function unescape_for_rss(str)
-- Character encoding
2015-11-12 17:42:03 +01:00
str = string.gsub(str, "´", "´")
2015-09-13 18:23:35 +02:00
str = string.gsub(str, ">", ">")
2015-11-12 17:42:03 +01:00
str = string.gsub(str, "&lt;", "<")
str = string.gsub(str, "&mdash;", "")
str = string.gsub(str, "&nabla;", "")
2015-09-13 18:23:35 +02:00
str = string.gsub(str, "&ndash;", "")
2015-11-12 17:42:03 +01:00
str = string.gsub(str, "&Psi;", "ψ")
str = string.gsub(str, "&psi;", "ψ")
2015-09-13 18:23:35 +02:00
str = string.gsub(str, "&raquo;", "»")
2015-11-12 17:42:03 +01:00
str = string.gsub(str, "&szlig;", "ß")
str = string.gsub(str, "&#39;", "'")
str = string.gsub(str, "&#124;", "|")
str = string.gsub(str, "&#160;", " ")
2015-09-13 18:23:35 +02:00
str = string.gsub(str, "&#187;", "»")
2015-11-12 17:42:03 +01:00
str = string.gsub(str, "&#223;", "ß")
2015-09-13 18:23:35 +02:00
str = string.gsub(str, "&#8211;", "")
2015-11-12 17:42:03 +01:00
str = string.gsub(str, "&#8217;", "'")
2015-09-13 18:23:35 +02:00
str = string.gsub(str, "&#8220;", "")
str = string.gsub(str, "&#8221;", "")
2015-11-12 17:42:03 +01:00
str = string.gsub(str, "&#8222;", "")
str = string.gsub(str, "&#8249;", "")
2015-09-13 18:23:35 +02:00
str = string.gsub(str, "&#8364;", "")
-- Ä Ö Ü
str = string.gsub(str, "&auml;", "ä")
str = string.gsub(str, "&Auml;", "Ä")
str = string.gsub(str, "&#228;", "ä")
str = string.gsub(str, "&#196;", "Ä")
str = string.gsub(str, "&ouml;", "ö")
str = string.gsub(str, "&Ouml;", "Ö")
str = string.gsub(str, "&#246;", "ö")
str = string.gsub(str, "&#214;", "Ö")
str = string.gsub(str, "&uuml;", "ü")
str = string.gsub(str, "&Uuml;", "Ü")
str = string.gsub(str, "&#252;", "ü")
str = string.gsub(str, "&#220;", "Ü")
2015-11-12 17:42:03 +01:00
2015-09-13 18:23:35 +02:00
str = string.gsub( str, '&#x(%d+);', function(n) return string.char(tonumber(n,16)) end )
str = string.gsub( str, '&amp;', '&' ) -- Be sure to do this after all others
return str
end
2015-06-02 21:52:21 +02:00
local function get_base_redis(id, option, extra)
local ex = ''
if option ~= nil then
ex = ex .. ':' .. option
if extra ~= nil then
ex = ex .. ':' .. extra
end
end
return 'rss:' .. id .. ex
end
local function prot_url(url)
local url, h = string.gsub(url, "http://", "")
local url, hs = string.gsub(url, "https://", "")
local protocol = "http"
if hs == 1 then
protocol = "https"
end
return url, protocol
end
local function get_rss(url, prot)
local res, code = nil, 0
if prot == "http" then
res, code = http.request(url)
elseif prot == "https" then
res, code = https.request(url)
end
if code ~= 200 then
2015-09-12 21:55:04 +02:00
return nil, 'Fehler beim Erreichen von ' .. url
2015-06-02 21:52:21 +02:00
end
local parsed = feedparser.parse(res)
if parsed == nil then
2015-06-08 23:32:11 +02:00
return nil, 'Fehler beim hinzufügen des RSS-Feeds.\nSicher, dass "' .. url .. '" einen RSS-Feed hat?'
2015-06-02 21:52:21 +02:00
end
return parsed, nil
end
local function get_new_entries(last, nentries)
local entries = {}
for k,v in pairs(nentries) do
if v.id == last then
return entries
else
table.insert(entries, v)
end
end
return entries
end
local function print_subs(id)
local uhash = get_base_redis(id)
local subs = redis:smembers(uhash)
2015-06-08 23:32:11 +02:00
local text = id .. ' hat folgende Feeds:\n---------\n'
2015-06-02 21:52:21 +02:00
for k,v in pairs(subs) do
text = text .. k .. ") " .. v .. '\n'
end
return text
end
local function subscribe(id, url)
local baseurl, protocol = prot_url(url)
local prothash = get_base_redis(baseurl, "protocol")
local lasthash = get_base_redis(baseurl, "last_entry")
local lhash = get_base_redis(baseurl, "subs")
local uhash = get_base_redis(id)
if redis:sismember(uhash, baseurl) then
2015-06-08 23:32:11 +02:00
return 'Der Feed von "' .. url .. '" ist bereits abonniert'
2015-06-02 21:52:21 +02:00
end
local parsed, err = get_rss(url, protocol)
if err ~= nil then
return err
end
local last_entry = ""
if #parsed.entries > 0 then
last_entry = parsed.entries[1].id
end
local name = parsed.feed.title
redis:set(prothash, protocol)
redis:set(lasthash, last_entry)
redis:sadd(lhash, id)
redis:sadd(uhash, baseurl)
2015-06-08 23:32:11 +02:00
return 'Der Feed von "' .. name .. '" wurde erfolgreich abonniert'
2015-06-02 21:52:21 +02:00
end
local function unsubscribe(id, n)
if #n > 3 then
2015-09-12 21:55:04 +02:00
return 'Du kannst nicht mehr als drei Feeds abonnieren!'
2015-06-02 21:52:21 +02:00
end
n = tonumber(n)
local uhash = get_base_redis(id)
local subs = redis:smembers(uhash)
if n < 1 or n > #subs then
2015-09-12 21:55:04 +02:00
return 'Abonnement-ID zu hoch!'
2015-06-02 21:52:21 +02:00
end
local sub = subs[n]
local lhash = get_base_redis(sub, "subs")
redis:srem(uhash, sub)
redis:srem(lhash, id)
local left = redis:smembers(lhash)
if #left < 1 then -- no one subscribed, remove it
local prothash = get_base_redis(sub, "protocol")
local lasthash = get_base_redis(sub, "last_entry")
redis:del(prothash)
redis:del(lasthash)
end
2015-06-08 23:32:11 +02:00
return 'Der Feed von "' .. sub .. '" wurde deabonniert'
2015-06-02 21:52:21 +02:00
end
local function cron()
-- sync every 15 mins?
local keys = redis:keys(get_base_redis("*", "subs"))
for k,v in pairs(keys) do
local base = string.match(v, "rss:(.+):subs") -- Get the URL base
2015-11-12 17:42:03 +01:00
print('Checke RSS: '..base)
2015-06-02 21:52:21 +02:00
local prot = redis:get(get_base_redis(base, "protocol"))
local last = redis:get(get_base_redis(base, "last_entry"))
local url = prot .. "://" .. base
local parsed, err = get_rss(url, prot)
if err ~= nil then
return
end
local newentr = get_new_entries(last, parsed.entries)
local subscribers = {}
2015-09-13 18:23:35 +02:00
local text = '' -- Send one message per feed with the latest entries
2015-06-02 21:52:21 +02:00
for k2, v2 in pairs(newentr) do
2015-09-13 18:23:35 +02:00
local title = v2.title or 'Kein Titel'
local link = v2.link or v2.id or 'Kein Link'
if v2.content then
content = string.sub(unescape_for_rss(v2.content:gsub("%b<>", "")), 1, 250) .. '...'
2015-09-13 19:37:45 +02:00
elseif v2.summary then
2015-09-13 18:23:35 +02:00
content = string.sub(unescape_for_rss(v2.summary:gsub("%b<>", "")), 1, 250) .. '...'
2015-09-13 19:37:45 +02:00
else
content = ''
2015-09-13 18:23:35 +02:00
end
2015-11-12 17:42:03 +01:00
text = text .. '[RSS] '.. title .. '\n'..content..'\n\n' .. link .. '\n\n'
2015-06-02 21:52:21 +02:00
end
if text ~= '' then
local newlast = newentr[1].id
redis:set(get_base_redis(base, "last_entry"), newlast)
for k2, receiver in pairs(redis:smembers(v)) do
send_msg(receiver, text, ok_cb, false)
end
end
end
end
local function run(msg, matches)
local id = "user#id" .. msg.from.id
if is_chat_msg(msg) then
id = "chat#id" .. msg.to.id
end
if matches[1] == "/rss"then
return print_subs(id)
end
if matches[1] == "sync" then
cron()
end
if matches[1] == "add" then
2015-06-02 21:52:21 +02:00
return subscribe(id, matches[2])
end
if matches[1] == "remove" then
2015-06-02 21:52:21 +02:00
return unsubscribe(id, matches[2])
end
end
return {
description = "RSS-Feed Reader",
2015-11-12 17:42:03 +01:00
usage = {"RSS Befehle kann nur Sudo\n",
"/rss (Feed-Abos anzeigen)",
"/rss add [URL] (Diesen Feed abonnieren)",
"/rss remove [NR] (Diesen Feed deabonnieren)",
"/rss sync (Feeds aktualisieren)"
2015-06-02 21:52:21 +02:00
},
patterns = {
"^/rss$",
2015-06-08 23:32:11 +02:00
"^/rss (add) (https?://[%w-_%.%?%.:/%+=&]+)$",
"^/rss (remove) (%d+)$",
2015-06-02 21:52:21 +02:00
"^/rss (sync)$"
},
run = run,
2015-07-09 13:08:23 +02:00
cron = cron,
2015-11-12 17:42:03 +01:00
privileged = true,
notyping = true
2015-06-02 21:52:21 +02:00
}