Рефракторинг

This commit is contained in:
2020-05-26 22:18:28 +03:00
parent 504e8b6a6b
commit 4a882f0062
7 changed files with 231 additions and 187 deletions

View File

@@ -1,140 +0,0 @@
import hashlib
import os
from re import match
from flask import render_template, request, redirect, url_for
from flask_login import LoginManager, login_user, login_required, logout_user, current_user
import db_routing
from db_init import db_fill
from db_routing import app, db
from scenario_manager import Executor
login_manager = LoginManager(app)
@login_manager.user_loader
def load_user(user_id):
return db_routing.get_user(id=user_id)
@app.route('/', methods=['GET'])
def index():
return render_template('index.html')
@app.route('/registration', methods=['GET', 'POST'])
def registration():
if current_user.is_authenticated:
return redirect(url_for('universal_error'))
if request.method == 'POST':
userName = request.form['RegUserLogin']
userPassw = request.form['RegUserPassw']
if string_check(userName) and string_check(userPassw):
if db_routing.add_user(userName, passw_hash(userPassw)):
login_user(db_routing.get_user(username=userName))
return redirect(url_for('workshop'))
return render_template('registration.html')
@app.route('/login', methods=['POST'])
def login():
userName = request.form['LogUserLogin']
userPassw = request.form['LogUserPassw']
if string_check(userName) and string_check(userPassw):
user = verify_password(userName, userPassw)
if user:
login_user(user)
return redirect(url_for('workshop'))
else:
return redirect(url_for('registration'))
else:
return redirect(url_for('registration'))
@app.route('/logout')
def logout():
logout_user()
return redirect(url_for('index'))
@app.route('/workshop', methods=['GET', 'POST'])
@login_required
def workshop():
if request.method == 'POST':
if 'NewScenarioName' in request.form:
newScenarioName = request.form['NewScenarioName']
triggerID = request.form['TriggerID']
triggerArgs = request.form['TriggerArgs']
actionID = request.form['ActionID']
actionArgs = request.form['ActionArgs']
new_scenario = db_routing.add_scenario(current_user.get_id(), newScenarioName, triggerID, triggerArgs,
actionID,
actionArgs)
activeScenario = Executor(new_scenario, current_user.get_tg_id())
activeScenario.start()
return redirect(url_for('workshop'))
if 'TGID' in request.form:
new_tg_id = request.form['TGID']
db_routing.tg_id_update(current_user.get_id(), new_tg_id)
return redirect(url_for('workshop'))
if 'ScenarioID' in request.form:
scnarioID = request.form['ScenarioID']
db_routing.delete_scenario(scnarioID)
return redirect(url_for('workshop'))
triggers_list = db_routing.get_trigers()
actions_list = db_routing.get_actions()
user_scripts_list = db_routing.get_user_scripts(current_user.get_id())
User = db_routing.get_user(id=current_user.get_id())
if User:
tg_id = User.tg_id
else:
tg_id = None
return render_template('workshop.html', triggers_list=triggers_list, actions_list=actions_list,
user_scripts_list=user_scripts_list, tg_id=tg_id)
@app.errorhandler(Exception)
def universal_error(error):
return render_template('error.html'), 404
def string_check(string):
if 2 < len(string) < 7:
if match('^[0-9A-Za-z]*$', string) and not ('\\' in string):
return True
else:
print(
'Некорректный ввод! Строка должно включать только английские буквы или цифры. Содержать не менее 3 и не '
'более 6 символов')
return False
def passw_hash(user_passw, salt=os.urandom(32)):
key = hashlib.pbkdf2_hmac('sha256', user_passw.encode('utf-8'), salt, 100000)
storage = salt + key
# salt_from_storage = storage[:32] # 32 длина соли
# key_from_storage = storage[32:]
return storage
def verify_password(username, password):
User = db_routing.get_user(username=username)
if User:
userSalt = User.password[:32]
if passw_hash(password, userSalt) == User.password:
return User
else:
print('Неверный пароль')
return False
if __name__ == '__main__':
if not os.path.exists('./data.db'):
db.create_all()
db_fill()
app.run()

