diff --git a/app/__init__.py b/app/__init__.py new file mode 100644 index 0000000..e8b0dcf --- /dev/null +++ b/app/__init__.py @@ -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 diff --git a/app/forms.py b/app/forms.py new file mode 100644 index 0000000..4afddfd --- /dev/null +++ b/app/forms.py @@ -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.") diff --git a/app/models.py b/app/models.py new file mode 100644 index 0000000..24dbecb --- /dev/null +++ b/app/models.py @@ -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"" + +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)) diff --git a/app/routes.py b/app/routes.py new file mode 100644 index 0000000..6e60a29 --- /dev/null +++ b/app/routes.py @@ -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") diff --git a/static/css/font-awesome.min.css b/app/static/css/font-awesome.min.css similarity index 100% rename from static/css/font-awesome.min.css rename to app/static/css/font-awesome.min.css diff --git a/static/css/images/arrow.svg b/app/static/css/images/arrow.svg similarity index 100% rename from static/css/images/arrow.svg rename to app/static/css/images/arrow.svg diff --git a/static/css/images/bars.svg b/app/static/css/images/bars.svg similarity index 100% rename from static/css/images/bars.svg rename to app/static/css/images/bars.svg diff --git a/static/css/images/close.svg b/app/static/css/images/close.svg similarity index 100% rename from static/css/images/close.svg rename to app/static/css/images/close.svg diff --git a/static/css/main.css b/app/static/css/main.css similarity index 100% rename from static/css/main.css rename to app/static/css/main.css diff --git a/static/css/noscript.css b/app/static/css/noscript.css similarity index 100% rename from static/css/noscript.css rename to app/static/css/noscript.css diff --git a/static/fonts/FontAwesome.otf b/app/static/fonts/FontAwesome.otf similarity index 100% rename from static/fonts/FontAwesome.otf rename to app/static/fonts/FontAwesome.otf diff --git a/static/fonts/fontawesome-webfont.eot b/app/static/fonts/fontawesome-webfont.eot similarity index 100% rename from static/fonts/fontawesome-webfont.eot rename to app/static/fonts/fontawesome-webfont.eot diff --git a/static/fonts/fontawesome-webfont.svg b/app/static/fonts/fontawesome-webfont.svg similarity index 100% rename from static/fonts/fontawesome-webfont.svg rename to app/static/fonts/fontawesome-webfont.svg diff --git a/static/fonts/fontawesome-webfont.ttf b/app/static/fonts/fontawesome-webfont.ttf similarity index 100% rename from static/fonts/fontawesome-webfont.ttf rename to app/static/fonts/fontawesome-webfont.ttf diff --git a/static/fonts/fontawesome-webfont.woff b/app/static/fonts/fontawesome-webfont.woff similarity index 100% rename from static/fonts/fontawesome-webfont.woff rename to app/static/fonts/fontawesome-webfont.woff diff --git a/static/fonts/fontawesome-webfont.woff2 b/app/static/fonts/fontawesome-webfont.woff2 similarity index 100% rename from static/fonts/fontawesome-webfont.woff2 rename to app/static/fonts/fontawesome-webfont.woff2 diff --git a/static/images/banner.jpg b/app/static/images/banner.jpg similarity index 100% rename from static/images/banner.jpg rename to app/static/images/banner.jpg diff --git a/static/images/pic01.jpg b/app/static/images/pic01.jpg similarity index 100% rename from static/images/pic01.jpg rename to app/static/images/pic01.jpg diff --git a/static/images/pic02.jpg b/app/static/images/pic02.jpg similarity index 100% rename from static/images/pic02.jpg rename to app/static/images/pic02.jpg diff --git a/static/images/pic03.jpg b/app/static/images/pic03.jpg similarity index 100% rename from static/images/pic03.jpg rename to app/static/images/pic03.jpg diff --git a/static/images/pic04.jpg b/app/static/images/pic04.jpg similarity index 100% rename from static/images/pic04.jpg rename to app/static/images/pic04.jpg diff --git a/static/images/pic05.jpg b/app/static/images/pic05.jpg similarity index 100% rename from static/images/pic05.jpg rename to app/static/images/pic05.jpg diff --git a/static/js/breakpoints.min.js b/app/static/js/breakpoints.min.js similarity index 100% rename from static/js/breakpoints.min.js rename to app/static/js/breakpoints.min.js diff --git a/static/js/browser.min.js b/app/static/js/browser.min.js similarity index 100% rename from static/js/browser.min.js rename to app/static/js/browser.min.js diff --git a/static/js/jquery.min.js b/app/static/js/jquery.min.js similarity index 100% rename from static/js/jquery.min.js rename to app/static/js/jquery.min.js diff --git a/static/js/jquery.scrollex.min.js b/app/static/js/jquery.scrollex.min.js similarity index 100% rename from static/js/jquery.scrollex.min.js rename to app/static/js/jquery.scrollex.min.js diff --git a/static/js/jquery.scrolly.min.js b/app/static/js/jquery.scrolly.min.js similarity index 100% rename from static/js/jquery.scrolly.min.js rename to app/static/js/jquery.scrolly.min.js diff --git a/static/js/main.js b/app/static/js/main.js similarity index 100% rename from static/js/main.js rename to app/static/js/main.js diff --git a/static/js/util.js b/app/static/js/util.js similarity index 100% rename from static/js/util.js rename to app/static/js/util.js diff --git a/static/sass/libs/_breakpoints.scss b/app/static/sass/libs/_breakpoints.scss similarity index 100% rename from static/sass/libs/_breakpoints.scss rename to app/static/sass/libs/_breakpoints.scss diff --git a/static/sass/libs/_functions.scss b/app/static/sass/libs/_functions.scss similarity index 100% rename from static/sass/libs/_functions.scss rename to app/static/sass/libs/_functions.scss diff --git a/static/sass/libs/_html-grid.scss b/app/static/sass/libs/_html-grid.scss similarity index 100% rename from static/sass/libs/_html-grid.scss rename to app/static/sass/libs/_html-grid.scss diff --git a/static/sass/libs/_mixins.scss b/app/static/sass/libs/_mixins.scss similarity index 100% rename from static/sass/libs/_mixins.scss rename to app/static/sass/libs/_mixins.scss diff --git a/static/sass/libs/_vars.scss b/app/static/sass/libs/_vars.scss similarity index 100% rename from static/sass/libs/_vars.scss rename to app/static/sass/libs/_vars.scss diff --git a/static/sass/libs/_vendor.scss b/app/static/sass/libs/_vendor.scss similarity index 100% rename from static/sass/libs/_vendor.scss rename to app/static/sass/libs/_vendor.scss diff --git a/static/sass/main.scss b/app/static/sass/main.scss similarity index 100% rename from static/sass/main.scss rename to app/static/sass/main.scss diff --git a/static/sass/noscript.scss b/app/static/sass/noscript.scss similarity index 100% rename from static/sass/noscript.scss rename to app/static/sass/noscript.scss diff --git a/app/templates/dashboard.html b/app/templates/dashboard.html new file mode 100644 index 0000000..b602dea --- /dev/null +++ b/app/templates/dashboard.html @@ -0,0 +1,96 @@ +{% extends "template.html" %} +{% block content %} + + +
+
+

