diff --git a/README.md b/README.md index 83c23e2..46f5110 100644 --- a/README.md +++ b/README.md @@ -133,6 +133,11 @@ sudo service nginx restart sudo cp deployment/ticketfrei-web.service /etc/systemd/system/ sudo systemctl daemon-reload sudo systemctl start ticketfrei-web.service + +# create and start the backend systemd service +sudo cp deployment/ticketfrei-backend.service /etc/systemd/system +sudo systemctl daemon-reload +sudo systemctl start ticketfrei-backend.service ``` ### Logs diff --git a/active_bots/__init__.py b/active_bots/__init__.py new file mode 100644 index 0000000..eedb95f --- /dev/null +++ b/active_bots/__init__.py @@ -0,0 +1,15 @@ +__all__ = [] + +import pkgutil +import inspect + +for loader, name, is_pkg in pkgutil.walk_packages(__path__): + module = loader.find_module(name).load_module(name) + + for name, value in inspect.getmembers(module): + if name.startswith('__'): + continue + + globals()[name] = value + __all__.append(name) + diff --git a/active_bots/mailbot.py b/active_bots/mailbot.py deleted file mode 100644 index 995b390..0000000 --- a/active_bots/mailbot.py +++ /dev/null @@ -1,114 +0,0 @@ -#!/usr/bin/env python3 - -from config import config -import logging -import sendmail -import ssl -import datetime -import email -import imaplib -import report -from bot import Bot - - -logger = logging.getLogger(__name__) - - -class Mailbot(Bot): - """ - Bot which sends Mails if mentioned via twitter/mastodon, and tells - other bots that it received mails. - """ - - def login(self, user): - # change to use mailbox of local system - mailinglist = user.get_mailinglist() - mailbox = imaplib.IMAP4_SSL(mailinglist) - context = ssl.create_default_context() - try: - mailbox.starttls(ssl_context=context) - except: - logger.error('StartTLS failed', exc_info=True) - try: - mailbox.login(config["mail"]["user"], - config["mail"]["passphrase"]) - except imaplib.IMAP4.error: - logger.error("Login to mail server failed", exc_info=True) - try: - mailer = sendmail.Mailer() - mailer.send('', config['web']['contact'], - 'Ticketfrei Crash Report', - attachment=config['logging']['logpath']) - except: - logger.error('Mail sending failed', exc_info=True) - - def crawl(self, user): - """ - crawl for new mails. - :return: msgs: (list of report.Report objects) - """ - mailbox = self.login(user) - try: - rv, data = mailbox.select("Inbox") - except imaplib.IMAP4.abort: - logger.error("Crawling Mail failed", exc_info=True) - rv = False - msgs = [] - if rv == 'OK': - rv, data = mailbox.search(None, "ALL") - if rv != 'OK': - return msgs - - for num in data[0].split(): - rv, data = mailbox.fetch(num, '(RFC822)') - if rv != 'OK': - logger.error("Couldn't fetch mail %s %s" % (rv, str(data))) - return msgs - msg = email.message_from_bytes(data[0][1]) - - # check if email was sent by the bot itself. Different solution? - if not user.get_mailinglist() in msg['From']: - # get a comparable date out of the email - date_tuple = email.utils.parsedate_tz(msg['Date']) - date_tuple = datetime.datetime.fromtimestamp( - email.utils.mktime_tz(date_tuple) - ) - date = int((date_tuple - - datetime.datetime(1970, 1, 1)).total_seconds()) - if date > user.get_seen_mail(): - msgs.append(self.make_report(msg)) - return msgs - - def post(self, user, report): - """ - sends reports by other sources to a mailing list. - - :param report: (report.Report object) - """ - mailinglist = self.login(user) - if report.source is not self: - mailer = sendmail.Mailer() - mailer.send(report.text, mailinglist, - "Warnung: Kontrolleure gesehen") - - def make_report(self, msg): - """ - generates a report out of a mail - - :param msg: email.parser.Message object - :return: post: report.Report object - """ - # get a comparable date out of the email - date_tuple = email.utils.parsedate_tz(msg['Date']) - date_tuple = datetime.datetime.fromtimestamp( - email.utils.mktime_tz(date_tuple) - ) - date = (date_tuple - datetime.datetime(1970, 1, 1)).total_seconds() - - author = msg.get("From") # get mail author from email header - # :todo take only the part before the @ - - text = msg.get_payload() - post = report.Report(author, "mail", text, None, date) - self.last_mail = date - return post diff --git a/active_bots/mastodonbot.py b/active_bots/mastodonbot.py index 07a2311..1007110 100755 --- a/active_bots/mastodonbot.py +++ b/active_bots/mastodonbot.py @@ -18,7 +18,11 @@ class MastodonBot(Bot): :return: list of statuses """ mentions = [] - m = Mastodon(*user.get_masto_credentials()) + try: + m = Mastodon(*user.get_masto_credentials()) + except TypeError: + #logger.error("No Mastodon Credentials in database.", exc_info=True) + return mentions try: notifications = m.notifications() except Exception: diff --git a/active_bots/twitterbot.py b/active_bots/twitterbot.py index fdf6045..696ed56 100755 --- a/active_bots/twitterbot.py +++ b/active_bots/twitterbot.py @@ -13,7 +13,7 @@ logger = logging.getLogger(__name__) class TwitterBot(Bot): def get_api(self, user): - keys = user.get_api_keys() + keys = user.get_twitter_credentials() auth = tweepy.OAuthHandler(consumer_key=keys[0], consumer_secret=keys[1]) auth.set_access_token(keys[2], # access_token_key @@ -27,7 +27,11 @@ class TwitterBot(Bot): :return: reports: (list of report.Report objects) """ reports = [] - api = self.get_api(user) + try: + api = self.get_api(user) + except Exception: + #logger.error("Error Authenticating Twitter", exc_info=True) + return reports last_mention = user.get_seen_tweet() try: if last_mention == 0: diff --git a/backend.py b/backend.py index b66fcfa..77189f3 100755 --- a/backend.py +++ b/backend.py @@ -39,5 +39,5 @@ if __name__ == '__main__': bot2.post(user, status) time.sleep(60) # twitter rate limit >.< except Exception: - logger.error('Shutdown.', exc_info=True) + logger.error("Shutdown.", exc_info=True) shutdown() diff --git a/bot.py b/bot.py index b003ab8..c288140 100644 --- a/bot.py +++ b/bot.py @@ -1,7 +1,8 @@ class Bot(object): # returns a list of Report objects def crawl(self, user): - pass + reports = [] + return reports # post/boost Report object def post(self, user, report): diff --git a/deployment/ticketfrei-backend.service b/deployment/ticketfrei-backend.service index db95b88..87dce2e 100644 --- a/deployment/ticketfrei-backend.service +++ b/deployment/ticketfrei-backend.service @@ -9,7 +9,7 @@ ExecStart=/srv/ticketfrei/bin/python3 backend.py #RuntimeDirectory=uwsgi Restart=always KillSignal=SIGQUIT -Type=notify +Type=simple StandardError=syslog NotifyAccess=all diff --git a/frontend.py b/frontend.py index 969bea6..943a62a 100755 --- a/frontend.py +++ b/frontend.py @@ -87,6 +87,20 @@ def city_page(city): return dict(info='There is no Ticketfrei bot in your city yet. Create one yourself!') +@get('/city/mail/') +@view('template/mail.tpl') +def display_mail_page(city, user): + return user.state() + + +@post('/city/mail/submit/') +def subscribe_mail(user, city): + email = request.forms['mailaddress'] + # add confirmation mail workflow + user.add_subscriber(email) + redirect('/city/' + city) + + @get('/settings') @view('template/settings.tpl') def settings(user): diff --git a/promotion/vag-zeitung.xcf b/promotion/vag-zeitung.xcf index 3cad778..9a63e97 100644 Binary files a/promotion/vag-zeitung.xcf and b/promotion/vag-zeitung.xcf differ diff --git a/promotion/vag-zeitung_p02.xcf b/promotion/vag-zeitung_p02.xcf index a85c299..cf2ec66 100644 Binary files a/promotion/vag-zeitung_p02.xcf and b/promotion/vag-zeitung_p02.xcf differ diff --git a/template/mail.tpl b/template/mail.tpl new file mode 100644 index 0000000..2b16981 --- /dev/null +++ b/template/mail.tpl @@ -0,0 +1,15 @@ +% rebase('template/wrapper.tpl') + +<% +import markdown as md + +html = md.markdown(markdown) +%> + +
+ + +
+ + +{{!html}} diff --git a/user.py b/user.py index 9823c78..ae4a82c 100644 --- a/user.py +++ b/user.py @@ -156,6 +156,9 @@ schlitz (self.uid,)) return db.cur.fetchone()[0] + def add_subscriber(self, email): + db.execute("INSERT INTO mailinglist(user_id, email, active VALUES(?, ?, ?);", (self.uid, email, 1)) + def set_badwords(self, words): db.execute("UPDATE badwords SET words = ? WHERE user_id = ?;", (words, self.uid)) @@ -201,7 +204,7 @@ schlitz db.commit() def get_twitter_token(self): - db.execute("SELECT access_token, access_token_secret FROM twitter_accouts WHERE user_id = ?;", + db.execute("SELECT client_id, client_secret FROM twitter_accounts WHERE user_id = ?;", (self.uid, )) return db.cur.fetchall()