1
0
Fork 0

Big rework of Flask and database with new login system

This commit is contained in:
Ethanell 2019-04-29 01:49:40 +02:00
parent 7de70b423c
commit 6beb1bb246
51 changed files with 500 additions and 174 deletions

14
app/__init__.py Normal file
View file

@ -0,0 +1,14 @@
from flask import Flask
from config import Config
from flask_sqlalchemy import SQLAlchemy
from flask_migrate import Migrate
from flask_login import LoginManager
app = Flask(__name__)
app.config.from_object(Config)
db = SQLAlchemy(app)
migrate = Migrate(app, db)
login = LoginManager(app)
login.login_view = "login"
from app import routes, models

28
app/forms.py Normal file
View file

@ -0,0 +1,28 @@
from flask_wtf import FlaskForm
from wtforms import StringField, PasswordField, BooleanField, SubmitField
from wtforms.validators import ValidationError, DataRequired, Email, EqualTo
from app.models import User
class LoginForm(FlaskForm):
username = StringField("Username", validators=[DataRequired()])
password = PasswordField("Password", validators=[DataRequired()])
remember_me = BooleanField("Remember Me")
submit = SubmitField("Sign In")
class RegistrationForm(FlaskForm):
username = StringField("Username", validators=[DataRequired()])
email = StringField("Email", validators=[DataRequired(), Email()])
password = PasswordField("Password", validators=[DataRequired()])
password2 = PasswordField(
"Repeat Password", validators=[DataRequired(), EqualTo("password")])
submit = SubmitField("Register")
def validate_username(self, username):
user = User.query.filter_by(username=username.data).first()
if user is not None:
raise ValidationError("Please use a different username.")
def validate_email(self, email):
user = User.query.filter_by(email=email.data).first()
if user is not None:
raise ValidationError("Please use a different email address.")

36
app/models.py Normal file
View file

@ -0,0 +1,36 @@
from app import db
from werkzeug.security import generate_password_hash, check_password_hash
from flask_login import UserMixin
from app import login
class User(UserMixin, db.Model):
id = db.Column(db.Integer, primary_key=True, unique=True)
username = db.Column(db.String(64), index=True, unique=True)
email = db.Column(db.String(120), index=True, unique=True)
password_hash = db.Column(db.String(128))
twitter_api = db.relationship("TwitterAPI", backref="user", lazy="dynamic")
trello_api = db.relationship('TrelloAPI', backref="user", lazy="dynamic")
def set_password(self, password):
self.password_hash = generate_password_hash(password)
def check_password(self, password):
return check_password_hash(self.password_hash, password)
def __repr__(self):
return f"<User {self.username}>"
class TwitterAPI(db.Model):
id = db.Column(db.Integer, primary_key=True, unique=True)
user_id = db.Column(db.Integer, db.ForeignKey("user.id"), unique=True)
access_token = db.Column(db.String(50), unique=True)
access_token_secret = db.Column(db.String(45), unique=True)
class TrelloAPI(db.Model):
id = db.Column(db.Integer, primary_key=True, unique=True)
user_id = db.Column(db.Integer, db.ForeignKey("user.id"), unique=True)
token = db.Column(db.String(64), unique=True)
@login.user_loader
def load_user(id):
return User.query.get(int(id))

165
app/routes.py Normal file
View file

@ -0,0 +1,165 @@
from app import app, db
from flask import Flask, request, redirect, session, render_template, flash, url_for
from flask_login import current_user, login_user, logout_user, login_required
from app.forms import LoginForm, RegistrationForm
from app.models import User, TwitterAPI, TrelloAPI
from werkzeug.urls import url_parse
import twitter_credentials, tweepy, tw
import trello_credentials, trello, tr
@app.route("/login", methods=["GET", "POST"])
def login():
if current_user.is_authenticated:
return redirect(url_for("home"))
form = LoginForm()
if form.validate_on_submit():
user = User.query.filter_by(username=form.username.data).first()
if user is None or not user.check_password(form.password.data):
flash("Invalid username or password")
return redirect(url_for("login"))
login_user(user, remember=form.remember_me.data)
next_page = request.args.get("next")
if not next_page or url_parse(next_page).netloc != "":
next_page = url_for("home")
return redirect(next_page)
return render_template("login.html", form=form)
@app.route("/register", methods=["GET", "POST"])
def register():
if current_user.is_authenticated:
return redirect(url_for("index"))
form = RegistrationForm()
if form.validate_on_submit():
user = User(username=form.username.data, email=form.email.data)
user.set_password(form.password.data)
db.session.add(user)
db.session.commit()
flash("Congratulations, you are now a registered user!")
return redirect(url_for("login"))
return render_template("register.html", form=form)
@app.route("/logout")
def logout():
logout_user()
return redirect(url_for("home"))
@app.route("/twlogin")
@login_required
def twlogin():
auth = tweepy.OAuthHandler(twitter_credentials.consumer_key, twitter_credentials.consumer_secret_key, "https://cyberplanificateur.flifloo.fr/twlogin")
if request.args.get("oauth_token") and request.args.get("oauth_verifier"):
auth.request_token = {"oauth_token" : request.args.get("oauth_token"), "oauth_token_secret" : request.args.get("oauth_verifier")}
try:
auth.get_access_token(request.args.get("oauth_verifier"))
except:
return "Error ! Failed to get access token"
else:
twapi = TwitterAPI(access_token = auth.access_token, access_token_secret = auth.access_token_secret, user = current_user)
db.session.add(twapi)
db.session.commit()
elif not TwitterAPI.query.filter_by(user=current_user).first():
return redirect(auth.get_authorization_url())
return redirect(url_for("settings"))
@app.route("/twlogout")
@login_required
def twlogout():
twapi = TwitterAPI.query.filter_by(user=current_user).first()
if twapi:
db.session.delete(twapi)
db.session.commit()
return redirect(url_for("settings"))
@app.route("/trlogin")
@login_required
def trlogin():
return redirect(f"https://trello.com/1/authorize?expiration=never&name=Cyberplanificateur&scope=read,write&response_type=token&key={trello_credentials.api_key}&return_url=https://cyberplanificateur.flifloo.fr/settings")
@app.route("/trlogout")
@login_required
def trlogout():
trapi = TrelloAPI.query.filter_by(user=current_user).first()
if trapi:
db.session.delete(trapi)
db.session.commit()
return redirect(url_for("settings"))
@app.route("/")
def home():
return render_template("index.html")
@app.route("/settings", methods = ["POST", "GET"])
@login_required
def settings():
trloginfail = False
if "trtoken" in request.form:
try:
trello.TrelloClient(api_key = trello_credentials.api_key, token = request.form["trtoken"]).list_boards()
except:
trloginfail = True
else:
trapi = TrelloAPI(token = request.form["trtoken"], user = current_user)
db.session.add(trapi)
db.session.commit()
return render_template("settings.html", twlogin = TwitterAPI.query.filter_by(user=current_user).first(), trlogin = TrelloAPI.query.filter_by(user=current_user).first(), trloginfail = trloginfail)
@app.route("/dashboard", methods = ["POST", "GET"])
def dashboard():
if not tw.is_login(session):
return redirect("/")
twapi = tw.api_login(session)
if request.args.get("twrm"):
database.twrm(request.args.get("twrm"))
if request.args.get("delet"):
twapi.destroy_status(request.args.get["twrm"])
elif "tweet" in request.form and "slots" in request.form and "keywords" in request.form:
try:
slots = int(request.form["slots"])
tweet = int(request.form["tweet"])
except:
formerror = True
else:
database.twadd(twapi.me().id, tweet, slots, str(request.form["keywords"].split(",")))
formerror = False
tweets = list()
idtake = list()
for t in database.twlist(twapi.me().id):
tw = twapi.get_status(t["id"])
keywords = "|"
for te in eval(t["keywords"]):
keywords += f" {te} |"
tweets.append({"text": tw.text, "id": tw.id, "slots": f"{t['slots']}/{t['maxslots']}", "keywords": keywords})
idtake.append(tw.id)
timeline = list()
for t in twapi.user_timeline():
if not t.in_reply_to_status_id and not t.retweeted and t.id not in idtake:
timeline.append({"text": t.text, "id": t.id})
if tr.is_login(session):
trapi = trello.TrelloClient(api_key = trello_credentials.api_key, token = database.trtoken(twapi.me().id))
boards = list()
for b in trapi.list_boards():
boards.append(b.name)
return render_template("dashboard.html", login = True, tweets = tweets, timeline = timeline, boards = boards, columns = None)
@app.route("/twtoken")
def twtoken():
return f"{session['access_token']} -- {session['access_secret_token']}"
@app.route("/twpost")
def twpost():
if tw.is_login(session):
api = twapi_login(session)
api.update_status("bloup")
return "Send !"
else:
return "Not login !"
@app.route("/test")
def test():
return render_template("elements.html")

View file

Before

Width:  |  Height:  |  Size: 401 B

After

Width:  |  Height:  |  Size: 401 B

View file

Before

Width:  |  Height:  |  Size: 396 B

After

Width:  |  Height:  |  Size: 396 B

View file

Before

Width:  |  Height:  |  Size: 357 B

After

Width:  |  Height:  |  Size: 357 B

View file

Before

Width:  |  Height:  |  Size: 434 KiB

After

Width:  |  Height:  |  Size: 434 KiB

View file

Before

Width:  |  Height:  |  Size: 52 KiB

After

Width:  |  Height:  |  Size: 52 KiB

View file

Before

Width:  |  Height:  |  Size: 11 KiB

After

Width:  |  Height:  |  Size: 11 KiB

View file

Before

Width:  |  Height:  |  Size: 9.4 KiB

After

Width:  |  Height:  |  Size: 9.4 KiB

View file

Before

Width:  |  Height:  |  Size: 11 KiB

After

Width:  |  Height:  |  Size: 11 KiB

View file

Before

Width:  |  Height:  |  Size: 2.3 KiB

After

Width:  |  Height:  |  Size: 2.3 KiB

View file

Before

Width:  |  Height:  |  Size: 2.2 KiB

After

Width:  |  Height:  |  Size: 2.2 KiB

View file

@ -0,0 +1,96 @@
{% extends "template.html" %}
{% block content %}
<!-- Main -->
<article id="main">
<header>
<h2>Dashboard</h2>
<p>Your personal dashboard</p>
</header>
<section class="wrapper style5">
<div class="inner">
<h3>Current automatized tweets</h3>
<hr />
<table>
<thead>
<tr>
<th class="align-center">Tweet</th>
<th class="align-center">Slots</th>
<th class="align-center">Keywords</th>
<th class="align-center">Actions</th>
</tr>
</thead>
<tbody>
{% for t in tweets %}
<tr>
<td><blockquote>{{ t['text'] }}</blockquote></td>
<td class="align-center">{{ t['slots'] }}</td>
<td class="align-center">{{ t['keywords'] }}</td>
<td class="align-right"><a href="https://cyberplanificateur.flifloo.fr/dashboard?twrm={{ t['id']}}" class="button primary">Disable</a>
<a href="https://cyberplanificateur.flifloo.fr/dashboard?twrm={{ t['id']}}&delet=True" class="button">Delet</a></td>
</tr>
{% endfor %}
</tbody>
</table>
<hr />
<h3>Add an automatized tweet</h3>
<hr />
<form action = "https://cyberplanificateur.flifloo.fr/dashboard" method = "POST">
<section>
<div class="row">
<div class="col-6 col-12-medium">
{% for t in timeline %}
<div class="col-4 col-12-small">
<input type="radio" id="{{ t['id'] }}" name="tweet" value="{{ t['id'] }}">
<label for="{{ t['id'] }}">{{ t['text'] }}</label>
</div>
{% endfor %}
</div>
<div class="col-6 col-12-medium">
<input type="text" name="slots" placeholder="Slots number" />
<input type="text" name="keywords" placeholder="Keywords (separate with a comma)" />
</div>
</div>
</section>
<input type="submit" value="Connect" class="button primary">
</form>
<hr />
<h3>Trello board</h3>
<hr />
<section>
<div class="row">
<div class="col-6 col-12-medium">
<h4>Choose a board</h4>
<form action="https://cyberplanificateur.flifloo.fr/dashboard" method="POST">
{% for b in boards %}
<div class="col-4 col-12-small">
<input type="radio" id="{{ b['id'] }}" name="board" value="{{ b['id'] }}">
<label for="{{ b['id'] }}">{{ b['text'] }}</label>
</div>
{% endfor %}
<input type="submit" value="Select" class="button primary">
</form>
</div>
<div class="col-6 col-12-medium">
<h4>Choose a column</h4>
<form action="https://cyberplanificateur.flifloo.fr/dashboard" method="POST">
{% for c in columns %}
<div class="col-4 col-12-small">
<input type="radio" id="{{ c['id'] }}" name="column" value="{{ c['id'] }}">
<label for="{{ c['id'] }}">{{ c['text'] }}</label>
</div>
{% endfor %}
<input type="submit" value="Select" class="button primary">
</form>
</div>
</div>
</section>
<hr />
</div>
</section>
</article>
{% endblock %}

