debugging the backend, adding mail subscribe page, finished VAG zeitung
This commit is contained in:
commit
1f0583da74
|
@ -133,6 +133,11 @@ sudo service nginx restart
|
||||||
sudo cp deployment/ticketfrei-web.service /etc/systemd/system/
|
sudo cp deployment/ticketfrei-web.service /etc/systemd/system/
|
||||||
sudo systemctl daemon-reload
|
sudo systemctl daemon-reload
|
||||||
sudo systemctl start ticketfrei-web.service
|
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
|
### Logs
|
||||||
|
|
15
active_bots/__init__.py
Normal file
15
active_bots/__init__.py
Normal file
|
@ -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)
|
||||||
|
|
|
@ -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
|
|
|
@ -18,7 +18,11 @@ class MastodonBot(Bot):
|
||||||
:return: list of statuses
|
:return: list of statuses
|
||||||
"""
|
"""
|
||||||
mentions = []
|
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:
|
try:
|
||||||
notifications = m.notifications()
|
notifications = m.notifications()
|
||||||
except Exception:
|
except Exception:
|
||||||
|
|
|
@ -13,7 +13,7 @@ logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
class TwitterBot(Bot):
|
class TwitterBot(Bot):
|
||||||
def get_api(self, user):
|
def get_api(self, user):
|
||||||
keys = user.get_api_keys()
|
keys = user.get_twitter_credentials()
|
||||||
auth = tweepy.OAuthHandler(consumer_key=keys[0],
|
auth = tweepy.OAuthHandler(consumer_key=keys[0],
|
||||||
consumer_secret=keys[1])
|
consumer_secret=keys[1])
|
||||||
auth.set_access_token(keys[2], # access_token_key
|
auth.set_access_token(keys[2], # access_token_key
|
||||||
|
@ -27,7 +27,11 @@ class TwitterBot(Bot):
|
||||||
:return: reports: (list of report.Report objects)
|
:return: reports: (list of report.Report objects)
|
||||||
"""
|
"""
|
||||||
reports = []
|
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()
|
last_mention = user.get_seen_tweet()
|
||||||
try:
|
try:
|
||||||
if last_mention == 0:
|
if last_mention == 0:
|
||||||
|
|
|
@ -39,5 +39,5 @@ if __name__ == '__main__':
|
||||||
bot2.post(user, status)
|
bot2.post(user, status)
|
||||||
time.sleep(60) # twitter rate limit >.<
|
time.sleep(60) # twitter rate limit >.<
|
||||||
except Exception:
|
except Exception:
|
||||||
logger.error('Shutdown.', exc_info=True)
|
logger.error("Shutdown.", exc_info=True)
|
||||||
shutdown()
|
shutdown()
|
||||||
|
|
3
bot.py
3
bot.py
|
@ -1,7 +1,8 @@
|
||||||
class Bot(object):
|
class Bot(object):
|
||||||
# returns a list of Report objects
|
# returns a list of Report objects
|
||||||
def crawl(self, user):
|
def crawl(self, user):
|
||||||
pass
|
reports = []
|
||||||
|
return reports
|
||||||
|
|
||||||
# post/boost Report object
|
# post/boost Report object
|
||||||
def post(self, user, report):
|
def post(self, user, report):
|
||||||
|
|
|
@ -9,7 +9,7 @@ ExecStart=/srv/ticketfrei/bin/python3 backend.py
|
||||||
#RuntimeDirectory=uwsgi
|
#RuntimeDirectory=uwsgi
|
||||||
Restart=always
|
Restart=always
|
||||||
KillSignal=SIGQUIT
|
KillSignal=SIGQUIT
|
||||||
Type=notify
|
Type=simple
|
||||||
StandardError=syslog
|
StandardError=syslog
|
||||||
NotifyAccess=all
|
NotifyAccess=all
|
||||||
|
|
||||||
|
|
14
frontend.py
14
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!')
|
return dict(info='There is no Ticketfrei bot in your city yet. Create one yourself!')
|
||||||
|
|
||||||
|
|
||||||
|
@get('/city/mail/<city>')
|
||||||
|
@view('template/mail.tpl')
|
||||||
|
def display_mail_page(city, user):
|
||||||
|
return user.state()
|
||||||
|
|
||||||
|
|
||||||
|
@post('/city/mail/submit/<city>')
|
||||||
|
def subscribe_mail(user, city):
|
||||||
|
email = request.forms['mailaddress']
|
||||||
|
# add confirmation mail workflow
|
||||||
|
user.add_subscriber(email)
|
||||||
|
redirect('/city/' + city)
|
||||||
|
|
||||||
|
|
||||||
@get('/settings')
|
@get('/settings')
|
||||||
@view('template/settings.tpl')
|
@view('template/settings.tpl')
|
||||||
def settings(user):
|
def settings(user):
|
||||||
|
|
Binary file not shown.
Binary file not shown.
15
template/mail.tpl
Normal file
15
template/mail.tpl
Normal file
|
@ -0,0 +1,15 @@
|
||||||
|
% rebase('template/wrapper.tpl')
|
||||||
|
|
||||||
|
<%
|
||||||
|
import markdown as md
|
||||||
|
|
||||||
|
html = md.markdown(markdown)
|
||||||
|
%>
|
||||||
|
|
||||||
|
<form action="/city/mail/submit/<% print(city) %>" method="post">
|
||||||
|
<input type="text" name="mailaddress" placeholder="E-Mail address" id="mailaddress">
|
||||||
|
<input name='confirm' value='Subscribe to E-Mail notifications' type='submit'/>
|
||||||
|
</form>
|
||||||
|
|
||||||
|
|
||||||
|
{{!html}}
|
5
user.py
5
user.py
|
@ -156,6 +156,9 @@ schlitz
|
||||||
(self.uid,))
|
(self.uid,))
|
||||||
return db.cur.fetchone()[0]
|
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):
|
def set_badwords(self, words):
|
||||||
db.execute("UPDATE badwords SET words = ? WHERE user_id = ?;",
|
db.execute("UPDATE badwords SET words = ? WHERE user_id = ?;",
|
||||||
(words, self.uid))
|
(words, self.uid))
|
||||||
|
@ -201,7 +204,7 @@ schlitz
|
||||||
db.commit()
|
db.commit()
|
||||||
|
|
||||||
def get_twitter_token(self):
|
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, ))
|
(self.uid, ))
|
||||||
return db.cur.fetchall()
|
return db.cur.fetchall()
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue