From 02a88cda3cce2a1782d3680ce9146d1b6076e7f3 Mon Sep 17 00:00:00 2001 From: williamneto Date: Sat, 3 Sep 2022 20:28:34 -0300 Subject: [PATCH 01/14] Adicionando blueprint para gerenciar rotas --- app/api.py => api.py | 0 app/__init__.py | 8 ++++++-- app/routes/analise/route.py | 37 +++++++++++++++++++++++++++++++++++++ 3 files changed, 43 insertions(+), 2 deletions(-) rename app/api.py => api.py (100%) create mode 100644 app/routes/analise/route.py diff --git a/app/api.py b/api.py similarity index 100% rename from app/api.py rename to api.py diff --git a/app/__init__.py b/app/__init__.py index 2bb9061..4008175 100644 --- a/app/__init__.py +++ b/app/__init__.py @@ -1,9 +1,13 @@ import settings as s from flask import Flask -app = Flask(__name__) # Flask core instance initiated +app = Flask(__name__, template_folder="templates/") # Flask core instance initiated app.config["SQLALCHEMY_DATABASE_URI"] = s.os.environ.get("DATABASE_URL") app.config['JSON_SORT_KEYS'] = False app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False -from app.routes import routes +from app.routes.analise.route import router as analise_router +from app.routes.auth.route import router as auth_router + +app.register_blueprint(analise_router) +app.register_blueprint(auth_router) \ No newline at end of file diff --git a/app/routes/analise/route.py b/app/routes/analise/route.py new file mode 100644 index 0000000..dce44df --- /dev/null +++ b/app/routes/analise/route.py @@ -0,0 +1,37 @@ +from flask import Blueprint +from flask import jsonify, request + +from app.models.models import Analises, AnaliseSchema +from app.services.botometer_service import BotometerService + +router = Blueprint( + "analise", + __name__ +) + +@router.get("/catch") +def catch(): + handle = str(request.args.get('profile')) + botometer_service = BotometerService() + response = botometer_service.catch(handle) + return jsonify(response), 200 + + +@router.get('/botprobability') # test only +def botprobability(): + handle = str(request.args.get('profile')) + botometer_service = BotometerService() + response = botometer_service.botProbability(handle) + return jsonify(response), 200 + +@router.get('/complete') +def complete(): + handle = str(request.args.get('profile')) + result = Analises.query.filter_by(handle=handle).first() + # result = Analises.query.get(1); + analise_schema = AnaliseSchema() + return jsonify(analise_schema.dump(result)) + +@router.post('/feedback') +def feedback(): + return jsonify("feedback") From 8998421fef0ee1361063744ed7980c6bfa04ae4f Mon Sep 17 00:00:00 2001 From: williamneto Date: Sat, 3 Sep 2022 20:34:04 -0300 Subject: [PATCH 02/14] =?UTF-8?q?Iniciando=20estrutura=20de=20autentica?= =?UTF-8?q?=C3=A7=C3=A3o?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/models/auth.py | 30 +++++++++++++++++++++++++ app/routes/auth/route.py | 24 ++++++++++++++++++++ app/routes/auth/templates/login.html | 6 +++++ app/routes/auth/templates/register.html | 7 ++++++ app/templates/base.html | 10 +++++++++ 5 files changed, 77 insertions(+) create mode 100644 app/models/auth.py create mode 100644 app/routes/auth/route.py create mode 100644 app/routes/auth/templates/login.html create mode 100644 app/routes/auth/templates/register.html create mode 100644 app/templates/base.html diff --git a/app/models/auth.py b/app/models/auth.py new file mode 100644 index 0000000..4bd98ac --- /dev/null +++ b/app/models/auth.py @@ -0,0 +1,30 @@ +"""Database models.""" +from flask_login import UserMixin +from werkzeug.security import check_password_hash, generate_password_hash + +from . import db + + +class User(UserMixin, db.Model): + """User account model.""" + + __tablename__ = "flasklogin-users" + id = db.Column(db.Integer, primary_key=True) + name = db.Column(db.String(100), nullable=False, unique=False) + email = db.Column(db.String(40), unique=True, nullable=False) + password = db.Column( + db.String(200), primary_key=False, unique=False, nullable=False + ) + created_on = db.Column(db.DateTime, index=False, unique=False, nullable=True) + last_login = db.Column(db.DateTime, index=False, unique=False, nullable=True) + + def set_password(self, password): + """Create hashed password.""" + self.password = generate_password_hash(password, method="sha256") + + def check_password(self, password): + """Check hashed password.""" + return check_password_hash(self.password, password) + + def __repr__(self): + return "".format(self.username) diff --git a/app/routes/auth/route.py b/app/routes/auth/route.py new file mode 100644 index 0000000..0806f32 --- /dev/null +++ b/app/routes/auth/route.py @@ -0,0 +1,24 @@ +from flask import Blueprint, render_template +from flask import jsonify, request + +from app.models.models import Analises, AnaliseSchema +from app.services.botometer_service import BotometerService + +router = Blueprint( + "auth", + __name__, + url_prefix="/auth", + template_folder="templates" +) + +@router.get("/login") +def login(): + return render_template( + "login.html", + ) + +@router.get("/register") +def register(): + return render_template( + "register.html" + ) \ No newline at end of file diff --git a/app/routes/auth/templates/login.html b/app/routes/auth/templates/login.html new file mode 100644 index 0000000..ff29fe7 --- /dev/null +++ b/app/routes/auth/templates/login.html @@ -0,0 +1,6 @@ +{% extends "base.html" %} + +{% block title %}Login{% endblock %} +{% block main %} +

Login

+{% endblock %} \ No newline at end of file diff --git a/app/routes/auth/templates/register.html b/app/routes/auth/templates/register.html new file mode 100644 index 0000000..c284373 --- /dev/null +++ b/app/routes/auth/templates/register.html @@ -0,0 +1,7 @@ +{% extends "base.html" %} + +{% block title %}Cadastro{% endblock %} +{% block main %} +

Cadastro

+

--{{ nome_user }}

+{% endblock %} \ No newline at end of file diff --git a/app/templates/base.html b/app/templates/base.html new file mode 100644 index 0000000..1275a05 --- /dev/null +++ b/app/templates/base.html @@ -0,0 +1,10 @@ + + + {% block title %}{% endblock %} | Pegabot + + + aa + {% block main %}{% endblock %} + + + \ No newline at end of file From a342e98aa9c320cd6a643cbbfbba12d07150d8e7 Mon Sep 17 00:00:00 2001 From: williamneto Date: Sat, 3 Sep 2022 22:21:21 -0300 Subject: [PATCH 03/14] =?UTF-8?q?Estrutura=20de=20autentica=C3=A7=C3=A3o?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/__init__.py | 9 ++- app/routes/auth/forms.py | 43 +++++++++++++++ app/routes/auth/route.py | 73 ++++++++++++++++++++++--- app/routes/auth/templates/login.html | 52 ++++++++++++++++-- app/routes/auth/templates/register.html | 7 --- app/routes/auth/templates/signup.html | 72 ++++++++++++++++++++++++ app/templates/base.html | 19 +++++-- migrations/versions/0b2f74965b1c_.py | 37 +++++++++++++ 8 files changed, 287 insertions(+), 25 deletions(-) create mode 100644 app/routes/auth/forms.py delete mode 100644 app/routes/auth/templates/register.html create mode 100644 app/routes/auth/templates/signup.html create mode 100644 migrations/versions/0b2f74965b1c_.py diff --git a/app/__init__.py b/app/__init__.py index 4008175..ca3ac96 100644 --- a/app/__init__.py +++ b/app/__init__.py @@ -1,13 +1,20 @@ import settings as s from flask import Flask +from flask_login import LoginManager app = Flask(__name__, template_folder="templates/") # Flask core instance initiated app.config["SQLALCHEMY_DATABASE_URI"] = s.os.environ.get("DATABASE_URL") app.config['JSON_SORT_KEYS'] = False app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False +app.config['SECRET_KEY'] ="LOINPV0898h-987hoIUB086vgo(*¨F(&tvOUYVhygvioutgf97VUvg" + +login_manager = LoginManager() +login_manager.init_app(app) from app.routes.analise.route import router as analise_router from app.routes.auth.route import router as auth_router +from app.routes.lab.route import router as lab_router app.register_blueprint(analise_router) -app.register_blueprint(auth_router) \ No newline at end of file +app.register_blueprint(auth_router) +app.register_blueprint(lab_router) \ No newline at end of file diff --git a/app/routes/auth/forms.py b/app/routes/auth/forms.py new file mode 100644 index 0000000..574356b --- /dev/null +++ b/app/routes/auth/forms.py @@ -0,0 +1,43 @@ +"""Sign-up & log-in forms.""" +from flask_wtf import FlaskForm +from wtforms import PasswordField, StringField, SubmitField +from wtforms.validators import DataRequired, Email, EqualTo, Length, Optional + + +class SignupForm(FlaskForm): + """User Sign-up Form.""" + + name = StringField("Name", validators=[DataRequired()]) + email = StringField( + "Email", + validators=[ + Length(min=6), + Email(message="Enter a valid email."), + DataRequired(), + ], + ) + password = PasswordField( + "Password", + validators=[ + DataRequired(), + Length(min=6, message="Select a stronger password."), + ], + ) + confirm = PasswordField( + "Confirm Your Password", + validators=[ + DataRequired(), + EqualTo("password", message="Passwords must match."), + ], + ) + submit = SubmitField("Register") + + +class LoginForm(FlaskForm): + """User Log-in Form.""" + + email = StringField( + "Email", validators=[DataRequired(), Email(message="Enter a valid email.")] + ) + password = PasswordField("Password", validators=[DataRequired()]) + submit = SubmitField("Log In") diff --git a/app/routes/auth/route.py b/app/routes/auth/route.py index 0806f32..b0a42c5 100644 --- a/app/routes/auth/route.py +++ b/app/routes/auth/route.py @@ -1,8 +1,11 @@ -from flask import Blueprint, render_template +from flask import Blueprint, flash, redirect, render_template, request, url_for from flask import jsonify, request +from flask_login import current_user, login_user -from app.models.models import Analises, AnaliseSchema -from app.services.botometer_service import BotometerService +from app import login_manager +from app.routes.auth.forms import SignupForm, LoginForm +from app.models.auth import User +from app.models import db router = Blueprint( "auth", @@ -11,14 +14,68 @@ template_folder="templates" ) -@router.get("/login") +@router.route("/login", methods=["GET", "POST"]) def login(): + """ + Log-in page for registered users. + + GET requests serve Log-in page. + POST requests validate and redirect user to dashboard. + """ + # Bypass if user is logged in + if current_user.is_authenticated: + return redirect(url_for("lab.home")) + + form = LoginForm() + # Validate login attempt + if form.validate_on_submit(): + user = User.query.filter_by(email=form.email.data).first() + if user and user.check_password(password=form.password.data): + login_user(user) + next_page = request.args.get("next") + return redirect(next_page or url_for("lab.home")) + flash("Invalid username/password combination") + return redirect(url_for("auth.login")) return render_template( "login.html", + form=form, + title="Log in.", + template="login-page", + body="Log in with your User account.", ) -@router.get("/register") -def register(): +@login_manager.user_loader +def load_user(user_id): + """Check if user is logged-in upon page load.""" + if user_id is not None: + return User.query.get(user_id) + return None + +@router.route("/signup", methods=["GET", "POST"]) +def signup(): + """ + User sign-up page. + + GET requests serve sign-up page. + POST requests validate form & user creation. + """ + form = SignupForm() + if form.validate_on_submit(): + existing_user = User.query.filter_by(email=form.email.data).first() + if existing_user is None: + user = User( + name=form.name.data, email=form.email.data + ) + user.set_password(form.password.data) + db.session.add(user) + db.session.commit() # Create new user + + return redirect(url_for("auth.login")) + flash("A user already exists with that email address.") return render_template( - "register.html" - ) \ No newline at end of file + "signup.html", + title="Create an Account.", + form=form, + template="signup-page", + body="Sign up for a user account.", + ) diff --git a/app/routes/auth/templates/login.html b/app/routes/auth/templates/login.html index ff29fe7..257c5a2 100644 --- a/app/routes/auth/templates/login.html +++ b/app/routes/auth/templates/login.html @@ -1,6 +1,50 @@ {% extends "base.html" %} -{% block title %}Login{% endblock %} -{% block main %} -

Login

-{% endblock %} \ No newline at end of file +{% block content %} +
+ + {% for message in get_flashed_messages() %} +
+ + {{ message }} +
+ {% endfor %} + +

Log In

+ +
+ {{ form.csrf_token }} + + + +
+ {{ form.password.label }} + {{ form.password }} + {% if form.email.errors %} +
    + {% for error in form.password.errors %} +
  • {{ error }}
  • {% endfor %} +
+ {% endif %} +
+ +
+ {{ form.submit }} +
+ + + +
+
+{% endblock %} diff --git a/app/routes/auth/templates/register.html b/app/routes/auth/templates/register.html deleted file mode 100644 index c284373..0000000 --- a/app/routes/auth/templates/register.html +++ /dev/null @@ -1,7 +0,0 @@ -{% extends "base.html" %} - -{% block title %}Cadastro{% endblock %} -{% block main %} -

Cadastro

-

--{{ nome_user }}

-{% endblock %} \ No newline at end of file diff --git a/app/routes/auth/templates/signup.html b/app/routes/auth/templates/signup.html new file mode 100644 index 0000000..64b2685 --- /dev/null +++ b/app/routes/auth/templates/signup.html @@ -0,0 +1,72 @@ +{% extends "base.html" %} + +{% block content %} +
+ + {% for message in get_flashed_messages() %} +
+ + {{ message }} +
+ {% endfor %} + +

Sign Up

+ +
+ {{ form.csrf_token }} + +
+ {{ form.name.label }} + {{ form.name(placeholder='John Smith') }} + {% if form.name.errors %} +
    + {% for error in form.email.errors %} +
  • {{ error }}
  • {% endfor %} +
+ {% endif %} +
+ + + +
+ {{ form.password.label }} + {{ form.password }} + {% if form.password.errors %} +
    + {% for error in form.password.errors %} +
  • {{ error }}
  • {% endfor %} +
+ {% endif %} +
+ +
+ {{ form.confirm.label }} + {{ form.confirm }} + {% if form.confirm.errors %} +
    + {% for error in form.confirm.errors %} +
  • {{ error }}
  • {% endfor %} +
+ {% endif %} +
+ +
+ {{ form.submit }} +
+ +
+ + +
+{% endblock %} diff --git a/app/templates/base.html b/app/templates/base.html index 1275a05..14213a1 100644 --- a/app/templates/base.html +++ b/app/templates/base.html @@ -1,10 +1,19 @@ - + + + + {% block title %}{% endblock %} | Pegabot - + + + + + - aa - {% block main %}{% endblock %} +
+ {% block content %}{% endblock %} +
- \ No newline at end of file + + diff --git a/migrations/versions/0b2f74965b1c_.py b/migrations/versions/0b2f74965b1c_.py new file mode 100644 index 0000000..58795f0 --- /dev/null +++ b/migrations/versions/0b2f74965b1c_.py @@ -0,0 +1,37 @@ +"""empty message + +Revision ID: 0b2f74965b1c +Revises: 6c7352e536fe +Create Date: 2022-09-03 21:06:39.614216 + +""" +from alembic import op +import sqlalchemy as sa + + +# revision identifiers, used by Alembic. +revision = '0b2f74965b1c' +down_revision = '6c7352e536fe' +branch_labels = None +depends_on = None + + +def upgrade(): + # ### commands auto generated by Alembic - please adjust! ### + op.create_table('flasklogin-users', + sa.Column('id', sa.Integer(), nullable=False), + sa.Column('name', sa.String(length=100), nullable=False), + sa.Column('email', sa.String(length=40), nullable=False), + sa.Column('password', sa.String(length=200), nullable=False), + sa.Column('created_on', sa.DateTime(), nullable=True), + sa.Column('last_login', sa.DateTime(), nullable=True), + sa.PrimaryKeyConstraint('id'), + sa.UniqueConstraint('email') + ) + # ### end Alembic commands ### + + +def downgrade(): + # ### commands auto generated by Alembic - please adjust! ### + op.drop_table('flasklogin-users') + # ### end Alembic commands ### From 8c5b49f7ae344c349caff82b69d00b6010d13100 Mon Sep 17 00:00:00 2001 From: williamneto Date: Sun, 4 Sep 2022 12:00:24 -0300 Subject: [PATCH 04/14] desafio.md --- desafio.md | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) create mode 100644 desafio.md diff --git a/desafio.md b/desafio.md new file mode 100644 index 0000000..a03a34b --- /dev/null +++ b/desafio.md @@ -0,0 +1,20 @@ +*Ampliar a capacidade de análises da aplicação, buscando por bots nas interações de usuários e hashtags através de uma área de usuário* + +**Interface do usuário** +- Página de cadastro +- Página de login +- Página principal - Laboratório + - Analisar perfis + - Analisar interações de perfis + - Analisar interações de hashtags * + - Criar alertas * +- Página de configurações + - Adicionar e editar chaves de API do Twitter + - Editar dados do usuário + +**Dúvidas** +- Acesso ao frontend atual do projeto - OK +- Chaves de API do Twitter - OK + +API Key: H85LUw9dCJWWf95prVb7HrKTg +API Key Secret: Bfz2JxpZwRBYRtrAdcutbIbE8bLklAEGkNMb4MKkBOBRaua66B \ No newline at end of file From d080e315a5598224b05d2e82a31c0f06d318a424 Mon Sep 17 00:00:00 2001 From: Mayara Melo <106121757+mayaramelo@users.noreply.github.com> Date: Sun, 4 Sep 2022 14:35:27 -0300 Subject: [PATCH 05/14] Login Rascunho Tentativa 1 --- login | 421 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 421 insertions(+) create mode 100644 login diff --git a/login b/login new file mode 100644 index 0000000..0d3f6f1 --- /dev/null +++ b/login @@ -0,0 +1,421 @@ + + + + + + + + + + + + + +PEGABOT Login + + + + +
+
==$0 +
+ +
+
+
+
+
+ +
== $0 + + From 8623a2e576de969f4334de5d8d1d227251545b2a Mon Sep 17 00:00:00 2001 From: williamneto Date: Sun, 4 Sep 2022 16:12:45 -0300 Subject: [PATCH 06/14] =?UTF-8?q?Implementando=20an=C3=A1lise=20de=20inter?= =?UTF-8?q?a=C3=A7=C3=B5es?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/models/models.py | 9 +- app/routes/lab/route.py | 120 +++++++++++++++++++++++++++ app/services/botometer_service.py | 5 -- app/services/twitter_handler.py | 17 +++- migrations/versions/619207295bd8_.py | 34 ++++++++ pyproject.toml | 1 + 6 files changed, 174 insertions(+), 12 deletions(-) create mode 100644 app/routes/lab/route.py create mode 100644 migrations/versions/619207295bd8_.py diff --git a/app/models/models.py b/app/models/models.py index f236d7f..0cecf85 100644 --- a/app/models/models.py +++ b/app/models/models.py @@ -13,10 +13,6 @@ class Analises(db.Model): id = db.Column(db.Integer, primary_key=True) handle = db.Column(db.String(80), nullable=False) total = db.Column(db.String(120), nullable=True) - friends = db.Column(db.String(120), nullable=True) - network = db.Column(db.String(120), nullable=True) - sentiment = db.Column(db.String(120), nullable=True) - temporal = db.Column(db.String(120), nullable=True) twitter_id = db.Column(db.String(120), nullable=True) twitter_handle = db.Column(db.String(120), nullable=True) twitter_user_name = db.Column(db.String(120), nullable=True) @@ -40,7 +36,10 @@ class Analises(db.Model): def process_bind_param(value): if type(value) is str: - return datetime.strptime(value, '%Y-%m-%dT %H:%M:%S') + try: + return datetime.strptime(value, '%Y-%m-%dT %H:%M:%S') + except: + return datetime.strptime(value, "%a %b %d %H:%M:%S %z %Y") return value def __repr__(self): diff --git a/app/routes/lab/route.py b/app/routes/lab/route.py new file mode 100644 index 0000000..e542292 --- /dev/null +++ b/app/routes/lab/route.py @@ -0,0 +1,120 @@ +from datetime import date, datetime, timedelta +from crypt import methods +from flask import Blueprint, flash, redirect, render_template, request, url_for +from flask import jsonify, request +from flask_login import current_user, login_required, logout_user +import json + +from app.models import db +from app.services.twitter_handler import TwitterHandler +from app.services.botometer_service import BotometerService +from app.models.models import BotProbability, Analises, AnaliseSchema + +router = Blueprint( + "lab", + __name__, + url_prefix="/lab", + template_folder="templates" +) + +@router.route("/home", methods=["GET"]) +@login_required +def home(): + def _getUser(user_data): + user = [{ + "created_at": user_data["created_at"], + "default_profile": user_data["default_profile"], + "description": user_data["description"], + "followers_count": user_data["followers_count"], + "friends_count": user_data["friends_count"], + "handle": user_data["screen_name"], + "lang": user_data["lang"], + "location": user_data["location"], + "name": user_data["name"], + "profile_image": user_data["profile_image_url"], + "twitter_id": user_data["id"], + "twitter_is_protected": user_data["protected"], + "verified": user_data["verified"], + "withheld_in_countries": user_data["withheld_in_countries"], + "É Bot?": '' + }] + + return(user) + + analises = None + target = request.args.get("target") + + if target: + handler = TwitterHandler() + botometer = BotometerService() + pegabot = BotProbability() + + data = handler.searchTweets( + q=target, + num_tweets=20, + ) + analises = [] + + for item in data: + user = item._json["user"] + + user_hist = botometer.findUserAnalisisByHandle( + user["screen_name"] + ) + + if "id" in user_hist: + analises.append(user_hist) + else: + user_tl = handler.getUserTimeline( + user["id"] + ) + + if 'api_errors' in user_tl: + # Fri Dec 10 00:43:39 +0000 2021 + created_datetime = datetime.strptime( + user["created_at"], + "%a %b %d %H:%M:%S %z %Y" + ) + if(date.today() == created_datetime): + print("Account created today") + # return {'api_errors': [{'code': '11', 'message:': 'Account created today.'}], 'codes': '11', 'reason': 'Too litle information available', 'args': 'Account created today.'} + # return user_tl + + probability = pegabot.botProbability( + str.lower(user["screen_name"]), + user_tl, + _getUser(user) + ) + analise = Analises( + # User + handle = user["screen_name"], + twitter_id = user["id"], + twitter_handle = str.lower(user["screen_name"]), + twitter_user_name = user["name"], + twitter_is_protected = user["protected"], + twitter_user_description = user["description"], + twitter_followers_count = user["followers_count"], + twitter_friends_count = user["friends_count"], + twitter_location = user["location"], + twitter_is_verified = user["verified"], + twitter_lang = user["lang"], + twitter_created_at = Analises.process_bind_param(value=user["created_at"]), + twitter_default_profile = user["default_profile"], + twitter_profile_image = user["profile_image_url"], + # twitter_withheld_in_countries = response.twitter_withheld_in_countries, # giving error, needs a refactor + total = probability.total, + cache_times_served = 0, # + cache_validity = datetime.today() + timedelta(30), + pegabot_version = probability.pegabot_version, + ) + db.session.add(analise) + db.session.commit() + analise_schema = AnaliseSchema() + analises.append( + analise_schema.dump(analise) + ) + return render_template( + "home.html", + current_user=current_user, + analises=analises + ) \ No newline at end of file diff --git a/app/services/botometer_service.py b/app/services/botometer_service.py index 82e6aca..155787f 100644 --- a/app/services/botometer_service.py +++ b/app/services/botometer_service.py @@ -19,7 +19,6 @@ def catch(self, handle): ''' user = self.findUserAnalisisByHandle(handle=handle) response = self.twitter_handler.findByHandle(handle=handle) # check on twitter - print(response) if 'id' in user: if 'api_errors' not in response: return user return response @@ -55,10 +54,6 @@ def catch(self, handle): twitter_profile_image = response.twitter_profile_image, # twitter_withheld_in_countries = response.twitter_withheld_in_countries, # giving error, needs a refactor total = probability.total, - friends = 0,#probability.friends, - temporal = 0,#probability.temporal, - network = 0,#probability.network, - sentiment = 0,#probability.sentiment, cache_times_served = 0, # cache_validity = datetime.today() + timedelta(30), pegabot_version = probability.pegabot_version, diff --git a/app/services/twitter_handler.py b/app/services/twitter_handler.py index 0c0f96b..20221f5 100644 --- a/app/services/twitter_handler.py +++ b/app/services/twitter_handler.py @@ -55,10 +55,23 @@ def findByHandle(self, handle): print("Tweepy Error retrieving user: {}".format(e)) return {'api_errors': e.api_errors, 'codes': e.api_codes, 'reason': e.response.reason, 'args': e.args} + def searchTweets(self, q, num_tweets=10, result_type="recent"): + tweets = self.api.search_tweets( + q=q, + count=num_tweets, + result_type="recent" + ) - def getUserTimeline(self, uid, num_tweets=100): + return tweets + + def getUserTimeline(self, uid, num_tweets=100, exclude_replies=True): try: - timeline = self.api.user_timeline(user_id = uid, count = num_tweets) + timeline = self.api.user_timeline( + user_id = uid, + count = num_tweets, + exclude_replies = exclude_replies + ) + tweets = [] for tweet in timeline: x = { diff --git a/migrations/versions/619207295bd8_.py b/migrations/versions/619207295bd8_.py new file mode 100644 index 0000000..938151c --- /dev/null +++ b/migrations/versions/619207295bd8_.py @@ -0,0 +1,34 @@ +"""empty message + +Revision ID: 619207295bd8 +Revises: 0b2f74965b1c +Create Date: 2022-09-04 14:28:27.289857 + +""" +from alembic import op +import sqlalchemy as sa + + +# revision identifiers, used by Alembic. +revision = '619207295bd8' +down_revision = '0b2f74965b1c' +branch_labels = None +depends_on = None + + +def upgrade(): + # ### commands auto generated by Alembic - please adjust! ### + op.drop_column('analises', 'friends') + op.drop_column('analises', 'sentiment') + op.drop_column('analises', 'network') + op.drop_column('analises', 'temporal') + # ### end Alembic commands ### + + +def downgrade(): + # ### commands auto generated by Alembic - please adjust! ### + op.add_column('analises', sa.Column('temporal', sa.VARCHAR(length=120), nullable=True)) + op.add_column('analises', sa.Column('network', sa.VARCHAR(length=120), nullable=True)) + op.add_column('analises', sa.Column('sentiment', sa.VARCHAR(length=120), nullable=True)) + op.add_column('analises', sa.Column('friends', sa.VARCHAR(length=120), nullable=True)) + # ### end Alembic commands ### diff --git a/pyproject.toml b/pyproject.toml index 6d9b07d..5913620 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -32,6 +32,7 @@ SQLAlchemy = "1.4.25" tweepy = "4.1.0" urllib3 = "1.26.7" Werkzeug = "2.0.2" +sklearn = "0.0" [tool.poetry.dev-dependencies] From 5f7e229d224a67c9e5eba2eb10ec0515d2b4608d Mon Sep 17 00:00:00 2001 From: williamneto Date: Sun, 4 Sep 2022 16:26:31 -0300 Subject: [PATCH 07/14] =?UTF-8?q?Implementando=20formul=C3=A1rio=20de=20an?= =?UTF-8?q?=C3=A1lise=20de=20intera=C3=A7=C3=B5es?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/routes/lab/forms.py | 8 +++++++ app/routes/lab/route.py | 11 ++++++---- app/routes/lab/templates/home.html | 34 ++++++++++++++++++++++++++++++ 3 files changed, 49 insertions(+), 4 deletions(-) create mode 100644 app/routes/lab/forms.py create mode 100644 app/routes/lab/templates/home.html diff --git a/app/routes/lab/forms.py b/app/routes/lab/forms.py new file mode 100644 index 0000000..c1026fe --- /dev/null +++ b/app/routes/lab/forms.py @@ -0,0 +1,8 @@ +from flask_wtf import FlaskForm +from wtforms import StringField, SubmitField + +class AnaliseForm(FlaskForm): + handle = StringField( + "Termo", + ) + submit = SubmitField("Analisar") \ No newline at end of file diff --git a/app/routes/lab/route.py b/app/routes/lab/route.py index e542292..09fb352 100644 --- a/app/routes/lab/route.py +++ b/app/routes/lab/route.py @@ -9,6 +9,7 @@ from app.services.twitter_handler import TwitterHandler from app.services.botometer_service import BotometerService from app.models.models import BotProbability, Analises, AnaliseSchema +from app.routes.lab.forms import AnaliseForm router = Blueprint( "lab", @@ -17,7 +18,7 @@ template_folder="templates" ) -@router.route("/home", methods=["GET"]) +@router.route("/home", methods=["GET", "POST"]) @login_required def home(): def _getUser(user_data): @@ -41,16 +42,16 @@ def _getUser(user_data): return(user) + form = AnaliseForm() analises = None - target = request.args.get("target") - if target: + if form.validate_on_submit(): handler = TwitterHandler() botometer = BotometerService() pegabot = BotProbability() data = handler.searchTweets( - q=target, + q=form.handle.data, num_tweets=20, ) analises = [] @@ -113,8 +114,10 @@ def _getUser(user_data): analises.append( analise_schema.dump(analise) ) + return render_template( "home.html", current_user=current_user, + form=form, analises=analises ) \ No newline at end of file diff --git a/app/routes/lab/templates/home.html b/app/routes/lab/templates/home.html new file mode 100644 index 0000000..70b5c77 --- /dev/null +++ b/app/routes/lab/templates/home.html @@ -0,0 +1,34 @@ +{% extends "base.html" %} + +{% block content %} + +{{ current_user.name }} + +{% if analises %} +
    + {% for analise in analises %} +
  • {{ analise.twitter_handle }} - {{ analise.total }}
  • + {% endfor %} +
+{% else %} +
+ {{ form.csrf_token }} + +
+ {{ form.handle.label }} + {{ form.handle }} + {% if form.handle.errors %} +
    + {% for error in form.handle.errors %} +
  • {{ error }}
  • {% endfor %} +
+ {% endif %} +
+ +
+ {{ form.submit }} +
+
+{% endif %} + +{% endblock content %} \ No newline at end of file From ff4ba6977c0d9bdb0487b946ad6e64b07c6dafec Mon Sep 17 00:00:00 2001 From: williamneto Date: Sun, 4 Sep 2022 16:48:47 -0300 Subject: [PATCH 08/14] =?UTF-8?q?Relacionando=20analises=20de=20intera?= =?UTF-8?q?=C3=A7=C3=B5es?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/models/auth.py | 2 +- app/models/models.py | 14 +++++++ app/routes/lab/route.py | 17 +++++++- app/routes/lab/templates/home.html | 6 +++ migrations/versions/5b4828a65817_.py | 60 ++++++++++++++++++++++++++++ 5 files changed, 96 insertions(+), 3 deletions(-) create mode 100644 migrations/versions/5b4828a65817_.py diff --git a/app/models/auth.py b/app/models/auth.py index 4bd98ac..dcd8237 100644 --- a/app/models/auth.py +++ b/app/models/auth.py @@ -8,7 +8,7 @@ class User(UserMixin, db.Model): """User account model.""" - __tablename__ = "flasklogin-users" + __tablename__ = "users" id = db.Column(db.Integer, primary_key=True) name = db.Column(db.String(100), nullable=False, unique=False) email = db.Column(db.String(40), unique=True, nullable=False) diff --git a/app/models/models.py b/app/models/models.py index 0cecf85..85af568 100644 --- a/app/models/models.py +++ b/app/models/models.py @@ -8,9 +8,23 @@ #Importa a classe de preparação de dados from app.models.prepare_data import MLTools +class AnalisesGroup(db.Model): + __tablename__ = 'analises_group' + id = db.Column(db.Integer, primary_key=True) + user = db.Column( + db.Integer, + db.ForeignKey("users.id") + ) + term = db.Column(db.String(80), nullable=False) + class Analises(db.Model): __tablename__ = 'analises' id = db.Column(db.Integer, primary_key=True) + group = db.Column( + db.Integer, + db.ForeignKey("analises_group.id"), + nullable=True + ) handle = db.Column(db.String(80), nullable=False) total = db.Column(db.String(120), nullable=True) twitter_id = db.Column(db.String(120), nullable=True) diff --git a/app/routes/lab/route.py b/app/routes/lab/route.py index 09fb352..6e137d9 100644 --- a/app/routes/lab/route.py +++ b/app/routes/lab/route.py @@ -8,7 +8,7 @@ from app.models import db from app.services.twitter_handler import TwitterHandler from app.services.botometer_service import BotometerService -from app.models.models import BotProbability, Analises, AnaliseSchema +from app.models.models import BotProbability, Analises, AnaliseSchema, AnalisesGroup from app.routes.lab.forms import AnaliseForm router = Blueprint( @@ -46,6 +46,13 @@ def _getUser(user_data): analises = None if form.validate_on_submit(): + analises_group = AnalisesGroup( + user=current_user.id, + term=form.handle.data + ) + db.session.add(analises_group) + db.session.commit() + handler = TwitterHandler() botometer = BotometerService() pegabot = BotProbability() @@ -87,6 +94,7 @@ def _getUser(user_data): _getUser(user) ) analise = Analises( + group=analises_group.id, # User handle = user["screen_name"], twitter_id = user["id"], @@ -115,9 +123,14 @@ def _getUser(user_data): analise_schema.dump(analise) ) + user_analises_groups = AnalisesGroup.query.filter_by( + user=current_user.id + ) + return render_template( "home.html", current_user=current_user, form=form, - analises=analises + analises=analises, + user_analises_groups=user_analises_groups ) \ No newline at end of file diff --git a/app/routes/lab/templates/home.html b/app/routes/lab/templates/home.html index 70b5c77..3a746eb 100644 --- a/app/routes/lab/templates/home.html +++ b/app/routes/lab/templates/home.html @@ -31,4 +31,10 @@ {% endif %} +
    + {% for item in user_analises_groups %} +
  • {{ item.term }}
  • + {% endfor %} +
+ {% endblock content %} \ No newline at end of file diff --git a/migrations/versions/5b4828a65817_.py b/migrations/versions/5b4828a65817_.py new file mode 100644 index 0000000..013ec16 --- /dev/null +++ b/migrations/versions/5b4828a65817_.py @@ -0,0 +1,60 @@ +"""empty message + +Revision ID: 5b4828a65817 +Revises: 619207295bd8 +Create Date: 2022-09-04 16:35:19.320647 + +""" +from alembic import op +import sqlalchemy as sa + + +# revision identifiers, used by Alembic. +revision = '5b4828a65817' +down_revision = '619207295bd8' +branch_labels = None +depends_on = None + + +def upgrade(): + # ### commands auto generated by Alembic - please adjust! ### + op.create_table('users', + sa.Column('id', sa.Integer(), nullable=False), + sa.Column('name', sa.String(length=100), nullable=False), + sa.Column('email', sa.String(length=40), nullable=False), + sa.Column('password', sa.String(length=200), nullable=False), + sa.Column('created_on', sa.DateTime(), nullable=True), + sa.Column('last_login', sa.DateTime(), nullable=True), + sa.PrimaryKeyConstraint('id'), + sa.UniqueConstraint('email') + ) + op.create_table('analises_group', + sa.Column('id', sa.Integer(), nullable=False), + sa.Column('user', sa.Integer(), nullable=True), + sa.Column('term', sa.String(length=80), nullable=False), + sa.ForeignKeyConstraint(['user'], ['users.id'], ), + sa.PrimaryKeyConstraint('id') + ) + op.drop_table('flasklogin-users') + op.add_column('analises', sa.Column('group', sa.Integer(), nullable=True)) + op.create_foreign_key(None, 'analises', 'analises_group', ['group'], ['id']) + # ### end Alembic commands ### + + +def downgrade(): + # ### commands auto generated by Alembic - please adjust! ### + op.drop_constraint(None, 'analises', type_='foreignkey') + op.drop_column('analises', 'group') + op.create_table('flasklogin-users', + sa.Column('id', sa.INTEGER(), nullable=False), + sa.Column('name', sa.VARCHAR(length=100), nullable=False), + sa.Column('email', sa.VARCHAR(length=40), nullable=False), + sa.Column('password', sa.VARCHAR(length=200), nullable=False), + sa.Column('created_on', sa.DATETIME(), nullable=True), + sa.Column('last_login', sa.DATETIME(), nullable=True), + sa.PrimaryKeyConstraint('id'), + sa.UniqueConstraint('email') + ) + op.drop_table('analises_group') + op.drop_table('users') + # ### end Alembic commands ### From 64934d10e9452c39b40c1f3ff6b42a8425e001fc Mon Sep 17 00:00:00 2001 From: williamneto Date: Sun, 4 Sep 2022 18:32:14 -0300 Subject: [PATCH 09/14] =?UTF-8?q?Utilizando=20chaves=20de=20API=20fornecid?= =?UTF-8?q?as=20pelo=20usu=C3=A1rio?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/models/auth.py | 5 ++++ app/routes/auth/forms.py | 6 ++++ app/routes/auth/route.py | 12 ++++++-- app/routes/auth/templates/signup.html | 41 +++++++++++++++++++++++++++ app/routes/lab/route.py | 4 ++- 5 files changed, 65 insertions(+), 3 deletions(-) diff --git a/app/models/auth.py b/app/models/auth.py index dcd8237..a79a01f 100644 --- a/app/models/auth.py +++ b/app/models/auth.py @@ -18,6 +18,11 @@ class User(UserMixin, db.Model): created_on = db.Column(db.DateTime, index=False, unique=False, nullable=True) last_login = db.Column(db.DateTime, index=False, unique=False, nullable=True) + twitter_api_key = db.Column(db.String(300), nullable=False, unique=False) + twitter_api_secret = db.Column(db.String(300), nullable=False, unique=False) + twitter_access_token = db.Column(db.String(300), nullable=False, unique=False) + twitter_access_token_secret = db.Column(db.String(300), nullable=False, unique=False) + def set_password(self, password): """Create hashed password.""" self.password = generate_password_hash(password, method="sha256") diff --git a/app/routes/auth/forms.py b/app/routes/auth/forms.py index 574356b..a5aa580 100644 --- a/app/routes/auth/forms.py +++ b/app/routes/auth/forms.py @@ -30,6 +30,12 @@ class SignupForm(FlaskForm): EqualTo("password", message="Passwords must match."), ], ) + + twitter_api_key = StringField("Twitter API Key", validators=[DataRequired()]) + twitter_api_secret = StringField("Twitter API Secret", validators=[DataRequired()]) + twitter_access_token = StringField("Twitter Access Token", validators=[DataRequired()]) + twitter_access_token_secret = StringField("Twitter Access Token Secret", validators=[DataRequired()]) + submit = SubmitField("Register") diff --git a/app/routes/auth/route.py b/app/routes/auth/route.py index b0a42c5..096e1ce 100644 --- a/app/routes/auth/route.py +++ b/app/routes/auth/route.py @@ -48,7 +48,10 @@ def login(): def load_user(user_id): """Check if user is logged-in upon page load.""" if user_id is not None: - return User.query.get(user_id) + try: + return User.query.get(user_id) + except: + return None return None @router.route("/signup", methods=["GET", "POST"]) @@ -64,7 +67,12 @@ def signup(): existing_user = User.query.filter_by(email=form.email.data).first() if existing_user is None: user = User( - name=form.name.data, email=form.email.data + name=form.name.data, + email=form.email.data, + twitter_api_key=form.twitter_api_key.data, + twitter_api_secret=form.twitter_api_secret.data, + twitter_access_token=form.twitter_access_token.data, + twitter_access_token_secret=form.twitter_access_token_secret.data ) user.set_password(form.password.data) db.session.add(user) diff --git a/app/routes/auth/templates/signup.html b/app/routes/auth/templates/signup.html index 64b2685..a4c4179 100644 --- a/app/routes/auth/templates/signup.html +++ b/app/routes/auth/templates/signup.html @@ -59,6 +59,47 @@