View file

@ -7,10 +7,10 @@
<h2>Cyberplanificateur</h2>
<p>Manage your commissions was never so easy with with the Cyberplanificateur</p>
<ul class="actions special">
{% if login %}
{% if current_user.is_authenticated %}
<li><a href="{{ url_for('dashboard') }}" class="button primary">Dashboard</a></li>
{% else %}
<li><a href="{{ url_for('twlogin') }}" class="button primary">Login !</a></li>
<li><a href="{{ url_for('login') }}" class="button primary">Login !</a></li>
{% endif %}
</ul>
</div>

31
app/templates/login.html Normal file
View file

@ -0,0 +1,31 @@
{% extends "template.html" %}
{% block content %}
<!-- Main -->
<article id="main">
<header>
<h2>Sign In</h2>
</header>
<section class="wrapper style5">
<div class="inner">
<form action="" method="post" novalidate>
{{ form.hidden_tag() }}
<p>
{{ form.username.label }}<br>
{{ form.username(size=32) }}
</p>
<p>
{{ form.password.label }}<br>
{{ form.password(size=32) }}
</p>
<p>{{ form.remember_me() }} {{ form.remember_me.label }}</p>
<p>{{ form.submit() }}</p>
</form>
<p>New User? <a href="{{ url_for('register') }}">Click to Register!</a></p>
</div>
</section>
</article>
{% endblock %}

View file

@ -0,0 +1,49 @@
{% extends "template.html" %}
{% block content %}
<!-- Main -->
<article id="main">
<header>
<h2>Register</h2>
</header>
<section class="wrapper style5">
<div class="inner">
<form action="" method="post">
{{ form.hidden_tag() }}
<p>
{{ form.username.label }}<br>
{{ form.username(size=32) }}<br>
{% for error in form.username.errors %}
<span style="color: red;">[{{ error }}]</span>
{% endfor %}
</p>
<p>
{{ form.email.label }}<br>
{{ form.email(size=64) }}<br>
{% for error in form.email.errors %}
<span style="color: red;">[{{ error }}]</span>
{% endfor %}
</p>
<p>
{{ form.password.label }}<br>
{{ form.password(size=32) }}<br>
{% for error in form.password.errors %}
<span style="color: red;">[{{ error }}]</span>
{% endfor %}
</p>
<p>
{{ form.password2.label }}<br>
{{ form.password2(size=32) }}<br>
{% for error in form.password2.errors %}
<span style="color: red;">[{{ error }}]</span>
{% endfor %}
</p>
<p>{{ form.submit() }}</p>
</form>
</div>
</section>
</article>
{% endblock %}

View file

@ -11,16 +11,21 @@
<div class="inner">
<h3>Connexions</h3>
{% if trloginfail and not trlogin %}
<h4><font color="red">Invalid Trello token !</font></h4>
<p>Twitter :
{% if twlogin %}
<font color="green">Connected</font></p>
<a href="{{ url_for('twlogout') }}" class="button">Disconnect</a>
{% else %}
<font color="red">Disconnected</font></p>
<a href="{{ url_for('twlogin') }}" class="button primary">Connect</a>
{% endif %}
<p>Trello :
{% if trlogin %}
<font color="green">Connected</font></p>
<a href="{{ url_for('trlogout')}}" class="button">Disconnect</a>
<a href="{{ url_for('trlogout') }}" class="button">Disconnect</a>
{% else %}
<font color="red">Disconnected</font></p>
<p><a href="https://trello.com/1/authorize?expiration=never&name=Cyberplanificateur&scope=read,write&response_type=token&key=4b9aa97a8ec693574d819aeaf9e0eefa&return_url=https://cyberplanificateur.flifloo.fr/settings">Click here</a> and give the token bellow</p>
<p><a href="{{ url_for('trlogin') }}">Click here</a> and give the token bellow</p>
<form action = "https://cyberplanificateur.flifloo.fr/settings" method = "POST">
<input type="text" name="trtoken" placeholder="Trello token" />
<input type="submit" value="Connect" class="button primary">

View file

@ -27,12 +27,12 @@
<div id="menu">
<ul>
<li><a href="{{ url_for('home') }}">Home</a></li>
{% if login %}
{% if current_user.is_authenticated %}
<li><a href="{{ url_for('dashboard') }}">Dashboard</a></li>
<li><a href="{{ url_for('settings')}}">Settings</a></li>
<li><a href="{{ url_for('twlogout')}}">Log Out</a></li>
<li><a href="{{ url_for('logout')}}">Log Out</a></li>
{% else %}
<li><a href="{{ url_for('twlogin')}}">Log In</a></li>
<li><a href="{{ url_for('login')}}">Log In</a></li>
{% endif %}
</ul>
</div>