View File

@@ -11,20 +11,21 @@ def test_action(var, tg_id):
# Ответ на письмо # Ответ на письмо
# формат строки (логин#пароль#адресат#текст) # формат строки (логин#пароль#адресат#текст)
# send_mail_config='login@gmail.com#Password123#myfriend@gmail.com#Текст сообщения' # send_mail_config=
# 'login@gmail.com#Password123#myfriend@gmail.com#Текст сообщения'
def send_mail(send_mail_config, tg_id): def send_mail(send_mail_config, tg_id):
send_mail_list = send_mail_config.split('#') send_mail_list = send_mail_config.split("#")
mail_sender = send_mail_list[0] # отправитель mail_sender = send_mail_list[0] # отправитель
mail_receiver = send_mail_list[2] # адресат mail_receiver = send_mail_list[2] # адресат
username = send_mail_list[0] # имя пользователя username = send_mail_list[0] # имя пользователя
password = send_mail_list[1] # пароль от почты password = send_mail_list[1] # пароль от почты
server = smtplib.SMTP('smtp.gmail.com:587') server = smtplib.SMTP("smtp.gmail.com:587")
# Формируем тело письма # Формируем тело письма
subject = u'J.a.r.v.i.s.' subject = u"J.a.r.v.i.s."
body = send_mail_list[3] body = send_mail_list[3]
msg = MIMEText(body, 'plain', 'utf-8') msg = MIMEText(body, "plain", "utf-8")
msg['Subject'] = Header(subject, 'utf-8') msg["Subject"] = Header(subject, "utf-8")
# Отправляем письмо # Отправляем письмо
server.starttls() server.starttls()

View File

@@ -2,10 +2,10 @@ from db_routing import add_trigger, add_action
def db_fill(): def db_fill():
add_trigger('Тест', 'test_trigger') add_trigger("Тест", "test_trigger")
add_trigger('Будильник', 'alarm_clock') add_trigger("Будильник", "alarm_clock")
add_trigger('Проверить почту', 'check_email') add_trigger("Проверить почту", "check_email")
add_action('Тест', 'test_action') add_action("Тест", "test_action")
add_action('Отправить письмо', 'send_mail') add_action("Отправить письмо", "send_mail")
add_action('Отправить сообщение в ТГ', 'send_message_tg') add_action("Отправить сообщение в ТГ", "send_message_tg")

View File

