189 lines
6.9 KiB
Python
189 lines
6.9 KiB
Python
from config import config
|
|
import jwt
|
|
import logging
|
|
from os import urandom
|
|
from pylibscrypt import scrypt_mcf
|
|
import sqlite3
|
|
|
|
|
|
logger = logging.getLogger(__name__)
|
|
|
|
|
|
class DB(object):
|
|
def __init__(self, dbfile):
|
|
self.conn = sqlite3.connect(dbfile)
|
|
self.cur = self.conn.cursor()
|
|
self.create()
|
|
self.secret = urandom(32)
|
|
|
|
def execute(self, *args, **kwargs):
|
|
return self.cur.execute(*args, **kwargs)
|
|
|
|
def commit(self):
|
|
self.conn.commit()
|
|
|
|
def close(self):
|
|
self.conn.close()
|
|
|
|
def create(self):
|
|
# init db
|
|
self.cur.executescript('''
|
|
CREATE TABLE IF NOT EXISTS user (
|
|
id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT UNIQUE,
|
|
passhash TEXT,
|
|
enabled INTEGER DEFAULT 1
|
|
);
|
|
CREATE TABLE IF NOT EXISTS email (
|
|
id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT UNIQUE,
|
|
user_id INTEGER,
|
|
email TEXT,
|
|
FOREIGN KEY(user_id) REFERENCES user(id)
|
|
);
|
|
CREATE TABLE IF NOT EXISTS triggerpatterns (
|
|
id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT UNIQUE,
|
|
user_id INTEGER,
|
|
pattern 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,
|
|
FOREIGN KEY(user_id) REFERENCES user(id)
|
|
);
|
|
CREATE TABLE IF NOT EXISTS mastodon_instances (
|
|
id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT UNIQUE,
|
|
instance TEXT,
|
|
client_id TEXT,
|
|
client_secret TEXT
|
|
);
|
|
CREATE TABLE IF NOT EXISTS mastodon_accounts (
|
|
id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT UNIQUE,
|
|
user_id INTEGER,
|
|
access_token TEXT,
|
|
instance_id INTEGER,
|
|
active INTEGER,
|
|
FOREIGN KEY(user_id) REFERENCES user(id),
|
|
FOREIGN KEY(instance_id) REFERENCES mastodon_instances(id)
|
|
);
|
|
CREATE TABLE IF NOT EXISTS seen_toots (
|
|
id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT UNIQUE,
|
|
user_id INTEGER,
|
|
mastodon_accounts_id INTEGER,
|
|
toot_id TEXT,
|
|
FOREIGN KEY(user_id) REFERENCES user(id),
|
|
FOREIGN KEY(mastodon_accounts_id)
|
|
REFERENCES mastodon_accounts(id)
|
|
);
|
|
CREATE TABLE IF NOT EXISTS twitter_request_tokens (
|
|
id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT UNIQUE,
|
|
user_id INTEGER,
|
|
request_token TEXT,
|
|
request_token_secret TEXT,
|
|
FOREIGN KEY(user_id) REFERENCES user(id)
|
|
);
|
|
CREATE TABLE IF NOT EXISTS twitter_accounts (
|
|
id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT UNIQUE,
|
|
user_id INTEGER,
|
|
client_id TEXT,
|
|
client_secret TEXT,
|
|
active INTEGER,
|
|
FOREIGN KEY(user_id) REFERENCES user(id)
|
|
);
|
|
CREATE TABLE IF NOT EXISTS seen_tweets (
|
|
id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT UNIQUE,
|
|
user_id INTEGER,
|
|
twitter_accounts_id INTEGER,
|
|
tweet_id TEXT,
|
|
FOREIGN KEY(user_id) REFERENCES user(id)
|
|
FOREIGN KEY(twitter_accounts_id)
|
|
REFERENCES twitter_accounts(id)
|
|
);
|
|
CREATE TABLE IF NOT EXISTS seen_dms (
|
|
id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT UNIQUE,
|
|
user_id INTEGER,
|
|
twitter_accounts_id INTEGER,
|
|
message_id TEXT,
|
|
FOREIGN KEY(user_id) REFERENCES user(id)
|
|
FOREIGN KEY(twitter_accounts_id)
|
|
REFERENCES twitter_accounts(id)
|
|
);
|
|
CREATE TABLE IF NOT EXISTS mailinglist (
|
|
id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT UNIQUE,
|
|
user_id INTEGER,
|
|
email TEXT,
|
|
active INTEGER,
|
|
FOREIGN KEY(user_id) REFERENCES user(id)
|
|
);
|
|
CREATE TABLE IF NOT EXISTS cities (
|
|
id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT UNIQUE,
|
|
user_id INTEGER,
|
|
city TEXT,
|
|
markdown TEXT,
|
|
masto_link TEXT,
|
|
twit_link TEXT,
|
|
FOREIGN KEY(user_id) REFERENCES user(id)
|
|
);
|
|
''')
|
|
|
|
def user_token(self, email, password):
|
|
return jwt.encode({
|
|
'email': email,
|
|
'passhash': scrypt_mcf(
|
|
password.encode('utf-8')
|
|
).decode('ascii')
|
|
}, self.secret).decode('ascii')
|
|
|
|
def confirm(self, token):
|
|
from user import User
|
|
try:
|
|
json = jwt.decode(token, self.secret)
|
|
except jwt.DecodeError:
|
|
return None # invalid token
|
|
if 'passhash' in json.keys():
|
|
# create user
|
|
self.execute("INSERT INTO user (passhash) VALUES(?);",
|
|
(json['passhash'], ))
|
|
uid = self.cur.lastrowid
|
|
self.execute("""
|
|
INSERT INTO triggerpatterns (user_id, pattern)
|
|
VALUES(?, ?);
|
|
""", (uid, '.*'))
|
|
else:
|
|
uid = json['uid']
|
|
self.execute("INSERT INTO email (user_id, email) VALUES(?, ?);",
|
|
(uid, json['email']))
|
|
self.commit()
|
|
return User(uid)
|
|
|
|
def by_email(self, email):
|
|
from user import User
|
|
self.execute("SELECT user_id FROM email WHERE email=?;", (email, ))
|
|
try:
|
|
uid, = self.cur.fetchone()
|
|
except TypeError:
|
|
return None
|
|
return User(uid)
|
|
|
|
def user_facing_properties(self, city):
|
|
self.execute("""SELECT city, markdown, masto_link, twit_link
|
|
FROM cities
|
|
WHERE city=?;""", (city, ))
|
|
try:
|
|
city, markdown, masto_link, twit_link = self.cur.fetchone()
|
|
return dict(city=city,
|
|
markdown=markdown,
|
|
masto_link=masto_link,
|
|
twit_link=twit_link)
|
|
except TypeError:
|
|
return None
|
|
|
|
@property
|
|
def active_users(self):
|
|
from user import User
|
|
self.execute("SELECT id FROM user WHERE enabled=1;")
|
|
return [User(uid) for uid, in self.cur.fetchall()]
|
|
|
|
|
|
db = DB(config['database']['db_path'])
|