Sign Up

{% endif %} + + + + +
{{ form.submit }}
diff --git a/app/routes/lab/route.py b/app/routes/lab/route.py index 6e137d9..dfe1767 100644 --- a/app/routes/lab/route.py +++ b/app/routes/lab/route.py @@ -53,7 +53,9 @@ def _getUser(user_data): db.session.add(analises_group) db.session.commit() - handler = TwitterHandler() + handler = TwitterHandler( + user=current_user + ) botometer = BotometerService() pegabot = BotProbability() From cadb9c29c441dad5e75d80e1390cf1a55f659766 Mon Sep 17 00:00:00 2001 From: williamneto Date: Sun, 4 Sep 2022 19:00:15 -0300 Subject: [PATCH 10/14] =?UTF-8?q?Utilizando=20chave=20de=20API=20fornecida?= =?UTF-8?q?=20pelo=20usu=C3=A1rio?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/services/twitter_handler.py | 22 +++++++++++++++------- 1 file changed, 15 insertions(+), 7 deletions(-) diff --git a/app/services/twitter_handler.py b/app/services/twitter_handler.py index 20221f5..f31ec2e 100644 --- a/app/services/twitter_handler.py +++ b/app/services/twitter_handler.py @@ -6,13 +6,21 @@ class TwitterHandler(): - def __init__(self): - self.twitter = { - 'TWITTER_API_KEY': s.os.environ.get("twitter_api_key"), - 'TWITTER_API_SECRET': s.os.environ.get("twitter_api_secret"), - 'TWITTER_API_TOKEN': s.os.environ.get("twitter_access_token"), - 'TWITTER_API_TOKEN_SECRET': s.os.environ.get("twitter_access_token_secret") - } + def __init__(self, user=None): + if not user: + self.twitter = { + 'TWITTER_API_KEY': s.os.environ.get("twitter_api_key"), + 'TWITTER_API_SECRET': s.os.environ.get("twitter_api_secret"), + 'TWITTER_API_TOKEN': s.os.environ.get("twitter_access_token"), + 'TWITTER_API_TOKEN_SECRET': s.os.environ.get("twitter_access_token_secret") + } + else: + self.twitter = { + 'TWITTER_API_KEY': user.twitter_api_key, + 'TWITTER_API_SECRET': user.twitter_api_secret, + 'TWITTER_API_TOKEN': user.twitter_access_token, + 'TWITTER_API_TOKEN_SECRET': user.twitter_access_token_secret + } self.auth = tweepy.OAuthHandler(self.twitter.get('TWITTER_API_KEY'), self.twitter.get('TWITTER_API_SECRET')) From 68791cb84862bc7d30f2db69abfb61f8bd80f7c3 Mon Sep 17 00:00:00 2001 From: williamneto Date: Sun, 4 Sep 2022 19:03:01 -0300 Subject: [PATCH 11/14] Visualizando analises de termos anteriores --- app/routes/lab/route.py | 30 +++++++++++++- app/routes/lab/templates/analises.html | 20 +++++++++ app/routes/lab/templates/home.html | 56 ++++++++++++-------------- app/templates/base.html | 1 + 4 files changed, 75 insertions(+), 32 deletions(-) create mode 100644 app/routes/lab/templates/analises.html diff --git a/app/routes/lab/route.py b/app/routes/lab/route.py index dfe1767..99e72ab 100644 --- a/app/routes/lab/route.py +++ b/app/routes/lab/route.py @@ -124,7 +124,9 @@ def _getUser(user_data): analises.append( analise_schema.dump(analise) ) - + + return redirect("/lab/analises/%s" % analises_group.id) + user_analises_groups = AnalisesGroup.query.filter_by( user=current_user.id ) @@ -135,4 +137,30 @@ def _getUser(user_data): form=form, analises=analises, user_analises_groups=user_analises_groups + ) + +@router.route("/analises/", methods=["GET"]) +@login_required +def view_analises(group_id): + try: + group = AnalisesGroup.query.filter_by( + id=group_id + ).first() + analises = Analises.query.filter_by( + group=group_id + ) + except: + flash("Pesquisa não encontrada") + return redirect(url_for("lab.home")) + + user_analises_groups = AnalisesGroup.query.filter_by( + user=current_user.id + ) + + return render_template( + "analises.html", + current_user=current_user, + analises=analises, + term=group.term, + user_analises_groups=user_analises_groups ) \ No newline at end of file diff --git a/app/routes/lab/templates/analises.html b/app/routes/lab/templates/analises.html new file mode 100644 index 0000000..e5dbf79 --- /dev/null +++ b/app/routes/lab/templates/analises.html @@ -0,0 +1,20 @@ +{% extends "base.html" %} + +{% block title %}{{ term }}{% endblock %} + +{% block content %} +