@@ -2,14 +2,14 @@ from flask import Flask
from flask_sqlalchemy import SQLAlchemy from flask_sqlalchemy import SQLAlchemy
from sqlalchemy import ForeignKey from sqlalchemy import ForeignKey
app = Flask('Jarvis', static_folder='static', template_folder='templates') app = Flask("Jarvis", static_folder="static", template_folder="templates")
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///data.db' app.config["SQLALCHEMY_DATABASE_URI"] = "sqlite:///data.db"
app.config['SECRET_KEY'] = 'Radius' app.config["SECRET_KEY"] = "Radius"
db = SQLAlchemy(app) db = SQLAlchemy(app)
class User(db.Model): class User(db.Model):
__tablename__ = 'Users' __tablename__ = "Users"
id = db.Column(db.Integer, primary_key=True) id = db.Column(db.Integer, primary_key=True)
username = db.Column(db.String(80), unique=True, nullable=False) username = db.Column(db.String(80), unique=True, nullable=False)
password = db.Column(db.String(120), nullable=False) password = db.Column(db.String(120), nullable=False)
@@ -34,27 +34,27 @@ class User(db.Model):
class Trigger(db.Model): class Trigger(db.Model):
__tablename__ = 'Triggers' __tablename__ = "Triggers"
id = db.Column(db.Integer, primary_key=True) id = db.Column(db.Integer, primary_key=True)
name = db.Column(db.String(80), unique=True, nullable=False) name = db.Column(db.String(80), unique=True, nullable=False)
def_name = db.Column(db.String(200)) def_name = db.Column(db.String(200))
class Action(db.Model): class Action(db.Model):
__tablename__ = 'Actions' __tablename__ = "Actions"
id = db.Column(db.Integer, primary_key=True) id = db.Column(db.Integer, primary_key=True)
name = db.Column(db.String(80), unique=True, nullable=False) name = db.Column(db.String(80), unique=True, nullable=False)
def_name = db.Column(db.String(200)) def_name = db.Column(db.String(200))
class Scenario(db.Model): class Scenario(db.Model):
__tablename__ = 'Scenarios' __tablename__ = "Scenarios"
id = db.Column(db.Integer, primary_key=True) id = db.Column(db.Integer, primary_key=True)
owner_id = db.Column(db.Integer, ForeignKey('Users.id')) owner_id = db.Column(db.Integer, ForeignKey("Users.id"))
scenario_name = db.Column(db.String(80), nullable=False) scenario_name = db.Column(db.String(80), nullable=False)
trigger_id = db.Column(db.Integer, ForeignKey('Triggers.id')) trigger_id = db.Column(db.Integer, ForeignKey("Triggers.id"))
trigger_args = db.Column(db.String(200)) trigger_args = db.Column(db.String(200))
action_id = db.Column(db.Integer, ForeignKey('Actions.id')) action_id = db.Column(db.Integer, ForeignKey("Actions.id"))
action_args = db.Column(db.String(200)) action_args = db.Column(db.String(200))
@@ -65,7 +65,7 @@ def add_user(user_name, passw_hash):
db.session.commit() db.session.commit()
return new_user return new_user
else: else:
print('Логин занят') print("Логин занят")
return False return False
@@ -83,9 +83,17 @@ def add_action(name, def_name):
return new_action return new_action
def add_scenario(owner_id, scenario_name, trigger_id, trigger_args, action_id, action_args): def add_scenario(
new_scenario = Scenario(owner_id=owner_id, scenario_name=scenario_name, trigger_id=trigger_id, owner_id, scenario_name, trigger_id, trigger_args, action_id, action_args
trigger_args=trigger_args, action_id=action_id, action_args=action_args) ):
new_scenario = Scenario(
owner_id=owner_id,
scenario_name=scenario_name,
trigger_id=trigger_id,
trigger_args=trigger_args,
action_id=action_id,
action_args=action_args,
)
db.session.add(new_scenario) db.session.add(new_scenario)
db.session.commit() db.session.commit()
return new_scenario return new_scenario
@@ -117,7 +125,9 @@ def get_actions(id=None):
def get_user_scripts(current_user_id): def get_user_scripts(current_user_id):
user_scripts_list = Scenario.query.filter_by(owner_id=current_user_id).all() user_scripts_list = Scenario.query.filter_by(
owner_id=current_user_id
).all()
return user_scripts_list return user_scripts_list

159
jarvis.py Normal file
View File

