From 2a9c5c657ffd4da5fbcd9ac505ab398e05f0c18d Mon Sep 17 00:00:00 2001
From: b3yond
Date: Fri, 25 May 2018 15:57:20 +0200
Subject: [PATCH] you can now set goodlist & blacklist in settings. render city
page #18. fixed #24 and #25.
---
README.md | 2 +-
db.py | 31 ++++--
frontend.py | 16 ++-
template/city.tpl | 7 +-
template/settings.tpl | 12 ++-
user.py | 228 ++++++++++++++++++++++++------------------
6 files changed, 188 insertions(+), 108 deletions(-)
diff --git a/README.md b/README.md
index 7b4603d..2bdc8d7 100644
--- a/README.md
+++ b/README.md
@@ -91,7 +91,7 @@ virtualenv -p python3 .
Install the dependencies:
```shell
-pip install tweepy pytoml Mastodon.py bottle pyjwt pylibscrypt
+pip install tweepy pytoml Mastodon.py bottle pyjwt pylibscrypt Markdown
```
Configure the bot:
diff --git a/db.py b/db.py
index ac4999d..0259a85 100644
--- a/db.py
+++ b/db.py
@@ -42,13 +42,13 @@ class DB(object):
CREATE TABLE IF NOT EXISTS triggerpatterns (
id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT UNIQUE,
user_id INTEGER,
- pattern TEXT,
+ patterns TEXT,
FOREIGN KEY(user_id) REFERENCES user(id)
);
CREATE TABLE IF NOT EXISTS badwords (
id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT UNIQUE,
user_id INTEGER,
- word TEXT,
+ words TEXT,
FOREIGN KEY(user_id) REFERENCES user(id)
);
CREATE TABLE IF NOT EXISTS mastodon_instances (
@@ -146,10 +146,29 @@ class DB(object):
self.execute("INSERT INTO user (passhash) VALUES(?);",
(json['passhash'], ))
uid = self.cur.lastrowid
- self.execute("""
- INSERT INTO triggerpatterns (user_id, pattern)
- VALUES(?, ?);
- """, (uid, '.*'))
+ default_triggerpatterns = """
+kontroll?e
+konti
+db
+vgn
+vag
+zivil
+sicherheit
+uniform
+station
+bus
+bahn
+tram
+linie
+nuernberg
+nürnberg
+s\d
+u\d\d?
+ """
+ self.execute("""INSERT INTO triggerpatterns (user_id, patterns)
+ VALUES(?, ?); """, (uid, default_triggerpatterns))
+ self.execute("INSERT INTO badwords (user_id, words) VALUES(?, ?);",
+ (uid, ""))
else:
uid = json['uid']
self.execute("INSERT INTO email (user_id, email) VALUES(?, ?);",
diff --git a/frontend.py b/frontend.py
index 43ca54d..07aff7f 100755
--- a/frontend.py
+++ b/frontend.py
@@ -38,7 +38,7 @@ def register_post():
return dict(error='Email address already in use.')
# send confirmation mail
try:
- # print(url('confirm/' + city + '/%s' % db.user_token(email, password))) # only for local testing
+ print(url('confirm/' + city + '/%s' % db.user_token(email, password))) # only for local testing
sendmail(
email,
"Confirm your account",
@@ -93,6 +93,20 @@ def settings(user):
return user.state()
+@post('/settings/goodlist')
+@view('template/settings.tpl')
+def update_trigger_patterns(user):
+ user.set_trigger_words(request.forms['goodlist'])
+ return user.state()
+
+
+@post('/settings/blacklist')
+@view('template/settings.tpl')
+def update_badwords(user):
+ user.set_badwords(request.forms['blacklist'])
+ return user.state()
+
+
@get('/api/state')
def api_enable(user):
return user.state()
diff --git a/template/city.tpl b/template/city.tpl
index d102660..dddac8d 100644
--- a/template/city.tpl
+++ b/template/city.tpl
@@ -1,4 +1,9 @@
% rebase('template/wrapper.tpl')
-$markdown.render()
+<%
+import markdown as md
+html = md.markdown(markdown)
+%>
+
+{{html}}
diff --git a/template/settings.tpl b/template/settings.tpl
index 32ab147..ea9c35d 100644
--- a/template/settings.tpl
+++ b/template/settings.tpl
@@ -1,7 +1,11 @@
% rebase('template/wrapper.tpl')
-
asdf
+% if enabled:
+
Disable
+% else:
+
Enable
+% end
@@ -86,7 +90,7 @@
@@ -100,7 +104,7 @@
diff --git a/user.py b/user.py
index 08fd505..96d88b8 100644
--- a/user.py
+++ b/user.py
@@ -27,7 +27,7 @@ class User(object):
@property
def enabled(self):
- db.execute("SELECT enabled FROM user WHERE user_id=?;", (self.uid, ))
+ db.execute("SELECT enabled FROM user WHERE id=?;", (self.uid, ))
return bool(db.cur.fetchone()[0])
@enabled.setter
@@ -59,16 +59,35 @@ class User(object):
def is_appropriate(self, report):
db.execute("SELECT pattern FROM triggerpatterns WHERE user_id=?;",
(self.uid, ))
- for pattern, in db.cur.fetchall():
+ patterns = db.cur.fetchone()
+ for pattern in patterns.splitlines():
if pattern.search(report.text) is not None:
break
else:
# no pattern matched
return False
+ default_badwords = """
+bastard
+bitch
+whore
+hitler
+slut
+hure
+jude
+schwuchtel
+fag
+faggot
+nigger
+neger
+schlitz
+ """
db.execute("SELECT word FROM badwords WHERE user_id=?;",
(self.uid, ))
- badwords = [word.lower() for word, in db.cur.fetchall()]
- for word in report.text.lower().split():
+ badwords = db.cur.fetchone()
+ for word in report.text.lower().splitlines():
+ if word in badwords:
+ return False
+ for word in default_badwords.splitlines():
if word in badwords:
return False
return True
@@ -129,8 +148,22 @@ class User(object):
db.execute("UPDATE seen_mail SET mail_date = ? WHERE user_id = ?;",
(mail_date, self.uid))
- def get_trigger_words(self, table):
- db.execute("SELECT words FROM ? WHERE user_id = ?;", (table, self.uid,))
+ def set_trigger_words(self, patterns):
+ db.execute("UPDATE triggerpatterns SET patterns = ? WHERE user_id = ?;",
+ (patterns, self.uid))
+
+ def get_trigger_words(self):
+ db.execute("SELECT patterns FROM triggerpatterns WHERE user_id = ?;",
+ (self.uid,))
+ return db.cur.fetchone()[0]
+
+ def set_badwords(self, words):
+ db.execute("UPDATE badwords SET words = ? WHERE user_id = ?;",
+ (words, self.uid))
+
+ def get_badwords(self):
+ db.execute("SELECT words FROM badwords WHERE user_id = ?;",
+ (self.uid,))
return db.cur.fetchone()[0]
def state(self):
@@ -142,7 +175,12 @@ class User(object):
# - logged in with twitter?
# - logged in with mastodon?
# - enabled?
- return dict(foo='bar')
+ citydict = db.user_facing_properties(self.get_city())
+ return dict(city=citydict['city'],
+ markdown=citydict['markdown'],
+ triggerwords=self.get_trigger_words(),
+ badwords=self.get_badwords(),
+ enabled=self.enabled)
def save_request_token(self, token):
db.execute("INSERT INTO twitter_request_tokens(user_id, request_token, request_token_secret) VALUES(?, ?, ?);",
@@ -191,99 +229,99 @@ class User(object):
db.commit()
def get_city(self):
- db.execute("SELECT city FROM user WHERE id == ?;", (self.uid, ))
+ db.execute("SELECT city FROM cities WHERE user_id == ?;", (self.uid, ))
return db.cur.fetchone()[0]
def set_city(self, city):
- masto_link = "masto.social/@" + city # get masto_link
- twit_link = "twitter.com/" + city # get twit_link
+ masto_link = "example.mastodon.social/@" + city # get masto_link
+ twit_link = "example.twitter.com/" + city # get twit_link
mailinglist = city + "@" + config['web']['host']
markdown = """
- = Wie funktioniert Ticketfrei? =
-
- Willst du mithelfen, Ticketkontrolleure zu überwachen?
- Willst du einen Fahrscheinfreien ÖPNV erkämpfen?
-
- == Ist es gerade sicher, schwarz zu fahren? ==
-
- Schau einfach auf das Profil unseres Bots: """ + twit_link + """
-
- Hat jemand vor kurzem etwas über Kontrolleur*innen gepostet?
- * Wenn ja, dann kauf dir vllt lieber ein Ticket. In Nürnberg
- haben wir die Erfahrung gemacht, dass Kontis normalerweile
- ungefähr ne Woche aktiv sind, ein paar Stunden am Tag. Wenn es
- also in den letzten Stunden einen Bericht gab, pass lieber
- auf.
- * Wenn nicht, ist es wahrscheinlich kein Problem :)
-
- Wir können natürlich nicht garantieren, dass es sicher ist,
- also pass trotzdem auf, wer auf dem Bahnsteig steht.
- Aber je mehr Leute mitmachen, desto eher kannst du dir sicher
- sein, dass wir sie finden, bevor sie uns finden.
-
- Also, wenn du weniger Glück hast, und der erste bist, der einen
- Kontrolleur sieht:
-
- == Was mache ich, wenn ich Kontis sehe? ==
-
- Ganz einfach, du schreibst es den anderen. Das geht entweder
-
-
-
- * Oder per Mail an """ + mailinglist + """, wenn ihr kein
- Social Media benutzen wollt.
-
- Schreibe einfach einen Toot oder einen Tweet, der den Bot
- mentioned, und gib an
- * Wo du die Kontis gesehen hast
- * Welche Linie sie benutzen und in welche Richtung sie fahren.
-
- Zum Beispiel so:
-
- [[https://github.com/b3yond/ticketfrei/blob/master/guides/tooting_screenshot.png|Screenshot of writing a toot]]
-
- [[https://github.com/b3yond/ticketfrei/blob/master/guides/toot_screenshot.png|A toot ready to be boosted]]
-
- Der Bot wird die Nachricht dann weiterverbreiten, auch zu den
- anderen Netzwerken.
- Dann können andere Leute das lesen und sicher vor Kontis sein.
-
- Danke, dass du mithilfst, öffentlichen Verkehr für alle
- sicherzustellen!
-
- == Kann ich darauf vertrauen, was random stranger from the
- Internet mir da erzählen? ==
-
- Aber natürlich! Wir haben Katzenbilder!
-
- [[https://lorempixel.com/550/300/cats|Katzenbilder...]]
-
- Glaubt besser nicht, wenn jemand postet, dass die Luft da und
- da gerade rein ist.
- Das ist vielleicht sogar gut gemeint - aber klar könnte die
- VAG sich hinsetzen und einfach lauter Falschmeldungen posten.
-
- Aber Falschmeldungen darüber, dass gerade Kontis i-wo unterwegs
- sind?
- Das macht keinen Sinn.
- Im schlimmsten Fall kauft jmd mal eine Fahrkarte mehr - aber
- kann sonst immer schwarz fahren.
-
- Also ja - es macht Sinn, uns zu vertrauen, wenn wir sagen, wo
- gerade Kontis sind.
-
- == Was ist Mastodon und warum sollte ich es benutzen? ==
-
- Mastodon ist ein dezentrales soziales Netzwerk - so wie
- Twitter, nur ohne Monopol und Zentralismus.
- Ihr könnt Kurznachrichten (Toots) über alles mögliche
- schreiben, und euch mit anderen austauschen.
-
- Mastodon ist Open Source, Privatsphäre-freundlich und relativ
- sicher vor Zensur.
-
- Um Mastodon zu benutzen, besucht diese Seite:
- https://joinmastodon.org/
+# Wie funktioniert Ticketfrei?
+
+Willst du mithelfen, Ticketkontrolleure zu überwachen?
+Willst du einen Fahrscheinfreien ÖPNV erkämpfen?
+
+## Ist es gerade sicher, schwarz zu fahren?
+
+Schau einfach auf das Profil unseres Bots: """ + twit_link + """
+
+Hat jemand vor kurzem etwas über Kontrolleur*innen gepostet?
+* Wenn ja, dann kauf dir vllt lieber ein Ticket. In Nürnberg
+ haben wir die Erfahrung gemacht, dass Kontis normalerweile
+ ungefähr ne Woche aktiv sind, ein paar Stunden am Tag. Wenn es
+ also in den letzten Stunden einen Bericht gab, pass lieber
+ auf.
+* Wenn nicht, ist es wahrscheinlich kein Problem :)
+
+Wir können natürlich nicht garantieren, dass es sicher ist,
+also pass trotzdem auf, wer auf dem Bahnsteig steht.
+Aber je mehr Leute mitmachen, desto eher kannst du dir sicher
+sein, dass wir sie finden, bevor sie uns finden.
+
+Also, wenn du weniger Glück hast, und der erste bist, der einen
+Kontrolleur sieht:
+
+## Was mache ich, wenn ich Kontis sehe?
+
+Ganz einfach, du schreibst es den anderen. Das geht entweder
+
+
+
+* Oder per Mail an """ + mailinglist + """, wenn ihr kein
+ Social Media benutzen wollt.
+
+Schreibe einfach einen Toot oder einen Tweet, der den Bot
+mentioned, und gib an
+* Wo du die Kontis gesehen hast
+* Welche Linie sie benutzen und in welche Richtung sie fahren.
+
+Zum Beispiel so:
+
+[[https://github.com/b3yond/ticketfrei/blob/master/guides/tooting_screenshot.png|Screenshot of writing a toot]]
+
+[[https://github.com/b3yond/ticketfrei/blob/master/guides/toot_screenshot.png|A toot ready to be boosted]]
+
+Der Bot wird die Nachricht dann weiterverbreiten, auch zu den
+anderen Netzwerken.
+Dann können andere Leute das lesen und sicher vor Kontis sein.
+
+Danke, dass du mithilfst, öffentlichen Verkehr für alle
+sicherzustellen!
+
+## Kann ich darauf vertrauen, was random stranger from the
+Internet mir da erzählen?
+
+Aber natürlich! Wir haben Katzenbilder!
+
+[[https://lorempixel.com/550/300/cats|Katzenbilder...]]
+
+Glaubt besser nicht, wenn jemand postet, dass die Luft da und
+da gerade rein ist.
+Das ist vielleicht sogar gut gemeint - aber klar könnte die
+VAG sich hinsetzen und einfach lauter Falschmeldungen posten.
+
+Aber Falschmeldungen darüber, dass gerade Kontis i-wo unterwegs
+sind?
+Das macht keinen Sinn.
+Im schlimmsten Fall kauft jmd mal eine Fahrkarte mehr - aber
+kann sonst immer schwarz fahren.
+
+Also ja - es macht Sinn, uns zu vertrauen, wenn wir sagen, wo
+gerade Kontis sind.
+
+## Was ist Mastodon und warum sollte ich es benutzen?
+
+Mastodon ist ein dezentrales soziales Netzwerk - so wie
+Twitter, nur ohne Monopol und Zentralismus.
+Ihr könnt Kurznachrichten (Toots) über alles mögliche
+schreiben, und euch mit anderen austauschen.
+
+Mastodon ist Open Source, Privatsphäre-freundlich und relativ
+sicher vor Zensur.
+
+Um Mastodon zu benutzen, besucht diese Seite:
+https://joinmastodon.org/
"""
db.execute("""INSERT INTO cities(user_id, city, markdown, masto_link,
twit_link) VALUES(?,?,?,?,?)""",