7
config.py Normal file
View file

@ -0,0 +1,7 @@
import os
basedir = os.path.abspath(os.path.dirname(__file__))
class Config(object):
SECRET_KEY = "*i9uld6u@t!kxl9%o+byxqf14&a&&@y@q=l$!lg4m%b-a*^o(a"
SQLALCHEMY_DATABASE_URI = "sqlite:///" + os.path.join(basedir, "database.db")
SQLALCHEMY_TRACK_MODIFICATIONS = False

9
cyberplanificateur.py Normal file
View file

@ -0,0 +1,9 @@
from app import app
from app.models import User, TwitterAPI, TrelloAPI
@app.shell_context_processor
def make_shell_context():
return {"db": db, "User": User, "TwitterAPI": TwitterAPI, "TrelloAPI": TrelloAPI}
if __name__ == "__main__":
app.run(debug=True, port=5000, host="0.0.0.0")

View file

@ -7,7 +7,7 @@ def tradd(id, token):
for u in dbc.execute("SELECT * FROM trello WHERE id=?", (id,)):
sucess = False
if sucess:
dbc.execute("INSERT INTO trello (id, token) VALUES (?, ?)", (id, token))
dbc.execute("INSERT INTO trello (id, token) VALUES (?, ?)", (id, token,))
dbc.close()
db.commit()
return sucess
@ -28,6 +28,31 @@ def trtoken(id):
dbc.close()
return token
def twadd(user, id, maxslots, keywords):
with sqlite3.connect('database.db') as db:
dbc = db.cursor()
dbc.execute("INSERT INTO tweets (user, id, slots, maxslots, keywords) VALUES (?, ?, ?, ?, ?)", (user, id, 0, maxslots, keywords,))
dbc.close()
db.commit()
def twrm(id):
with sqlite3.connect('database.db') as db:
dbc = db.cursor()
dbc.execute("DELETE FROM tweets WHERE id=?", (id,))
dbc.close()
db.commit()
def twlist(user):
with sqlite3.connect('database.db') as db:
dbc = db.cursor()
tweets = list()
for u in dbc.execute("SELECT * FROM tweets WHERE user=?", (user,)):
tweets.append({"id": u[1], "slots": u[2], "maxslots": u[3], "keywords": u[4]})
dbc.close()
db.commit()
return tweets
with sqlite3.connect('database.db') as db:
Table = False
dbc = db.cursor()
@ -36,7 +61,8 @@ with sqlite3.connect('database.db') as db:
for t in dbc.execute("SELECT name FROM sqlite_master WHERE type='table' AND name='trello';"):
Table = True
if not Table:
dbc.execute('''CREATE TABLE trello (id text, token text)''')
dbc.execute('''CREATE TABLE trello (id int, token text)''')
dbc.execute('''CREATE TABLE tweets (user int, id int, slots int, maxslots int, keywords text)''')
dbc.close()
db.commit()
#register("flifloo", "flifloo@gmail.com", "owo")

99
site.py
View file