@@ -0,0 +1,159 @@
import hashlib
import os
from re import match
from flask import render_template, request, redirect, url_for
from flask_login import (
LoginManager,
login_user,
login_required,
logout_user,
current_user,
)
import db_routing
from db_init import db_fill
from db_routing import app, db
from scenario_manager import Executor
login_manager = LoginManager(app)
@login_manager.user_loader
def load_user(user_id):
return db_routing.get_user(id=user_id)
@app.route("/", methods=["GET"])
def index():
return render_template("index.html")
@app.route("/registration", methods=["GET", "POST"])
def registration():
if current_user.is_authenticated:
return redirect(url_for("universal_error"))
if request.method == "POST":
userName = request.form["RegUserLogin"]
userPassw = request.form["RegUserPassw"]
if string_check(userName) and string_check(userPassw):
if db_routing.add_user(userName, passw_hash(userPassw)):
login_user(db_routing.get_user(username=userName))
return redirect(url_for("workshop"))
return render_template("registration.html")
@app.route("/login", methods=["POST"])
def login():
userName = request.form["LogUserLogin"]
userPassw = request.form["LogUserPassw"]
if string_check(userName) and string_check(userPassw):
user = verify_password(userName, userPassw)
if user:
login_user(user)
return redirect(url_for("workshop"))
else:
return redirect(url_for("registration"))
else:
return redirect(url_for("registration"))
@app.route("/logout")
def logout():
logout_user()
return redirect(url_for("index"))
@app.route("/workshop", methods=["GET", "POST"])
@login_required
def workshop():
if request.method == "POST":
if "NewScenarioName" in request.form:
newScenarioName = request.form["NewScenarioName"]
triggerID = request.form["TriggerID"]
triggerArgs = request.form["TriggerArgs"]
actionID = request.form["ActionID"]
actionArgs = request.form["ActionArgs"]
new_scenario = db_routing.add_scenario(
current_user.get_id(),
newScenarioName,
triggerID,
triggerArgs,
actionID,
actionArgs,
)
activeScenario = Executor(new_scenario, current_user.get_tg_id())
activeScenario.start()
return redirect(url_for("workshop"))
if "TGID" in request.form:
new_tg_id = request.form["TGID"]
db_routing.tg_id_update(current_user.get_id(), new_tg_id)
return redirect(url_for("workshop"))
if "ScenarioID" in request.form:
scnarioID = request.form["ScenarioID"]
db_routing.delete_scenario(scnarioID)
return redirect(url_for("workshop"))
triggers_list = db_routing.get_trigers()
actions_list = db_routing.get_actions()
user_scripts_list = db_routing.get_user_scripts(current_user.get_id())
User = db_routing.get_user(id=current_user.get_id())
if User:
tg_id = User.tg_id
else:
tg_id = None
return render_template(
"workshop.html",
triggers_list=triggers_list,
actions_list=actions_list,
user_scripts_list=user_scripts_list,
tg_id=tg_id,
)
@app.errorhandler(Exception)
def universal_error(error):
return render_template("error.html"), 404
def string_check(string):
if 2 < len(string) < 7:
if match("^[0-9A-Za-z]*$", string) and not ("\\" in string):
return True
else:
print(
"Некорректный ввод! Строка должно включать только английские буквы"
" или цифры. Содержать не менее 3 и не более 6 символов"
)
return False
def passw_hash(user_passw, salt=os.urandom(32)):
key = hashlib.pbkdf2_hmac(
"sha256", user_passw.encode("utf-8"), salt, 100000
)
storage = salt + key
# salt_from_storage = storage[:32] # 32 длина соли
# key_from_storage = storage[32:]
return storage
def verify_password(username, password):
User = db_routing.get_user(username=username)
if User:
userSalt = User.password[:32]
if passw_hash(password, userSalt) == User.password:
return User
else:
print("Неверный пароль")
return False
if __name__ == "__main__":
if not os.path.exists("./data.db"):
db.create_all()
db_fill()
app.run()

View File

@@ -1,18 +1,22 @@
import telebot import telebot
botToken = '' botToken = ""
bot = telebot.TeleBot(botToken) bot = telebot.TeleBot(botToken)
# telebot.apihelper.proxy = {'Socks5': '247398282:247398282@orbtl.s5.opennetwork.cc:999'} # - прокси, если нужен в # telebot.apihelper.proxy = {}
# прокси, если нужен, в
# формате {'https': 'login:password@address:port'} # формате {'https': 'login:password@address:port'}
@bot.message_handler(commands=['start']) # Реакция на команду start @bot.message_handler(commands=["start"]) # Реакция на команду start
def start_message(message): def start_message(message):
bot.send_message(message.chat.id, bot.send_message(
'Добро пожаловать в Jarvis!\nЭто помощник, сценарии поведения которого настраиваются через ' message.chat.id,
'web-приложение на Flask\n') "Добро пожаловать в Jarvis!\n"
"Это помощник, сценарии поведения которого настраиваются через ",
"web-приложение на Flask\n",
)
def send_message(user_id, text): def send_message(user_id, text):

