78 lines
2.3 KiB
Python
78 lines
2.3 KiB
Python
from xml.etree import ElementTree as etree
|
|
from urllib.request import Request, urlopen
|
|
from urllib.error import HTTPError, URLError
|
|
from json import loads, dumps
|
|
from re import sub
|
|
|
|
class RSS:
|
|
def __init__(self, state):
|
|
self.name = "RSS"
|
|
self.bot = state["bot"]
|
|
self.alias = state["alias"]
|
|
self.use = state["use"]
|
|
self.source = state["source"]
|
|
self.channels = state["channels"]
|
|
self.memory = state.get("memory", {
|
|
"initialized": False,
|
|
"known": list()
|
|
})
|
|
|
|
def start(self):
|
|
if not self.memory["initialized"]:
|
|
self.memory["initialized"] = True
|
|
self.fetch(self.cache)
|
|
return self.run()
|
|
|
|
def run(self):
|
|
self.fetch(self.mirror)
|
|
return {
|
|
"bot": self.bot,
|
|
"alias": self.alias,
|
|
"use": self.use,
|
|
"source": self.source,
|
|
"channels": self.channels,
|
|
"memory": self.memory
|
|
}
|
|
|
|
def cache(self, item):
|
|
guid = item.findtext("guid", None)
|
|
if guid is not None:
|
|
self.memory["known"].append(guid)
|
|
|
|
def mirror(self, item):
|
|
guid = item.findtext("guid", None)
|
|
if guid is None:
|
|
return
|
|
|
|
if guid in self.memory["known"]:
|
|
return
|
|
|
|
self.memory["known"].append(guid)
|
|
|
|
use = sub(r"(<\/?[^>]+>)|\n", "", item.findtext(self.use, ""))
|
|
user = item.findtext("author", "").split("@")[0]
|
|
metadata = "(posted by {}) <{}>".format(user, guid)
|
|
header = "[{}] {}".format(self.alias, use)
|
|
splitter = " "
|
|
max_size = 450 - len(splitter)
|
|
if len(header) + len(metadata) >= max_size:
|
|
header_size = max_size - len(metadata)
|
|
header = header[:header_size]
|
|
response = "{}{}{}".format(header, splitter, metadata)
|
|
for channel in self.channels:
|
|
self.bot.send_message(channel, response)
|
|
|
|
def fetch(self, callback):
|
|
req = Request(self.source)
|
|
try:
|
|
response = urlopen(req).read()
|
|
except HTTPError:
|
|
return
|
|
except URLError:
|
|
return
|
|
|
|
feed = etree.fromstring(response)
|
|
items = feed.findall("channel/item")
|
|
for item in items:
|
|
callback(item)
|