{{ term }}

+ + +

Últimas análises

+
    + {% for item in user_analises_groups %} +
  • {{ item.term }}
  • + {% endfor %} +
+ +{% endblock content %} \ No newline at end of file diff --git a/app/routes/lab/templates/home.html b/app/routes/lab/templates/home.html index 3a746eb..a2e8809 100644 --- a/app/routes/lab/templates/home.html +++ b/app/routes/lab/templates/home.html @@ -1,40 +1,34 @@ {% extends "base.html" %} -{% block content %} +{% block title %}Lab{% endblock %} -{{ current_user.name }} +{% block content %} -{% if analises %} -
    - {% for analise in analises %} -
  • {{ analise.twitter_handle }} - {{ analise.total }}
  • - {% endfor %} -
-{% else %} -
- {{ form.csrf_token }} +

Analisar termo

+ + {{ form.csrf_token }} -
- {{ form.handle.label }} - {{ form.handle }} - {% if form.handle.errors %} -
    - {% for error in form.handle.errors %} -
  • {{ error }}
  • {% endfor %} -
- {% endif %} -
+
+ {{ form.handle.label }} + {{ form.handle }} + {% if form.handle.errors %} +
    + {% for error in form.handle.errors %} +
  • {{ error }}
  • {% endfor %} +
+ {% endif %} +
-
- {{ form.submit }} -
-
-{% endif %} +
+ {{ form.submit }} +
+ -
    - {% for item in user_analises_groups %} -
  • {{ item.term }}
  • - {% endfor %} -
+

Últimas análises