Dashboard

+

Your personal dashboard

+
+
+
+ +

Current automatized tweets

+
+ + + + + + + + + + + {% for t in tweets %} + + + + + + + {% endfor %} + +
TweetSlotsKeywordsActions
{{ t['text'] }}
{{ t['slots'] }}{{ t['keywords'] }}Disable + Delet
+
+ +

Add an automatized tweet

+
+
+
+
+
+ {% for t in timeline %} +
+ + +
+ {% endfor %} +
+
+ + +
+
+
+ +
+
+ +

Trello board

+
+
+
+
+

Choose a board

+
+ {% for b in boards %} +
+ + +
+ {% endfor %} + +
+
+
+

Choose a column

+
+ {% for c in columns %} +
+ + +
+ {% endfor %} + +
+
+
+
+
+
+
+
+ +{% endblock %} diff --git a/templates/elements.html b/app/templates/elements.html similarity index 100% rename from templates/elements.html rename to app/templates/elements.html diff --git a/templates/index.html b/app/templates/index.html similarity index 97% rename from templates/index.html rename to app/templates/index.html index f50fb47..353aea9 100644 --- a/templates/index.html +++ b/app/templates/index.html @@ -7,10 +7,10 @@

Cyberplanificateur

Manage your commissions was never so easy with with the Cyberplanificateur

