you can now set goodlist & blacklist in settings. render city page #18. fixed #24 and #25.

This commit is contained in:
b3yond 2018-05-25 15:57:20 +02:00
parent c9dfb6611a
commit 2a9c5c657f
6 changed files with 188 additions and 108 deletions

View file

@ -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:

31
db.py
View file

@ -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(?, ?);",

View file

@ -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()

View file

@ -1,4 +1,9 @@
% rebase('template/wrapper.tpl')
$markdown.render()
<%
import markdown as md
html = md.markdown(markdown)
%>
{{html}}

View file

@ -1,7 +1,11 @@
% rebase('template/wrapper.tpl')
<a href="/logout/"><button>Logout</button></a>
<div id="enablebutton" style="float: right; padding: 2em;">asdf</div>
% if enabled:
<div id="enablebutton" style="float: right; padding: 2em;">Disable</div>
% else:
<div id="enablebutton" style="float: right; padding: 2em;" color="red">Enable</div>
% end
<a class='button' style="padding: 1.5em;" href="/login/twitter">
<picture>
@ -72,7 +76,7 @@
suggest:
</p>
<form action="/settings/goodlist" method="post">
<textarea id="markdown" rows="20" cols="70" name="goodlist" wrap="physical">$markdown</textarea>
<textarea id="markdown" rows="20" cols="70" name="goodlist" wrap="physical">{{markdown}}</textarea>
<input name='confirm' value='Save' type='submit'/>
</form>
</div>
@ -86,7 +90,7 @@
</p>
<form action="/settings/goodlist" method="post">
<!-- find a way to display current good list. js which reads from a cookie? template? -->
<textarea id="goodlist" rows="8" cols="70" name="goodlist" wrap="physical">$triggerwords</textarea>
<textarea id="goodlist" rows="8" cols="70" name="goodlist" wrap="physical">{{triggerwords}}</textarea>
<input name='confirm' value='Submit' type='submit'/>
</form>
</div>
@ -100,7 +104,7 @@
</p>
<form action="/settings/blacklist" method="post">
<!-- find a way to display current blacklist. js which reads from a cookie? template? -->
<textarea id="blacklist" rows="8" cols="70" name="blacklist" wrap="physical">$badwords</textarea>
<textarea id="blacklist" rows="8" cols="70" name="blacklist" wrap="physical">{{badwords}}</textarea>
<input name='confirm' value='Submit' type='submit'/>
</form>
</div>

168
user.py
View file

@ -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? =
# Wie funktioniert Ticketfrei?
Willst du mithelfen, Ticketkontrolleure zu überwachen?
Willst du einen Fahrscheinfreien ÖPNV erkämpfen?
Willst du mithelfen, Ticketkontrolleure zu überwachen?
Willst du einen Fahrscheinfreien ÖPNV erkämpfen?
== Ist es gerade sicher, schwarz zu fahren? ==
## Ist es gerade sicher, schwarz zu fahren?
Schau einfach auf das Profil unseres Bots: """ + twit_link + """
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
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 :)
* 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.
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:
Also, wenn du weniger Glück hast, und der erste bist, der einen
Kontrolleur sieht:
== Was mache ich, wenn ich Kontis sehe? ==
## Was mache ich, wenn ich Kontis sehe?
Ganz einfach, du schreibst es den anderen. Das geht entweder
Ganz einfach, du schreibst es den anderen. Das geht entweder
<!-- * mit Mastodon: """ + masto_link + """ -->
<!-- * über Twitter: """ + twit_link + """ -->
* Oder per Mail an """ + mailinglist + """, wenn ihr kein
<!-- * mit Mastodon: """ + masto_link + """ -->
<!-- * über Twitter: """ + twit_link + """ -->
* 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.
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:
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/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]]
[[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.
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!
Danke, dass du mithilfst, öffentlichen Verkehr für alle
sicherzustellen!
== Kann ich darauf vertrauen, was random stranger from the
Internet mir da erzählen? ==
## Kann ich darauf vertrauen, was random stranger from the
Internet mir da erzählen?
Aber natürlich! Wir haben Katzenbilder!
Aber natürlich! Wir haben Katzenbilder!
[[https://lorempixel.com/550/300/cats|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.
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.
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.
Also ja - es macht Sinn, uns zu vertrauen, wenn wir sagen, wo
gerade Kontis sind.
== Was ist Mastodon und warum sollte ich es benutzen? ==
## 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 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.
Mastodon ist Open Source, Privatsphäre-freundlich und relativ
sicher vor Zensur.
Um Mastodon zu benutzen, besucht diese Seite:
https://joinmastodon.org/
Um Mastodon zu benutzen, besucht diese Seite:
https://joinmastodon.org/
"""
db.execute("""INSERT INTO cities(user_id, city, markdown, masto_link,
twit_link) VALUES(?,?,?,?,?)""",