+
    + {% for item in user_analises_groups %} +
  • {{ item.term }}
  • + {% endfor %} +
{% endblock content %} \ No newline at end of file diff --git a/app/templates/base.html b/app/templates/base.html index 14213a1..22dcdbc 100644 --- a/app/templates/base.html +++ b/app/templates/base.html @@ -10,6 +10,7 @@ + {{ current_user.name }}
{% block content %}{% endblock %}
From aabf6118eab4533ead0ba423608d0ae0d74a1c54 Mon Sep 17 00:00:00 2001 From: williamneto Date: Sun, 4 Sep 2022 19:03:55 -0300 Subject: [PATCH 12/14] Ignorando migrations --- .gitignore | 2 + migrations/versions/0b2f74965b1c_.py | 37 --------------- migrations/versions/5b4828a65817_.py | 60 ------------------------- migrations/versions/619207295bd8_.py | 34 -------------- migrations/versions/6b9a6d061aa9_.py | 67 ---------------------------- migrations/versions/6c7352e536fe_.py | 30 ------------- migrations/versions/cc5846eb4bde_.py | 28 ------------ 7 files changed, 2 insertions(+), 256 deletions(-) delete mode 100644 migrations/versions/0b2f74965b1c_.py delete mode 100644 migrations/versions/5b4828a65817_.py delete mode 100644 migrations/versions/619207295bd8_.py delete mode 100644 migrations/versions/6b9a6d061aa9_.py delete mode 100644 migrations/versions/6c7352e536fe_.py delete mode 100644 migrations/versions/cc5846eb4bde_.py diff --git a/.gitignore b/.gitignore index e728253..2ce95f2 100644 --- a/.gitignore +++ b/.gitignore @@ -28,3 +28,5 @@ __pycache__/* ../.DS_Store ../.DS_Store/* .DS_Store/ + +*migrations/versions/ \ No newline at end of file diff --git a/migrations/versions/0b2f74965b1c_.py b/migrations/versions/0b2f74965b1c_.py deleted file mode 100644 index 58795f0..0000000 --- a/migrations/versions/0b2f74965b1c_.py +++ /dev/null @@ -1,37 +0,0 @@ -"""empty message - -Revision ID: 0b2f74965b1c -Revises: 6c7352e536fe -Create Date: 2022-09-03 21:06:39.614216 - -""" -from alembic import op -import sqlalchemy as sa - - -# revision identifiers, used by Alembic. -revision = '0b2f74965b1c' -down_revision = '6c7352e536fe' -branch_labels = None -depends_on = None - - -def upgrade(): - # ### commands auto generated by Alembic - please adjust! ### - op.create_table('flasklogin-users', - sa.Column('id', sa.Integer(), nullable=False), - sa.Column('name', sa.String(length=100), nullable=False), - sa.Column('email', sa.String(length=40), nullable=False), - sa.Column('password', sa.String(length=200), nullable=False), - sa.Column('created_on', sa.DateTime(), nullable=True), - sa.Column('last_login', sa.DateTime(), nullable=True), - sa.PrimaryKeyConstraint('id'), - sa.UniqueConstraint('email') - ) - # ### end Alembic commands ### - - -def downgrade(): - # ### commands auto generated by Alembic - please adjust! ### - op.drop_table('flasklogin-users') - # ### end Alembic commands ### diff --git a/migrations/versions/5b4828a65817_.py b/migrations/versions/5b4828a65817_.py deleted file mode 100644 index 013ec16..0000000 --- a/migrations/versions/5b4828a65817_.py +++ /dev/null @@ -1,60 +0,0 @@ -"""empty message - -Revision ID: 5b4828a65817 -Revises: 619207295bd8 -Create Date: 2022-09-04 16:35:19.320647 - -""" -from alembic import op -import sqlalchemy as sa - - -# revision identifiers, used by Alembic. -revision = '5b4828a65817' -down_revision = '619207295bd8' -branch_labels = None -depends_on = None - - -def upgrade(): - # ### commands auto generated by Alembic - please adjust! ### - op.create_table('users', - sa.Column('id', sa.Integer(), nullable=False), - sa.Column('name', sa.String(length=100), nullable=False), - sa.Column('email', sa.String(length=40), nullable=False), - sa.Column('password', sa.String(length=200), nullable=False), - sa.Column('created_on', sa.DateTime(), nullable=True), - sa.Column('last_login', sa.DateTime(), nullable=True), - sa.PrimaryKeyConstraint('id'), - sa.UniqueConstraint('email') - ) - op.create_table('analises_group', - sa.Column('id', sa.Integer(), nullable=False), - sa.Column('user', sa.Integer(), nullable=True), - sa.Column('term', sa.String(length=80), nullable=False), - sa.ForeignKeyConstraint(['user'], ['users.id'], ), - sa.PrimaryKeyConstraint('id') - ) - op.drop_table('flasklogin-users') - op.add_column('analises', sa.Column('group', sa.Integer(), nullable=True)) - op.create_foreign_key(None, 'analises', 'analises_group', ['group'], ['id']) - # ### end Alembic commands ### - - -def downgrade(): - # ### commands auto generated by Alembic - please adjust! ### - op.drop_constraint(None, 'analises', type_='foreignkey') - op.drop_column('analises', 'group') - op.create_table('flasklogin-users', - sa.Column('id', sa.INTEGER(), nullable=False), - sa.Column('name', sa.VARCHAR(length=100), nullable=False), - sa.Column('email', sa.VARCHAR(length=40), nullable=False), - sa.Column('password', sa.VARCHAR(length=200), nullable=False), - sa.Column('created_on', sa.DATETIME(), nullable=True), - sa.Column('last_login', sa.DATETIME(), nullable=True), - sa.PrimaryKeyConstraint('id'), - sa.UniqueConstraint('email') - ) - op.drop_table('analises_group') - op.drop_table('users') - # ### end Alembic commands ### diff --git a/migrations/versions/619207295bd8_.py b/migrations/versions/619207295bd8_.py deleted file mode 100644 index 938151c..0000000 --- a/migrations/versions/619207295bd8_.py +++ /dev/null @@ -1,34 +0,0 @@ -"""empty message - -Revision ID: 619207295bd8 -Revises: 0b2f74965b1c -Create Date: 2022-09-04 14:28:27.289857 - -""" -from alembic import op -import sqlalchemy as sa - - -# revision identifiers, used by Alembic. -revision = '619207295bd8' -down_revision = '0b2f74965b1c' -branch_labels = None -depends_on = None - - -def upgrade(): - # ### commands auto generated by Alembic - please adjust! ### - op.drop_column('analises', 'friends') - op.drop_column('analises', 'sentiment') - op.drop_column('analises', 'network') - op.drop_column('analises', 'temporal') - # ### end Alembic commands ### - - -def downgrade(): - # ### commands auto generated by Alembic - please adjust! ### - op.add_column('analises', sa.Column('temporal', sa.VARCHAR(length=120), nullable=True)) - op.add_column('analises', sa.Column('network', sa.VARCHAR(length=120), nullable=True)) - op.add_column('analises', sa.Column('sentiment', sa.VARCHAR(length=120), nullable=True)) - op.add_column('analises', sa.Column('friends', sa.VARCHAR(length=120), nullable=True)) - # ### end Alembic commands ### diff --git a/migrations/versions/6b9a6d061aa9_.py b/migrations/versions/6b9a6d061aa9_.py deleted file mode 100644 index f196d40..0000000 --- a/migrations/versions/6b9a6d061aa9_.py +++ /dev/null @@ -1,67 +0,0 @@ -"""empty message - -Revision ID: 6b9a6d061aa9 -Revises: -Create Date: 2021-10-14 12:51:14.745000 - -""" -from alembic import op -import sqlalchemy as sa - - -# revision identifiers, used by Alembic. -revision = '6b9a6d061aa9' -down_revision = None -branch_labels = None -depends_on = None - - -def upgrade(): - # ### commands auto generated by Alembic - please adjust! ### - op.create_table('analises', - sa.Column('id', sa.Integer(), nullable=False), - sa.Column('handle', sa.String(length=80), nullable=False), - sa.Column('total', sa.String(length=120), nullable=True), - sa.Column('network', sa.String(length=120), nullable=True), - sa.Column('sentiment', sa.String(length=120), nullable=True), - sa.Column('friends', sa.String(length=120), nullable=True), - sa.Column('temporal', sa.String(length=120), nullable=True), - sa.Column('twitter_id', sa.String(length=120), nullable=True), - sa.Column('twitter_handle', sa.String(length=120), nullable=True), - sa.Column('twitter_user_name', sa.String(length=120), nullable=True), - sa.Column('twitter_is_protected', sa.Boolean(), nullable=True), - sa.Column('twitter_user_description', sa.String(length=255), nullable=True), - sa.Column('twitter_followers_count', sa.Integer(), nullable=True), - sa.Column('twitter_friends_count', sa.Integer(), nullable=True), - sa.Column('twitter_location', sa.String(length=120), nullable=True), - sa.Column('twitter_created_at', sa.TIMESTAMP(timezone=120), nullable=True), - sa.Column('twitter_is_verified', sa.Boolean(create_constraint=120), nullable=True), - sa.Column('twitter_lang', sa.TIMESTAMP(timezone=120), nullable=True), - sa.Column('twitter_default_profile', sa.String(length=255), nullable=True), - sa.Column('twitter_profile_image', sa.String(length=255), nullable=True), - sa.Column('twitter_withheld_in_countries', sa.String(length=255), nullable=True), - sa.Column('cache_times_served', sa.Integer(), nullable=True), - sa.Column('cache_validity', sa.TIMESTAMP(), nullable=True), - sa.PrimaryKeyConstraint('id') - ) - op.create_table('feedbacks', - sa.Column('id', sa.Integer(), nullable=False), - sa.Column('analisis_id', sa.String(length=80), nullable=False), - sa.Column('feedback', sa.BOOLEAN(), nullable=False), - sa.PrimaryKeyConstraint('id') - ) - op.create_table('relatorios', - sa.Column('id', sa.Integer(), nullable=False), - sa.Column('report_name', sa.String(), nullable=False), - sa.Column('analise_id', sa.String(length=80), nullable=False), - sa.PrimaryKeyConstraint('id') - ) - # ### end Alembic commands ### - - -def downgrade(): - # ### commands auto generated by Alembic - please adjust! ### - op.drop_table('relatorios') - op.drop_table('feedbacks') - op.drop_table('analises') - # ### end Alembic commands ### diff --git a/migrations/versions/6c7352e536fe_.py b/migrations/versions/6c7352e536fe_.py deleted file mode 100644 index 3307012..0000000 --- a/migrations/versions/6c7352e536fe_.py +++ /dev/null @@ -1,30 +0,0 @@ -"""empty message - -Revision ID: 6c7352e536fe -Revises: cc5846eb4bde -Create Date: 2021-10-14 14:13:23.707627 - -""" -from alembic import op -import sqlalchemy as sa - - -# revision identifiers, used by Alembic. -revision = '6c7352e536fe' -down_revision = 'cc5846eb4bde' -branch_labels = None -depends_on = None - - -def upgrade(): - # ### commands auto generated by Alembic - please adjust! ### - op.add_column('analises', sa.Column('created_at', sa.DateTime(), nullable=True)) - op.add_column('analises', sa.Column('updated_at', sa.DateTime(), nullable=True)) - # ### end Alembic commands ### - - -def downgrade(): - # ### commands auto generated by Alembic - please adjust! ### - op.drop_column('analises', 'updated_at') - op.drop_column('analises', 'created_at') - # ### end Alembic commands ### diff --git a/migrations/versions/cc5846eb4bde_.py b/migrations/versions/cc5846eb4bde_.py deleted file mode 100644 index acfc757..0000000 --- a/migrations/versions/cc5846eb4bde_.py +++ /dev/null @@ -1,28 +0,0 @@ -"""empty message - -Revision ID: cc5846eb4bde -Revises: 6b9a6d061aa9 -Create Date: 2021-10-14 12:54:24.662955 - -""" -from alembic import op -import sqlalchemy as sa - - -# revision identifiers, used by Alembic. -revision = 'cc5846eb4bde' -down_revision = '6b9a6d061aa9' -branch_labels = None -depends_on = None - - -def upgrade(): - # ### commands auto generated by Alembic - please adjust! ### - op.add_column('analises', sa.Column('pegabot_version', sa.String(length=255), nullable=True)) - # ### end Alembic commands ### - - -def downgrade(): - # ### commands auto generated by Alembic - please adjust! ### - op.drop_column('analises', 'pegabot_version') - # ### end Alembic commands ### From 4ccfe20e8f7721cd11ba2c86af0a6dfbf939800c Mon Sep 17 00:00:00 2001 From: williamneto Date: Sun, 4 Sep 2022 19:04:31 -0300 Subject: [PATCH 13/14] Ajuste no template de login --- app/routes/auth/templates/login.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/routes/auth/templates/login.html b/app/routes/auth/templates/login.html index 257c5a2..c8d4406 100644 --- a/app/routes/auth/templates/login.html +++ b/app/routes/auth/templates/login.html @@ -29,7 +29,7 @@

Log In

{{ form.password.label }} {{ form.password }} - {% if form.email.errors %} + {% if form.password.errors %}