View File

@@ -12,41 +12,51 @@ def test_trigger(var, tg_id):
# Формат строки (год месяц день час минута секунда) # Формат строки (год месяц день час минута секунда)
# Config_time='2020#3#22#15#20#0' # Config_time='2020#3#22#15#20#0'
def alarm_clock(config_time, tg_id): def alarm_clock(config_time, tg_id):
config_list = config_time.split('#') config_list = config_time.split("#")
dt = datetime.datetime(int(config_list[0]), int(config_list[1]), int(config_list[2]), int(config_list[3]), dt = datetime.datetime(
int(config_list[0]),
int(config_list[1]),
int(config_list[2]),
int(config_list[3]),
int(config_list[4]), int(config_list[4]),
int(config_list[5])) int(config_list[5]),
)
diff = (dt - datetime.datetime.now()).total_seconds() diff = (dt - datetime.datetime.now()).total_seconds()
try: try:
time.sleep(diff) time.sleep(diff)
except: except Exception:
print('Нельзя поставить будильник в прошлое') print("Нельзя поставить будильник в прошлое")
return return
# проверка почты на новое письмо gmail # проверка почты на новое письмо gmail
# Нужно включить https://myaccount.google.com/lesssecureapps и https://mail.google.com/mail/u/2/#settings/fwdandpop # Нужно включить https://myaccount.google.com/lesssecureapps и
# https://mail.google.com/mail/u/2/#settings/fwdandpop
# Формат строки (логин#пароль) # Формат строки (логин#пароль)
# check_mail_config='login@gmail.com Password123' # check_mail_config='login@gmail.com Password123'
def check_email(check_mail_config, tg_id): def check_email(check_mail_config, tg_id):
mail_config_list = check_mail_config.split('#') mail_config_list = check_mail_config.split("#")
mail = imaplib.IMAP4_SSL('imap.gmail.com', 993) mail = imaplib.IMAP4_SSL("imap.gmail.com", 993)
mail.login(mail_config_list[0], mail_config_list[1]) mail.login(mail_config_list[0], mail_config_list[1])
mail.list() mail.list()
count_Email_Start = (mail.select("inbox")[1][0]).decode('utf-8') count_Email_Start = (mail.select("inbox")[1][0]).decode("utf-8")
while True: while True:
mail.list() mail.list()
count_Email_Current = (mail.select("inbox")[1][0]).decode('utf-8') count_Email_Current = (mail.select("inbox")[1][0]).decode("utf-8")
if count_Email_Current > count_Email_Start: if count_Email_Current > count_Email_Start:
result, data = mail.search(None, "ALL") result, data = mail.search(None, "ALL")
ids = data[0] # Получаем сроку номеров писем ids = data[0] # Получаем сроку номеров писем
id_list = ids.split() # Разделяем ID писем id_list = ids.split() # Разделяем ID писем
latest_email_id = id_list[-1] # Берем последний ID latest_email_id = id_list[-1] # Берем последний ID
result, data = mail.fetch(latest_email_id, "(RFC822)") # Получаем тело письма (RFC822) для данного ID result, data = mail.fetch(
latest_email_id, "(RFC822)"
) # Получаем тело письма (RFC822) для данного ID
raw_email = data[0][1] raw_email = data[0][1]
email_message = email.message_from_bytes(raw_email) email_message = email.message_from_bytes(raw_email)
email_message_From = email_message['From'] email_message_From = email_message["From"]
email_message_From = email_message_From[email_message_From.index('<'):email_message_From.index('>')] email_message_From = email_message_From[
email_message_From.index("<") : email_message_From.index(">")
]
email_message_From = email_message_From[1:] email_message_From = email_message_From[1:]
return return
# count_Email_Start = count_Email_Current # count_Email_Start = count_Email_Current