Code-Refactor

This commit is contained in:
Andreas Bielawski 2016-12-13 21:20:02 +01:00
parent 4d9a498e50
commit 39b9b6a23f

446
bot.py
View File

@ -4,28 +4,26 @@
# RSS Bot # RSS Bot
# Python 3 required # Python 3 required
import logging
import re import re
import redis
import feedparser
from json import loads
from configparser import ConfigParser from configparser import ConfigParser
from json import loads
from urllib.parse import urlparse
import feedparser
import redis
from bs4 import BeautifulSoup
from telegram import ChatAction, ParseMode from telegram import ChatAction, ParseMode
from telegram.error import TelegramError, Unauthorized, BadRequest, TimedOut, NetworkError, ChatMigrated
from telegram.ext import Updater, Job, CommandHandler, MessageHandler, Filters from telegram.ext import Updater, Job, CommandHandler, MessageHandler, Filters
from telegram.ext.dispatcher import run_async from telegram.ext.dispatcher import run_async
from telegram.error import (TelegramError, Unauthorized, BadRequest,
TimedOut, NetworkError, ChatMigrated)
import logging
from bs4 import BeautifulSoup
from urllib.parse import urlparse
# Bot Configuration # Bot Configuration
config = ConfigParser() config = ConfigParser()
config.read_file(open('config.ini')) config.read_file(open('config.ini'))
redis_conf = config['REDIS'] redis_conf = config['REDIS']
redis_db = redis_conf.get('db' , 0) redis_db = redis_conf.get('db', 0)
redis_host = redis_conf.get('host') redis_host = redis_conf.get('host')
redis_port = redis_conf.get('port', 6379) redis_port = redis_conf.get('port', 6379)
redis_socket = redis_conf.get('socket_path') redis_socket = redis_conf.get('socket_path')
@ -51,6 +49,7 @@ if not r.ping():
print('Konnte nicht mit Redis verbinden, prüfe deine Einstellungen') print('Konnte nicht mit Redis verbinden, prüfe deine Einstellungen')
quit() quit()
def is_number(s): def is_number(s):
try: try:
float(s) float(s)
@ -58,113 +57,125 @@ def is_number(s):
except ValueError: except ValueError:
return False return False
def remove_tags(html): def remove_tags(html):
return ''.join(BeautifulSoup(html, "html.parser").findAll(text=True)) return ''.join(BeautifulSoup(html, "html.parser").findAll(text=True))
def can_use(update): def can_use(update):
if update.message.from_user.id in admins: if update.message.from_user.id in admins:
return True return True
else: else:
return False return False
def cleanRSS(str): def cleanRSS(str):
str = str.replace('[…]', '') str = str.replace('[…]', '')
str = str.replace('[bilder]', '') str = str.replace('[bilder]', '')
str = str.replace('[mehr]', '') str = str.replace('[mehr]', '')
str = str.replace('[video]', '') str = str.replace('[video]', '')
str = str.replace('...[more]', '') str = str.replace('...[more]', '')
str = str.replace('[more]', '') str = str.replace('[more]', '')
str = str.replace('[liveticker]', '') str = str.replace('[liveticker]', '')
str = str.replace('[livestream]', '') str = str.replace('[livestream]', '')
str = str.replace('[multimedia]', '') str = str.replace('[multimedia]', '')
str = str.replace('[phoenix]', '') str = str.replace('[phoenix]', '')
str = str.replace('[swr]', '') str = str.replace('[swr]', '')
str = str.replace('[ndr]', '') str = str.replace('[ndr]', '')
str = str.replace('[mdr]', '') str = str.replace('[mdr]', '')
str = str.replace('[rbb]', '') str = str.replace('[rbb]', '')
str = str.replace('[wdr]', '') str = str.replace('[wdr]', '')
str = str.replace('[hr]', '') str = str.replace('[hr]', '')
str = str.replace('[br]', '') str = str.replace('[br]', '')
str = str.replace('Click for full.', '') str = str.replace('Click for full.', '')
str = str.replace('Read more »', '') str = str.replace('Read more »', '')
str = str.replace('Read more', '') str = str.replace('Read more', '')
str = str.replace('(more…)', '') str = str.replace('(more…)', '')
str = str.replace('View On WordPress', '') str = str.replace('View On WordPress', '')
str = str.replace('Continue reading →', '') str = str.replace('Continue reading →', '')
str = str.replace('(RSS generated with FetchRss)', '') str = str.replace('(RSS generated with FetchRss)', '')
str = str.replace('-- Delivered by Feed43 service', '') str = str.replace('-- Delivered by Feed43 service', '')
str = str.replace('Meldung bei www.tagesschau.de lesen', '') str = str.replace('Meldung bei www.tagesschau.de lesen', '')
str = str.replace('The post.*appeared first on Sugoi! Anime Blog.', '') str = str.replace('The post.*appeared first on Sugoi! Anime Blog.', '')
str = str.replace('Der Beitrag.*erschien zuerst auf MAnime.de.', '') str = str.replace('Der Beitrag.*erschien zuerst auf MAnime.de.', '')
str = re.sub('http://www\.serienjunkies.de/.*\.html', '', str) str = re.sub('http://www\.serienjunkies.de/.*\.html', '', str)
return str return str
def check_chat(bot, username): def check_chat(bot, username):
try: try:
return bot.getChat(username) return bot.getChat(username)
except: except:
return return
# Commands # Commands
@run_async @run_async
def start(bot, update): def start(bot, update):
if not can_use(update): if not can_use(update):
return return
bot.sendMessage( bot.sendMessage(
chat_id = update.message.chat_id, chat_id=update.message.chat_id,
text = '<b>Willkommen beim RSS-Bot!</b>\nLass uns anfangen! Sende /hilfe, um zu starten.', text='<b>Willkommen beim RSS-Bot!</b>\nLass uns anfangen! Sende /hilfe, um zu starten.',
reply_to_message_id = update.message.message_id, reply_to_message_id=update.message.message_id,
parse_mode = ParseMode.HTML parse_mode=ParseMode.HTML
) )
@run_async @run_async
def help(bot, update): def help(bot, update):
if not can_use(update): if not can_use(update):
return return
bot.sendMessage( bot.sendMessage(
chat_id = update.message.chat_id, chat_id=update.message.chat_id,
text = '<b>/rss</b>: Abonnierte Feeds anzeigen\n<b>/sub</b> <i>Feed-URL</i>: Feed abonnieren\n<b>/del</b> <i>n</i>: Feed löschen', text='<b>/rss</b>: Abonnierte Feeds anzeigen\n<b>/sub</b> <i>Feed-URL</i>: Feed abonnieren\n<b>/del</b> <i>n</i>: Feed löschen',
reply_to_message_id = update.message.message_id, reply_to_message_id=update.message.message_id,
parse_mode = ParseMode.HTML parse_mode=ParseMode.HTML
) )
def subscribe_to_rss(bot, update, args): def subscribe_to_rss(bot, update, args):
if not can_use(update): if not can_use(update):
return return
if len(args) < 1: if len(args) < 1:
bot.sendMessage(chat_id=update.message.chat_id, text='Bitte gebe eine Feed-URL ein.', reply_to_message_id=update.message.message_id) bot.sendMessage(chat_id=update.message.chat_id, text='Bitte gebe eine Feed-URL ein.',
return reply_to_message_id=update.message.message_id)
return
feed_url = args[0] feed_url = args[0]
is_url = re.search("http[s]?://(?:[a-zA-Z]|[0-9]|[$-_@.&+]|[!*\(\),]|(?:%[0-9a-fA-F][0-9a-fA-F]))+", feed_url) is_url = re.search("http[s]?://(?:[a-zA-Z]|[0-9]|[$-_@.&+]|[!*\(\),]|(?:%[0-9a-fA-F][0-9a-fA-F]))+", feed_url)
if not is_url: if not is_url:
bot.sendMessage(chat_id=update.message.chat_id, text='Dies ist keine URL.', reply_to_message_id=update.message.message_id) bot.sendMessage(chat_id=update.message.chat_id, text='Dies ist keine URL.',
return reply_to_message_id=update.message.message_id)
return
if len(args) > 1: if len(args) > 1:
username = args[1] username = args[1]
chat_info = check_chat(bot, username) chat_info = check_chat(bot, username)
if not chat_info: if not chat_info:
bot.sendMessage(chat_id=update.message.chat_id, text='Dieser Kanal existiert nicht!', reply_to_message_id=update.message.message_id) bot.sendMessage(chat_id=update.message.chat_id, text='Dieser Kanal existiert nicht!',
return reply_to_message_id=update.message.message_id)
chat_id = str(chat_info.id) return
chat_id = str(chat_info.id)
else: else:
chat_id = str(update.message.chat_id) chat_id = str(update.message.chat_id)
if r.sismember('pythonbot:rss:' + chat_id, feed_url): if r.sismember('pythonbot:rss:' + chat_id, feed_url):
bot.sendMessage(chat_id=update.message.chat_id, text='Dieser Feed wurde bereits abonniert.', reply_to_message_id=update.message.message_id) bot.sendMessage(chat_id=update.message.chat_id, text='Dieser Feed wurde bereits abonniert.',
return reply_to_message_id=update.message.message_id)
return
bot.sendChatAction(update.message.chat_id, action=ChatAction.TYPING) bot.sendChatAction(update.message.chat_id, action=ChatAction.TYPING)
feed_data = feedparser.parse(feed_url) feed_data = feedparser.parse(feed_url)
if not 'link' in feed_data.feed: if not 'link' in feed_data.feed:
bot.sendMessage(chat_id=update.message.chat_id, text='Kein gültiger Feed.',reply_to_message_id=update.message.message_id) bot.sendMessage(chat_id=update.message.chat_id, text='Kein gültiger Feed.',
return reply_to_message_id=update.message.message_id)
return
if not 'title' in feed_data.feed: if not 'title' in feed_data.feed:
feed_title = 'Unbekannten Feed' feed_title = 'Unbekannten Feed'
else: else:
feed_title = feed_data.feed.title feed_title = feed_data.feed.title
if len(feed_data.entries) > 0: if len(feed_data.entries) > 0:
if not 'id' in feed_data.entries[0]: if not 'id' in feed_data.entries[0]:
last_entry = feed_data.entries[0].link last_entry = feed_data.entries[0].link
@ -172,191 +183,202 @@ def subscribe_to_rss(bot, update, args):
last_entry = feed_data.entries[0].id last_entry = feed_data.entries[0].id
lhash = 'pythonbot:rss:' + feed_url + ':last_entry' lhash = 'pythonbot:rss:' + feed_url + ':last_entry'
if not r.exists(lhash): if not r.exists(lhash):
r.set(lhash, last_entry) r.set(lhash, last_entry)
r.sadd('pythonbot:rss:' + feed_url + ':subs', int(chat_id)) r.sadd('pythonbot:rss:' + feed_url + ':subs', int(chat_id))
r.sadd('pythonbot:rss:' + chat_id, feed_url) r.sadd('pythonbot:rss:' + chat_id, feed_url)
bot.sendMessage( bot.sendMessage(
chat_id = update.message.chat_id, chat_id=update.message.chat_id,
text = '<b>' + feed_title + '</b> hinzugefügt!', text='<b>' + feed_title + '</b> hinzugefügt!',
reply_to_message_id = update.message.message_id, reply_to_message_id=update.message.message_id,
parse_mode = ParseMode.HTML parse_mode=ParseMode.HTML
) )
def unsubscribe_rss(bot, update, args): def unsubscribe_rss(bot, update, args):
if not can_use(update): if not can_use(update):
return
if len(args) < 1:
bot.sendMessage(chat_id=update.message.chat_id, text='Bitte gebe eine Nummer ein', reply_to_message_id=update.message.message_id)
return
if len(args) > 1:
username = args[1]
chat_info = check_chat(bot, username)
if not chat_info:
bot.sendMessage(chat_id=update.message.chat_id, text='Dieser Kanal existiert nicht!', reply_to_message_id=update.message.message_id)
return return
chat_id = str(chat_info.id)
if len(args) < 1:
bot.sendMessage(chat_id=update.message.chat_id, text='Bitte gebe eine Nummer ein',
reply_to_message_id=update.message.message_id)
return
if len(args) > 1:
username = args[1]
chat_info = check_chat(bot, username)
if not chat_info:
bot.sendMessage(chat_id=update.message.chat_id, text='Dieser Kanal existiert nicht!',
reply_to_message_id=update.message.message_id)
return
chat_id = str(chat_info.id)
else: else:
chat_id = str(update.message.chat_id) chat_id = str(update.message.chat_id)
if not is_number(args[0]): if not is_number(args[0]):
bot.sendMessage(chat_id=update.message.chat_id, text='Bitte gebe eine Nummer ein.', reply_to_message_id=update.message.message_id) bot.sendMessage(chat_id=update.message.chat_id, text='Bitte gebe eine Nummer ein.',
return reply_to_message_id=update.message.message_id)
return
uhash = 'pythonbot:rss:' + chat_id uhash = 'pythonbot:rss:' + chat_id
n = int(args[0]) n = int(args[0])
subs = list(r.smembers(uhash)) subs = list(r.smembers(uhash))
if n < 1 or n > len(subs): if n < 1 or n > len(subs):
bot.sendMessage(chat_id=update.message.chat_id, text='Abonnement-ID ist zu hoch.', reply_to_message_id=update.message.message_id) bot.sendMessage(chat_id=update.message.chat_id, text='Abonnement-ID ist zu hoch.',
reply_to_message_id=update.message.message_id)
return return
sub = subs[n-1] sub = subs[n - 1]
lhash = 'pythonbot:rss:' + sub + ':subs' lhash = 'pythonbot:rss:' + sub + ':subs'
r.srem(uhash, sub) r.srem(uhash, sub)
r.srem(lhash, int(chat_id)) r.srem(lhash, int(chat_id))
bot.sendMessage( bot.sendMessage(
chat_id = update.message.chat_id, chat_id=update.message.chat_id,
text = '<b>' + sub + '</b> entfernt.', text='<b>' + sub + '</b> entfernt.',
reply_to_message_id = update.message.message_id, reply_to_message_id=update.message.message_id,
parse_mode = ParseMode.HTML parse_mode=ParseMode.HTML
) )
left = r.smembers(lhash) left = r.smembers(lhash)
if len(left) < 1: # no one subscribed, remove it if len(left) < 1: # no one subscribed, remove it
r.delete('pythonbot:rss:' + sub + ':last_entry') r.delete('pythonbot:rss:' + sub + ':last_entry')
def get_rss_list(chat_id, chat_name): def get_rss_list(chat_id, chat_name):
uhash = 'pythonbot:rss:' + chat_id uhash = 'pythonbot:rss:' + chat_id
subs = list(r.smembers(uhash)) subs = list(r.smembers(uhash))
if len(subs) < 1: if len(subs) < 1:
return '<b>Keine Feeds abonniert!</b>' return '<b>Keine Feeds abonniert!</b>'
text = '<b>' + chat_name + '</b> hat abonniert:\n' text = '<b>' + chat_name + '</b> hat abonniert:\n'
for n, feed in enumerate(subs): for n, feed in enumerate(subs):
text = text + str(n+1) + ') ' + feed + '\n' text = text + str(n + 1) + ') ' + feed + '\n'
return text return text
@run_async
@run_async
def list_rss(bot, update, args): def list_rss(bot, update, args):
if not can_use(update): if not can_use(update):
return
if len(args) == 1:
username = args[0]
chat_info = check_chat(bot, username)
if not chat_info:
bot.sendMessage(chat_id=update.message.chat_id, text='Dieser Kanal existiert nicht!', reply_to_message_id=update.message.message_id)
return return
rss_list = get_rss_list(str(chat_info.id), chat_info.title) if len(args) == 1:
username = args[0]
chat_info = check_chat(bot, username)
if not chat_info:
bot.sendMessage(chat_id=update.message.chat_id, text='Dieser Kanal existiert nicht!',
reply_to_message_id=update.message.message_id)
return
rss_list = get_rss_list(str(chat_info.id), chat_info.title)
else: else:
if update.message.chat.first_name: if update.message.chat.first_name:
chat_name = update.message.chat.first_name chat_name = update.message.chat.first_name
else: else:
chat_name = update.message.chat.title chat_name = update.message.chat.title
rss_list = get_rss_list(str(update.message.chat_id), chat_name) rss_list = get_rss_list(str(update.message.chat_id), chat_name)
bot.sendMessage( bot.sendMessage(
chat_id=update.message.chat_id, chat_id=update.message.chat_id,
text = rss_list, text=rss_list,
reply_to_message_id=update.message.message_id, reply_to_message_id=update.message.message_id,
parse_mode=ParseMode.HTML parse_mode=ParseMode.HTML
) )
def get_new_entries(last, new_entries): def get_new_entries(last, new_entries):
entries = [] entries = []
for k,v in enumerate(new_entries): for k, v in enumerate(new_entries):
if 'id' in v: if 'id' in v:
if v.id == last: if v.id == last:
return entries return entries
else:
entries.append(v)
else: else:
entries.append(v) if v.link == last:
else: return entries
if v.link == last: else:
return entries entries.append(v)
else:
entries.append(v)
return entries return entries
def manually_check_rss(bot, update): def manually_check_rss(bot, update):
if not can_use(update): if not can_use(update):
return return
check_rss(bot, '') check_rss(bot, '')
bot.sendMessage( bot.sendMessage(
chat_id=update.message.chat_id, chat_id=update.message.chat_id,
text = 'Ausgeführt.', text='Ausgeführt.',
reply_to_message_id=update.message.message_id reply_to_message_id=update.message.message_id
) )
@run_async @run_async
def check_rss(bot, job): def check_rss(bot, job):
keys = list(r.keys('pythonbot:rss:*:subs')) keys = list(r.keys('pythonbot:rss:*:subs'))
for k, v in enumerate(keys): for k, v in enumerate(keys):
p = re.compile('pythonbot:rss:(.+):subs') p = re.compile('pythonbot:rss:(.+):subs')
match_func = p.search(v) match_func = p.search(v)
url = match_func.group(1) url = match_func.group(1)
print('RSS: ' + url) print('RSS: ' + url)
last = r.get('pythonbot:rss:' + url + ':last_entry') last = r.get('pythonbot:rss:' + url + ':last_entry')
feed_data = feedparser.parse(url) feed_data = feedparser.parse(url)
if feed_data.status < 400: if feed_data.status < 400:
if not 'title' in feed_data.feed: if not 'title' in feed_data.feed:
feed_title = feed_data.feed.link feed_title = feed_data.feed.link
else:
feed_title = feed_data.feed.title
newentr = get_new_entries(last, feed_data.entries)
text = ''
for k2, v2 in enumerate(newentr):
if not 'title' in v2:
title = 'Kein Titel'
else: else:
title = remove_tags(v2.title).lstrip() feed_title = feed_data.feed.title
if not 'link' in v2: newentr = get_new_entries(last, feed_data.entries)
link = feed_data.feed.link text = ''
link_name = link for k2, v2 in enumerate(newentr):
else: if not 'title' in v2:
link = v2.link title = 'Kein Titel'
f = re.search('^https?://feedproxy\.google\.com/~r/(.+?)/.*', link) # feedproxy.google.com else:
if f: title = remove_tags(v2.title).lstrip()
link_name = f.group(1) if not 'link' in v2:
else: link = feed_data.feed.link
link_name = urlparse(link).netloc link_name = link
link_name = re.sub('^www\d?\.', '', link_name) # www. else:
if 'content' in v2: link = v2.link
content = remove_tags(v2.content[0].value).lstrip() f = re.search('^https?://feedproxy\.google\.com/~r/(.+?)/.*', link) # feedproxy.google.com
content = cleanRSS(content) if f:
if len(content) > 250: link_name = f.group(1)
content = content[0:250] + '...' else:
elif 'summary' in v2: link_name = urlparse(link).netloc
content = remove_tags(v2.summary).lstrip() link_name = re.sub('^www\d?\.', '', link_name) # www.
content = cleanRSS(content) if 'content' in v2:
if len(content) > 250: content = remove_tags(v2.content[0].value).lstrip()
content = content[0:250] + '...' content = cleanRSS(content)
else: if len(content) > 250:
content = '' content = content[0:250] + '...'
# Für 1 Nachricht pro Beitrag, tue dies: elif 'summary' in v2:
# Entferne hier das "text + "... content = remove_tags(v2.summary).lstrip()
text = text + '\n<b>' + title + '</b>\n<i>' + feed_title + '</i>\n' + content + '\n<a href="' + link + '">Auf ' + link_name + ' weiterlesen</a>\n' content = cleanRSS(content)
# ...und setze hier vor jeder Zeile 2 zusätzliche Leerzeichen if len(content) > 250:
if text != '': content = content[0:250] + '...'
if not 'id' in newentr[0]: else:
newlast = newentr[0].link content = ''
else: # Für 1 Nachricht pro Beitrag, tue dies:
newlast = newentr[0].id # Entferne hier das "text + "...
r.set('pythonbot:rss:' + url + ':last_entry', newlast) text = text + '\n<b>' + title + '</b>\n<i>' + feed_title + '</i>\n' + content + '\n<a href="' + link + '">Auf ' + link_name + ' weiterlesen</a>\n'
for k2, receiver in enumerate(list(r.smembers(v))): # ...und setze hier vor jeder Zeile 2 zusätzliche Leerzeichen
try: if text != '':
bot.sendMessage(receiver, text, parse_mode=ParseMode.HTML, disable_web_page_preview=True) if not 'id' in newentr[0]:
except Unauthorized: newlast = newentr[0].link
print('Chat ' + receiver + ' existiert nicht mehr, lösche aus Abonnenten-Liste') else:
r.srem(v, receiver) newlast = newentr[0].id
r.delete('pythonbot:rss:' + receiver) r.set('pythonbot:rss:' + url + ':last_entry', newlast)
except ChatMigrated as e: for k2, receiver in enumerate(list(r.smembers(v))):
print('Chat migriert: ' + receiver + ' -> ' + str(e.new_chat_id)) try:
r.srem(v, receiver) bot.sendMessage(receiver, text, parse_mode=ParseMode.HTML, disable_web_page_preview=True)
r.sadd(v, e.new_chat_id) except Unauthorized:
r.rename('pythonbot:rss:' + receiver, 'pythonbot:rss:' + str(e.new_chat_id)) print('Chat ' + receiver + ' existiert nicht mehr, lösche aus Abonnenten-Liste')
bot.sendMessage(e.new_chat_id, text, parse_mode=ParseMode.HTML, disable_web_page_preview=True) r.srem(v, receiver)
else: r.delete('pythonbot:rss:' + receiver)
print('HTTP-Fehler: ' + str(feed_data.status)) except ChatMigrated as e:
print('Chat migriert: ' + receiver + ' -> ' + str(e.new_chat_id))
r.srem(v, receiver)
r.sadd(v, e.new_chat_id)
r.rename('pythonbot:rss:' + receiver, 'pythonbot:rss:' + str(e.new_chat_id))
bot.sendMessage(e.new_chat_id, text, parse_mode=ParseMode.HTML, disable_web_page_preview=True)
else:
print('HTTP-Fehler: ' + str(feed_data.status))
print('----------') print('----------')
def error(bot, update, error): def error(bot, update, error):
logger.warn('Update "%s" verursachte Fehler "%s"' % (update, error)) logger.warn('Update "%s" verursachte Fehler "%s"' % (update, error))
@ -365,7 +387,7 @@ def main():
# Create the EventHandler and pass it your bot's token. # Create the EventHandler and pass it your bot's token.
updater = Updater(token=config['DEFAULT']['token']) updater = Updater(token=config['DEFAULT']['token'])
j = updater.job_queue j = updater.job_queue
# Bot-Infos prüfen # Bot-Infos prüfen
bot_info = updater.bot.getMe() bot_info = updater.bot.getMe()
print('Starte ' + bot_info.first_name + ', AKA @' + bot_info.username + ' (' + str(bot_info.id) + ')') print('Starte ' + bot_info.first_name + ', AKA @' + bot_info.username + ' (' + str(bot_info.id) + ')')
@ -377,7 +399,7 @@ def main():
dp.add_handler(CommandHandler("start", start)) dp.add_handler(CommandHandler("start", start))
dp.add_handler(CommandHandler("help", help)) dp.add_handler(CommandHandler("help", help))
dp.add_handler(CommandHandler("hilfe", help)) dp.add_handler(CommandHandler("hilfe", help))
dp.add_handler(CommandHandler("rss", list_rss, pass_args=True)) dp.add_handler(CommandHandler("rss", list_rss, pass_args=True))
dp.add_handler(CommandHandler("sub", subscribe_to_rss, pass_args=True)) dp.add_handler(CommandHandler("sub", subscribe_to_rss, pass_args=True))
dp.add_handler(CommandHandler("del", unsubscribe_rss, pass_args=True)) dp.add_handler(CommandHandler("del", unsubscribe_rss, pass_args=True))
@ -385,7 +407,7 @@ def main():
# log all errors # log all errors
dp.add_error_handler(error) dp.add_error_handler(error)
# cron # cron
job_minute = Job(check_rss, 60.0) job_minute = Job(check_rss, 60.0)
j.put(job_minute, next_t=10.0) j.put(job_minute, next_t=10.0)