diff --git a/app/templates/login.html b/app/templates/login.html new file mode 100644 index 0000000..1dfec0b --- /dev/null +++ b/app/templates/login.html @@ -0,0 +1,31 @@ +{% extends "template.html" %} +{% block content %} + + +
+
+

Sign In

+
+
+
+ +
+ {{ form.hidden_tag() }} +

+ {{ form.username.label }}
+ {{ form.username(size=32) }} +

+

+ {{ form.password.label }}
+ {{ form.password(size=32) }} +

+

{{ form.remember_me() }} {{ form.remember_me.label }}

+

{{ form.submit() }}

+
+

New User? Click to Register!

+ +
+
+
+ +{% endblock %} diff --git a/app/templates/register.html b/app/templates/register.html new file mode 100644 index 0000000..86cfa37 --- /dev/null +++ b/app/templates/register.html @@ -0,0 +1,49 @@ +{% extends "template.html" %} +{% block content %} + + +
+
+

Register

+
+
+
+ +
+ {{ form.hidden_tag() }} +

+ {{ form.username.label }}
+ {{ form.username(size=32) }}
+ {% for error in form.username.errors %} + [{{ error }}] + {% endfor %} +

+

+ {{ form.email.label }}
+ {{ form.email(size=64) }}
+ {% for error in form.email.errors %} + [{{ error }}] + {% endfor %} +

+

+ {{ form.password.label }}
+ {{ form.password(size=32) }}
+ {% for error in form.password.errors %} + [{{ error }}] + {% endfor %} +

+

+ {{ form.password2.label }}
+ {{ form.password2(size=32) }}
+ {% for error in form.password2.errors %} + [{{ error }}] + {% endfor %} +

+

{{ form.submit() }}

+
+ +
+
+
+ +{% endblock %} diff --git a/templates/settings.html b/app/templates/settings.html similarity index 61% rename from templates/settings.html rename to app/templates/settings.html index c4495bd..0f19606 100644 --- a/templates/settings.html +++ b/app/templates/settings.html @@ -11,16 +11,21 @@

Connexions

- {% if trloginfail and not trlogin %} -

Invalid Trello token !

+

Twitter : + {% if twlogin %} + Connected

+ Disconnect + {% else %} + Disconnected

+ Connect {% endif %}

Trello : {% if trlogin %} Connected

- Disconnect + Disconnect {% else %} Disconnected

-

Click here and give the token bellow

+

Click here and give the token bellow

diff --git a/templates/template.html b/app/templates/template.html similarity index 93% rename from templates/template.html rename to app/templates/template.html index 2e9ecfe..e4482f7 100644 --- a/templates/template.html +++ b/app/templates/template.html @@ -27,12 +27,12 @@ diff --git a/config.py b/config.py new file mode 100644 index 0000000..1828423 --- /dev/null +++ b/config.py @@ -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 diff --git a/cyberplanificateur.py b/cyberplanificateur.py new file mode 100644 index 0000000..fb9fbfe --- /dev/null +++ b/cyberplanificateur.py @@ -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") diff --git a/database.py b/database.py index 1fe73b3..3bbd5dd 100644 --- a/database.py +++ b/database.py @@ -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") diff --git a/site.py b/site.py deleted file mode 100644 index 5869ec8..0000000 --- a/site.py +++ /dev/null @@ -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") diff --git a/templates/dashboard.html b/templates/dashboard.html deleted file mode 100644 index 5ebf1ce..0000000 --- a/templates/dashboard.html +++ /dev/null @@ -1,64 +0,0 @@ -{% extends "template.html" %} -{% block content %} - - -
-
-

Dashboard

-

Your personal dashboard

-
-
-
- -

Current automatized tweets

-
- - {% for t in tweets %} - - - - - {% endfor %} -
{{ t }}
Disable - Delet
-
- -

Add an automatized tweet

-
-
-
-
- {% for t in timeline %} -
- - -
- {% endfor %} -
-
- - -
-
-
- -
- -

Trello board

-
-
-
-
-

Choose a board

-
-
-

Choose a columns

-
-
-
-
-
-
-
- -{% endblock %} diff --git a/tr.py b/tr.py new file mode 100644 index 0000000..e0cd1fb --- /dev/null +++ b/tr.py @@ -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) diff --git a/tw.py b/tw.py new file mode 100644 index 0000000..59cebe1 --- /dev/null +++ b/tw.py @@ -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()