@ -1,99 +0,0 @@
from flask import Flask, request, redirect, session, render_template
import twitter_credentials, tweepy, database, trello_credentials, trello
app = Flask(__name__)
app.secret_key = "*i9uld6u@t!kxl9%o+byxqf14&a&&@y@q=l$!lg4m%b-a*^o(a"
def is_twkeys(session):
try:
session["access_token"]
session["access_secret_token"]
except:
return False
else:
return True
def twapi_login(session):
auth = tweepy.OAuthHandler(twitter_credentials.consumer_key, twitter_credentials.consumer_secret_key)
auth.set_access_token(session["access_token"], session["access_secret_token"])
return tweepy.API(auth)
def is_twlogin(session):
return is_twkeys(session) and twapi_login(session).verify_credentials()
def is_trlogin(session):
return is_twkeys(session) and database.trtoken(twapi_login(session).me().id)
@app.route("/twlogin")
def twlogin():
auth = tweepy.OAuthHandler(twitter_credentials.consumer_key, twitter_credentials.consumer_secret_key, "https://cyberplanificateur.flifloo.fr/twlogin")
if request.args.get("oauth_token") and request.args.get("oauth_verifier"):
auth.request_token = {"oauth_token" : request.args.get("oauth_token"), "oauth_token_secret" : request.args.get("oauth_verifier")}
try:
auth.get_access_token(request.args.get("oauth_verifier"))
except:
return "Error ! Failed to get access token"
else:
session["access_token"] = auth.access_token
session["access_secret_token"] = auth.access_token_secret
elif not is_twlogin(session):
return redirect(auth.get_authorization_url())
return redirect("/")
@app.route("/twlogout")
def twlogout():
if is_twkeys(session):
session.pop("access_token", None)
session.pop("access_secret_token", None)
return redirect("/")
@app.route("/trlogout")
def trlogout():
if not is_twlogin(session):
return redirect("/")
if is_trlogin(session):
database.trrm(twapi_login(session).me().id)
return redirect("/settings")
@app.route("/")
def home():
return render_template("index.html", login = is_twlogin(session))
@app.route("/settings", methods = ['POST', 'GET'])
def settings():
if not is_twlogin(session):
return redirect("/")
trloginfail = False
if "trtoken" in request.form:
try:
trello.TrelloClient(api_key = trello_credentials.api_key, token = request.form["trtoken"]).list_boards()
except:
trloginfail = True
else:
database.tradd(twapi_login(session).me().id, request.form["trtoken"])
return render_template("settings.html", login = True, trlogin = is_trlogin(session), trloginfail = trloginfail)
@app.route("/dashboard")
def dashboard():
if not is_twlogin(session):
return redirect("/")
return render_template("dashboard.html", login = True, tweets = ["test1", "test2", "test3"], timeline = [{"id": 1, "text": "test1"}, {"id": 2, "text": "test2"}, {"id": 3, "text": "test3"}, {"id": 4, "text": "test4"}])
@app.route("/twpost")
def twpost():
if is_twlogin(session):
api = twapi_login(session)
api.update_status("bloup")
return "Send !"
else:
return "Not login !"
@app.route("/test")
def test():
return render_template("elements.html")
if __name__ == "__main__":
app.run(debug=True, port=5000, host="0.0.0.0")

View file

@ -1,64 +0,0 @@
{% extends "template.html" %}
{% block content %}
<!-- Main -->
<article id="main">
<header>
<h2>Dashboard</h2>
<p>Your personal dashboard</p>
</header>
<section class="wrapper style5">
<div class="inner">
<h3>Current automatized tweets</h3>
<hr />
<table>
{% for t in tweets %}
<tr>
<td><blockquote>{{ t }}</blockquote></td>
<td><a href="#" class="button primary">Disable</a>
<a href="#" class="button">Delet</a></td>
</tr>
{% endfor %}
</table>
<hr />
<h3>Add an automatized tweet</h3>
<hr />
<section>
<div class="row">
<div class="col-6 col-12-medium">
{% for t in timeline %}
<div class="col-4 col-12-small">
<input type="radio" id="{{ t['id'] }}" name="tweet">
<label for="{{ t['id'] }}">{{ t['text'] }}</label>
</div>
{% endfor %}
</div>
<div class="col-6 col-12-medium">
<input type="text" name="slots" placeholder="Slots number" />
<input type="text" name="keywords" placeholder="Keywords (separate with a comma)" />
</div>
</div>
</section>
<input type="submit" value="Connect" class="button primary">
<hr />
<h3>Trello board</h3>
<hr />
<section>
<div class="row">
<div class="col-6 col-12-medium">
<h4>Choose a board</h4>
</div>
<div class="col-6 col-12-medium">
<h4>Choose a columns</h4>
</div>
</div>
</section>
<hr />
</div>
</section>
</article>
{% endblock %}

5
tr.py Normal file
View file

@ -0,0 +1,5 @@
import trello
import tw
def is_trlogin(session):
return is_twkeys(session) and database.trtoken(tw.api_login(session).me().id)

18
tw.py Normal file
View file

@ -0,0 +1,18 @@
import tweepy, twitter_credentials
def api_login(session):
auth = tweepy.OAuthHandler(twitter_credentials.consumer_key, twitter_credentials.consumer_secret_key)
auth.set_access_token(session["access_token"], session["access_secret_token"])
return tweepy.API(auth)
def is_keys(session):
try:
session["access_token"]
session["access_secret_token"]
except:
return False
else:
return True
def is_login(session):
return is_keys(session) and api_login(session).verify_credentials()